Esempio n. 1
0
/**
 * @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
}
Esempio n. 2
0
/**
 *
 * @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);
}
Esempio n. 5
0
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
}
Esempio n. 6
0
/**
 *
 * @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);        
}