Example #1
0
/**
 *
 * @brief Initialize the tickless idle feature
 *
 * This routine initializes the tickless idle feature by calculating the
 * necessary hardware-specific parameters.
 *
 * Note that the maximum number of ticks that can elapse during a "tickless idle"
 * is limited by <default_load_value>.  The larger the value (the lower the
 * tick frequency), the fewer elapsed ticks during a "tickless idle".
 * Conversely, the smaller the value (the higher the tick frequency), the
 * more elapsed ticks during a "tickless idle".
 *
 * @return N/A
 */
static void sysTickTicklessIdleInit(void)
{
	/* enable counter, disable interrupt and set clock src to system clock
	 */
	u32_t ctrl = SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_CLKSOURCE_Msk;

	volatile u32_t dummy; /* used to help determine the 'skew time' */

	/* store the default reload value (which has already been set) */
	default_load_value = sysTickReloadGet();

	/* calculate the max number of ticks with this 24-bit H/W counter */
	max_system_ticks = 0x00ffffff / default_load_value;

	/* determine the associated load value */
	max_load_value = max_system_ticks * default_load_value;

	/*
	 * Calculate the skew from switching the timer in and out of idle mode.
	 * The following sequence is emulated:
	 *    1. Stop the timer.
	 *    2. Read the current counter value.
	 *    3. Calculate the new/remaining counter reload value.
	 *    4. Load the new counter value.
	 *    5. Set the timer mode to periodic/one-shot.
	 *    6. Start the timer.
	 *
	 * The timer must be running for this to work, so enable the
	 * systick counter without generating interrupts, using the processor
	 *clock.
	 * Note that the reload value has already been set by the caller.
	 */

	SysTick->CTRL |= ctrl;
	__ISB();

	timer_idle_skew = sysTickCurrentGet(); /* start of skew time */

	SysTick->CTRL |= ctrl; /* normally sysTickStop() */

	dummy = sysTickCurrentGet(); /* emulate sysTickReloadSet() */

	/* emulate calculation of the new counter reload value */
	if ((dummy == 1) || (dummy == default_load_value)) {
		dummy = max_system_ticks - 1;
		dummy += max_load_value - default_load_value;
	} else {
		dummy = dummy - 1;
		dummy += dummy * default_load_value;
	}

	/* _sysTickStart() without interrupts */
	SysTick->CTRL |= ctrl;

	timer_mode = TIMER_MODE_PERIODIC;

	/* skew time calculation for down counter (assumes no rollover) */
	timer_idle_skew -= sysTickCurrentGet();

	/* restore the previous sysTick state */
	sysTickStop();
	sysTickReloadSet(default_load_value);
#ifdef CONFIG_TICKLESS_KERNEL
	idle_original_ticks = 0;
#endif
}
Example #2
0
/**
 *
 * @brief Initialize the tickless idle feature
 *
 * This routine initializes the tickless idle feature by calculating the
 * necessary hardware-specific parameters.
 *
 * Note that the maximum number of ticks that can elapse during a "tickless idle"
 * is limited by <default_load_value>.  The larger the value (the lower the
 * tick frequency), the fewer elapsed ticks during a "tickless idle".
 * Conversely, the smaller the value (the higher the tick frequency), the
 * more elapsed ticks during a "tickless idle".
 *
 * @return N/A
 */
static void sysTickTicklessIdleInit(void)
{
	/* enable counter, disable interrupt and set clock src to system clock
	 */
	union __stcsr stcsr = {.bit = {1, 0, 1, 0, 0, 0} };

	volatile uint32_t dummy; /* used to help determine the 'skew time' */

	/* store the default reload value (which has already been set) */
	default_load_value = sysTickReloadGet();

	/* calculate the max number of ticks with this 24-bit H/W counter */
	max_system_ticks = 0x00ffffff / default_load_value;

	/* determine the associated load value */
	max_load_value = max_system_ticks * default_load_value;

	/*
	 * Calculate the skew from switching the timer in and out of idle mode.
	 * The following sequence is emulated:
	 *    1. Stop the timer.
	 *    2. Read the current counter value.
	 *    3. Calculate the new/remaining counter reload value.
	 *    4. Load the new counter value.
	 *    5. Set the timer mode to periodic/one-shot.
	 *    6. Start the timer.
	 *
	 * The timer must be running for this to work, so enable the
	 * systick counter without generating interrupts, using the processor
	 *clock.
	 * Note that the reload value has already been set by the caller.
	 */

	__scs.systick.stcsr.val |= stcsr.val;
	__asm__(" isb"); /* ensure the timer is started before reading */

	timer_idle_skew = sysTickCurrentGet(); /* start of skew time */

	__scs.systick.stcsr.val |= stcsr.val; /* normally sysTickStop() */

	dummy = sysTickCurrentGet(); /* emulate sysTickReloadSet() */

	/* emulate calculation of the new counter reload value */
	if ((dummy == 1) || (dummy == default_load_value)) {
		dummy = max_system_ticks - 1;
		dummy += max_load_value - default_load_value;
	} else {
		dummy = dummy - 1;
		dummy += dummy * default_load_value;
	}

	/* _sysTickStart() without interrupts */
	__scs.systick.stcsr.val |= stcsr.val;

	timer_mode = TIMER_MODE_PERIODIC;

	/* skew time calculation for down counter (assumes no rollover) */
	timer_idle_skew -= sysTickCurrentGet();

	/* restore the previous sysTick state */
	sysTickStop();
	sysTickReloadSet(default_load_value);
}