/** * @brief Place system timer into idle state. * * Re-program the timer to enter into the idle state for the given number of * sys ticks, counted from the previous sys tick. The timer will fire in the * number of sys ticks supplied or the maximum number of sys ticks (converted * to RTC ticks) that can be programmed into the hardware. * * This will only be called from idle context, with IRQs disabled. * * A value of -1 will result in the maximum number of sys ticks. * * Example 1: Idle sleep is entered: * * sys tick timeline: (1) (2) (3) (4) (5) (6) * rtc tick timeline : 0----100----200----300----400----500----600 * ****************** * 150 * * a) The last sys tick was announced at 100 * b) The idle context enters sleep at 150, between sys tick 1 and 2, with * sys_ticks = 3. * c) The RTC is programmed to fire at sys tick 1 + 3 = 4 (RTC tick 400) * * @return N/A */ void _timer_idle_enter(s32_t sys_ticks) { #ifdef CONFIG_TICKLESS_KERNEL if (sys_ticks != K_FOREVER) { /* Need to reprograme timer if current program is smaller*/ if (sys_ticks > expected_sys_ticks) { _set_time(sys_ticks); } } else { expected_sys_ticks = 0; /* Set time to largest possile RTC Tick*/ _set_time(_get_max_clock_time()); } #else /* Restrict ticks to max supported by RTC without risking overflow*/ if ((sys_ticks < 0) || (sys_ticks > (RTC_HALF / sys_clock_hw_cycles_per_tick))) { sys_ticks = RTC_HALF / sys_clock_hw_cycles_per_tick; } expected_sys_ticks = sys_ticks; /* If ticks is 0, the RTC interrupt handler will be set pending * immediately, meaning that we will not go to sleep. */ rtc_compare_set(rtc_past + (sys_ticks * sys_clock_hw_cycles_per_tick)); #endif }
/** * * @brief Place the system timer into idle state * * Re-program the timer to enter into the idle state for the given number of * ticks. It is set to a "one shot" mode where it will fire in the number of * ticks supplied or the maximum number of ticks that can be programmed into * hardware. A value of -1 will result in the maximum number of ticks. * * @return N/A */ void _timer_idle_enter(s32_t ticks /* system ticks */ ) { #ifdef CONFIG_TICKLESS_KERNEL if (ticks != K_FOREVER) { /* Need to reprogram only if current program is smaller */ if (ticks > idle_original_ticks) { _set_time(ticks); } } else { sysTickStop(); idle_original_ticks = 0; } idle_mode = IDLE_TICKLESS; #else sysTickStop(); /* * We're being asked to have the timer fire in "ticks" from now. To * maintain accuracy we must account for the remaining time left in the * timer. So we read the count out of it and add it to the requested * time out */ idle_original_count = sysTickCurrentGet() - timer_idle_skew; if ((ticks == -1) || (ticks > max_system_ticks)) { /* * We've been asked to fire the timer so far in the future that * the required count value would not fit in the 24-bit reload * register. * Instead, we program for the maximum programmable interval * minus one system tick to prevent overflow when the left over * count read earlier is added. */ idle_original_count += max_load_value - default_load_value; idle_original_ticks = max_system_ticks - 1; } else { /* * leave one tick of buffer to have to time react when coming * back */ idle_original_ticks = ticks - 1; idle_original_count += idle_original_ticks * default_load_value; } /* * Set timer to virtual "one shot" mode - sysTick does not have multiple * modes, so the reload value is simply changed. */ timer_mode = TIMER_MODE_ONE_SHOT; idle_mode = IDLE_TICKLESS; sysTickReloadSet(idle_original_count); sysTickStart(); #endif }
gboolean gsd_datetime_mechanism_set_time (GsdDatetimeMechanism *mechanism, gint64 seconds_since_epoch, DBusGMethodInvocation *context) { struct timeval tv; reset_killtimer (); g_debug ("SetTime(%" G_GINT64_FORMAT ") called", seconds_since_epoch); tv.tv_sec = (time_t) seconds_since_epoch; tv.tv_usec = 0; return _set_time (mechanism, &tv, context); }
gboolean gnome_clock_applet_mechanism_set_time (GnomeClockAppletMechanism *mechanism, gint64 seconds_since_epoch, DBusGMethodInvocation *context) { struct timeval tv; reset_killtimer (); g_debug ("SetTime(%lld) called", seconds_since_epoch); tv.tv_sec = (time_t) seconds_since_epoch; tv.tv_usec = 0; return _set_time (mechanism, &tv, context); }
void _timer_idle_enter(s32_t ticks) { #ifdef CONFIG_TICKLESS_KERNEL if (ticks != K_FOREVER) { /* Need to reprogram only if current program is smaller */ if (ticks > programmed_ticks) { _set_time(ticks); } } else { programmed_ticks = 0; timer0_control_register_set(timer0_control_register_get() & ~_ARC_V2_TMR_CTRL_IE); } #else u32_t status; if ((ticks == K_FOREVER) || (ticks > max_system_ticks)) { /* * The number of cycles until the timer must fire next might not fit * in the 32-bit counter register. To work around this, program * the counter to fire in the maximum number of ticks. */ ticks = max_system_ticks; } programmed_ticks = ticks; programmed_limit = (programmed_ticks * cycles_per_tick) - 1; timer0_limit_register_set(programmed_limit); /* * If Timer0's IP bit is set, then it is known that we have straddled * a tick boundary while entering tickless idle. */ status = timer0_control_register_get(); if (status & _ARC_V2_TMR_CTRL_IP) { straddled_tick_on_idle_enter = 1; } __ASSERT_EVAL({}, u32_t timer_count = timer0_count_register_get(), timer_count <= programmed_limit, "timer_count: %d, limit %d\n", timer_count, programmed_limit); #endif }
/** * * @brief Handling of tickless idle when interrupted * * The function will be called by _sys_power_save_idle_exit(), called from * _arch_isr_direct_pm() for 'direct' interrupts, or from _isr_wrapper for * regular ones, which is called on every IRQ handler if the device was * idle, and optionally called when a 'direct' IRQ handler executes if the * device was idle. * * Example 1: Idle sleep is interrupted before time: * * sys tick timeline: (1) (2) (3) (4) (5) (6) * rtc tick timeline : 0----100----200----300----400----500----600 * **************!*** * 150 350 * * Assume that _timer_idle_enter() is called at 150 (1) to sleep for 3 * sys ticks. The last sys tick was announced at 100. * * On wakeup (non-RTC IRQ at 350): * * a) Notify how many sys ticks have passed, i.e., 350 - 150 / 100 = 2. * b) Schedule next sys tick at 400. * */ void _timer_idle_exit(void) { #ifdef CONFIG_TICKLESS_KERNEL if (!expected_sys_ticks && _sys_clock_always_on) { _set_time(_get_max_clock_time()); } #else /* Clear the event flag and interrupt in case we woke up on the RTC * interrupt. No need to run the RTC ISR since everything that needs * to run in the ISR will be done in this call. */ RTC_CC_EVENT = 0; NVIC_ClearPendingIRQ(NRF5_IRQ_RTC1_IRQn); rtc_announce_set_next(); /* After exiting idle, the kernel no longer expects more than one sys * ticks to have passed when _sys_clock_tick_announce() is called. */ expected_sys_ticks = 1; #endif }
gboolean gsd_datetime_mechanism_adjust_time (GsdDatetimeMechanism *mechanism, gint64 seconds_to_add, DBusGMethodInvocation *context) { struct timeval tv; reset_killtimer (); g_debug ("AdjustTime(%" G_GINT64_FORMAT " ) called", seconds_to_add); if (gettimeofday (&tv, NULL) != 0) { GError *error; error = g_error_new (GSD_DATETIME_MECHANISM_ERROR, GSD_DATETIME_MECHANISM_ERROR_GENERAL, "Error calling gettimeofday(): %s", strerror (errno)); dbus_g_method_return_error (context, error); g_error_free (error); return FALSE; } tv.tv_sec += (time_t) seconds_to_add; return _set_time (mechanism, &tv, context); }
gboolean gnome_clock_applet_mechanism_adjust_time (GnomeClockAppletMechanism *mechanism, gint64 seconds_to_add, DBusGMethodInvocation *context) { struct timeval tv; reset_killtimer (); g_debug ("AdjustTime(%lld) called", seconds_to_add); if (gettimeofday (&tv, NULL) != 0) { GError *error; error = g_error_new (GNOME_CLOCK_APPLET_MECHANISM_ERROR, GNOME_CLOCK_APPLET_MECHANISM_ERROR_GENERAL, "Error calling gettimeofday(): %s", strerror (errno)); dbus_g_method_return_error (context, error); g_error_free (error); return FALSE; } tv.tv_sec += (time_t) seconds_to_add; return _set_time (mechanism, &tv, context); }