void _enable_sys_clock(void) { if (!(SysTick->CTRL & SysTick_CTRL_ENABLE_Msk)) { sysTickStart(); sys_tick_reload(); } }
int main(int argc,char *argv[]) /* * main function of the shell program, calls process_input(). As process_input() * does all the error reporting and does not propagate errors out of it * and shell program does not have to return any failure exit status * to its parent shell, main() simply retuns 0 */ { //Bootstrap bootstrap(); //flexTimer0Start(); //process input //process_input(); uint32_t pid; struct spawnArgs args; args.argc = 1; args.argv = NULL; args.spawnedPidptr = &pid; args.stackSize = STACK_SIZE; args.funcPtr = runShell; svc_spawn(&args); sysTickStart(); privUnprivileged(); while(1); return 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 }
void _set_time(u32_t time) { if (!time) { idle_original_ticks = 0; return; } idle_original_ticks = time > max_system_ticks ? max_system_ticks : time; _sys_clock_tick_count = _get_elapsed_clock_time(); /* clear overflow tracking flag as it is accounted */ timer_overflow = 0; sysTickStop(); sysTickReloadSet(idle_original_ticks * default_load_value); sysTickStart(); sys_tick_reload(); }
/** * * @brief Handling of tickless idle when interrupted * * The routine, called by _sys_power_save_idle_exit, is responsible for taking * the timer out of idle mode and generating an interrupt at the next * tick interval. It is expected that interrupts have been disabled. * * Note that in this routine, _sys_idle_elapsed_ticks must be zero because the * ticker has done its work and consumed all the ticks. This has to be true * otherwise idle mode wouldn't have been entered in the first place. * * @return N/A */ void _timer_idle_exit(void) { #ifdef CONFIG_TICKLESS_KERNEL if (idle_mode == IDLE_TICKLESS) { idle_mode = IDLE_NOT_TICKLESS; if (!idle_original_ticks && _sys_clock_always_on) { _sys_clock_tick_count = _get_elapsed_clock_time(); timer_overflow = 0; sysTickReloadSet(max_load_value); sysTickStart(); sys_tick_reload(); } } #else u32_t count; /* timer's current count register value */ if (timer_mode == TIMER_MODE_PERIODIC) { /* * The timer interrupt handler is handling a completed tickless * idle or this has been called by mistake; there's nothing to * do here. */ return; } sysTickStop(); /* timer is in idle mode, adjust the ticks expired */ count = sysTickCurrentGet(); if ((count == 0) || (SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk)) { /* * The timer expired and/or wrapped around. Re-set the timer to * its default value and mode. */ sysTickReloadSet(default_load_value); timer_mode = TIMER_MODE_PERIODIC; /* * Announce elapsed ticks to the kernel. Note we are guaranteed * that the timer ISR will execute before the tick event is * serviced, so _sys_idle_elapsed_ticks is adjusted to account * for it. */ _sys_idle_elapsed_ticks = idle_original_ticks - 1; _sys_clock_tick_announce(); } else { u32_t elapsed; /* elapsed "counter time" */ u32_t remaining; /* remaining "counter time" */ elapsed = idle_original_count - count; remaining = elapsed % default_load_value; /* ensure that the timer will interrupt at the next tick */ if (remaining == 0) { /* * Idle was interrupted on a tick boundary. Re-set the * timer to its default value and mode. */ sysTickReloadSet(default_load_value); timer_mode = TIMER_MODE_PERIODIC; } else if (count > remaining) { /* * There is less time remaining to the next tick * boundary than time left for idle. Leave in "one * shot" mode. */ sysTickReloadSet(remaining); } _sys_idle_elapsed_ticks = elapsed / default_load_value; if (_sys_idle_elapsed_ticks) { _sys_clock_tick_announce(); } } idle_mode = IDLE_NOT_TICKLESS; sysTickStart(); #endif }
/** * * @brief System clock tick handler * * This routine handles the system clock tick interrupt. A TICK_EVENT event * is pushed onto the kernel stack. * * The symbol for this routine is either _timer_int_handler. * * @return N/A */ void _timer_int_handler(void *unused) { ARG_UNUSED(unused); #ifdef CONFIG_EXECUTION_BENCHMARKING extern void read_systick_start_of_tick_handler(void); read_systick_start_of_tick_handler(); #endif #ifdef CONFIG_KERNEL_EVENT_LOGGER_INTERRUPT extern void _sys_k_event_logger_interrupt(void); _sys_k_event_logger_interrupt(); #endif #ifdef CONFIG_SYS_POWER_MANAGEMENT s32_t numIdleTicks; /* * All interrupts are disabled when handling idle wakeup. * For tickless idle, this ensures that the calculation and programming * of * the device for the next timer deadline is not interrupted. * For non-tickless idle, this ensures that the clearing of the kernel * idle * state is not interrupted. * In each case, _sys_power_save_idle_exit is called with interrupts * disabled. */ __asm__(" cpsid i"); /* PRIMASK = 1 */ #ifdef CONFIG_TICKLESS_IDLE #if defined(CONFIG_TICKLESS_KERNEL) if (!idle_original_ticks) { if (_sys_clock_always_on) { _sys_clock_tick_count = _get_elapsed_clock_time(); /* clear overflow tracking flag as it is accounted */ timer_overflow = 0; sysTickStop(); idle_original_ticks = max_system_ticks; sysTickReloadSet(max_load_value); sysTickStart(); sys_tick_reload(); } __asm__(" cpsie i"); /* re-enable interrupts (PRIMASK = 0) */ _ExcExit(); return; } idle_mode = IDLE_NOT_TICKLESS; _sys_idle_elapsed_ticks = idle_original_ticks; /* * Clear programmed ticks before announcing elapsed time so * that recursive calls to _update_elapsed_time() will not * announce already consumed elapsed time */ idle_original_ticks = 0; _sys_clock_tick_announce(); /* _sys_clock_tick_announce() could cause new programming */ if (!idle_original_ticks && _sys_clock_always_on) { _sys_clock_tick_count = _get_elapsed_clock_time(); /* clear overflow tracking flag as it is accounted */ timer_overflow = 0; sysTickStop(); sysTickReloadSet(max_load_value); sysTickStart(); sys_tick_reload(); } #else /* * If this a wakeup from a completed tickless idle or after * _timer_idle_exit has processed a partial idle, return * to the normal tick cycle. */ if (timer_mode == TIMER_MODE_ONE_SHOT) { sysTickStop(); sysTickReloadSet(default_load_value); sysTickStart(); timer_mode = TIMER_MODE_PERIODIC; } /* set the number of elapsed ticks and announce them to the kernel */ if (idle_mode == IDLE_TICKLESS) { /* tickless idle completed without interruption */ idle_mode = IDLE_NOT_TICKLESS; _sys_idle_elapsed_ticks = idle_original_ticks + 1; /* actual # of idle ticks */ _sys_clock_tick_announce(); } else { _sys_clock_final_tick_announce(); } /* accumulate total counter value */ clock_accumulated_count += default_load_value * _sys_idle_elapsed_ticks; #endif #else /* !CONFIG_TICKLESS_IDLE */ /* * No tickless idle: * Update the total tick count and announce this tick to the kernel. */ clock_accumulated_count += sys_clock_hw_cycles_per_tick; _sys_clock_tick_announce(); #endif /* CONFIG_TICKLESS_IDLE */ numIdleTicks = _NanoIdleValGet(); /* get # of idle ticks requested */ if (numIdleTicks) { _NanoIdleValClear(); /* clear kernel idle setting */ /* * Complete idle processing. * Note that for tickless idle, nothing will be done in * _timer_idle_exit. */ _sys_power_save_idle_exit(numIdleTicks); } __asm__(" cpsie i"); /* re-enable interrupts (PRIMASK = 0) */ #else /* !CONFIG_SYS_POWER_MANAGEMENT */ /* accumulate total counter value */ clock_accumulated_count += sys_clock_hw_cycles_per_tick; /* * one more tick has occurred -- don't need to do anything special since * timer is already configured to interrupt on the following tick */ _sys_clock_tick_announce(); #endif /* CONFIG_SYS_POWER_MANAGEMENT */ #ifdef CONFIG_EXECUTION_BENCHMARKING extern void read_systick_end_of_tick_handler(void); read_systick_end_of_tick_handler(); #endif extern void _ExcExit(void); _ExcExit(); }
/** * * @brief Handling of tickless idle when interrupted * * The routine, called by _sys_power_save_idle_exit, is responsible for taking * the timer out of idle mode and generating an interrupt at the next * tick interval. It is expected that interrupts have been disabled. * * Note that in this routine, _sys_idle_elapsed_ticks must be zero because the * ticker has done its work and consumed all the ticks. This has to be true * otherwise idle mode wouldn't have been entered in the first place. * * @return N/A */ void _timer_idle_exit(void) { uint32_t count; /* timer's current count register value */ if (timer_mode == TIMER_MODE_PERIODIC) { /* * The timer interrupt handler is handling a completed tickless * idle * or this has been called by mistake; there's nothing to do * here. */ return; } sysTickStop(); /* timer is in idle mode, adjust the ticks expired */ count = sysTickCurrentGet(); if ((count == 0) || (__scs.systick.stcsr.bit.countflag)) { /* * The timer expired and/or wrapped around. Re-set the timer to * its default value and mode. */ sysTickReloadSet(default_load_value); timer_mode = TIMER_MODE_PERIODIC; /* * Announce elapsed ticks to the microkernel. Note we are * guaranteed * that the timer ISR will execute before the tick event is * serviced, * so _sys_idle_elapsed_ticks is adjusted to account for it. */ _sys_idle_elapsed_ticks = idle_original_ticks - 1; _sys_clock_tick_announce(); } else { uint32_t elapsed; /* elapsed "counter time" */ uint32_t remaining; /* remaining "counter time" */ elapsed = idle_original_count - count; remaining = elapsed % default_load_value; /* ensure that the timer will interrupt at the next tick */ if (remaining == 0) { /* * Idle was interrupted on a tick boundary. Re-set the * timer to * its default value and mode. */ sysTickReloadSet(default_load_value); timer_mode = TIMER_MODE_PERIODIC; } else if (count > remaining) { /* * There is less time remaining to the next tick * boundary than * time left for idle. Leave in "one shot" mode. */ sysTickReloadSet(remaining); } _sys_idle_elapsed_ticks = elapsed / default_load_value; if (_sys_idle_elapsed_ticks) { _sys_clock_tick_announce(); } } idle_mode = IDLE_NOT_TICKLESS; sysTickStart(); }
/** * * @brief System clock tick handler * * This routine handles the system clock tick interrupt. A TICK_EVENT event * is pushed onto the microkernel stack. * * The symbol for this routine is either _timer_int_handler (for normal * system operation) or _real_timer_int_handler (when GDB_INFO is enabled). * * @return N/A */ void _TIMER_INT_HANDLER(void *unused) { ARG_UNUSED(unused); #ifdef CONFIG_KERNEL_EVENT_LOGGER_INTERRUPT extern void _sys_k_event_logger_interrupt(void); _sys_k_event_logger_interrupt(); #endif #ifdef CONFIG_INT_LATENCY_BENCHMARK uint32_t value = __scs.systick.val; uint32_t delta = __scs.systick.reload - value; if (_hw_irq_to_c_handler_latency > delta) { /* keep the lowest value observed */ _hw_irq_to_c_handler_latency = delta; } #endif #ifdef CONFIG_SYS_POWER_MANAGEMENT int32_t numIdleTicks; /* * All interrupts are disabled when handling idle wakeup. * For tickless idle, this ensures that the calculation and programming * of * the device for the next timer deadline is not interrupted. * For non-tickless idle, this ensures that the clearing of the kernel * idle * state is not interrupted. * In each case, _sys_power_save_idle_exit is called with interrupts * disabled. */ __asm__(" cpsid i"); /* PRIMASK = 1 */ #ifdef CONFIG_TICKLESS_IDLE /* * If this a wakeup from a completed tickless idle or after * _timer_idle_exit has processed a partial idle, return * to the normal tick cycle. */ if (timer_mode == TIMER_MODE_ONE_SHOT) { sysTickStop(); sysTickReloadSet(default_load_value); sysTickStart(); timer_mode = TIMER_MODE_PERIODIC; } /* set the number of elapsed ticks and announce them to the kernel */ if (idle_mode == IDLE_TICKLESS) { /* tickless idle completed without interruption */ idle_mode = IDLE_NOT_TICKLESS; _sys_idle_elapsed_ticks = idle_original_ticks + 1; /* actual # of idle ticks */ _sys_clock_tick_announce(); } else { /* * Increment the tick because _timer_idle_exit does not * account for the tick due to the timer interrupt itself. * Also, if not in tickless mode, _sys_idle_elapsed_ticks will be 0. */ _sys_idle_elapsed_ticks++; /* * If we transition from 0 elapsed ticks to 1 we need to * announce the * tick event to the microkernel. Other cases will be covered by * _timer_idle_exit. */ if (_sys_idle_elapsed_ticks == 1) { _sys_clock_tick_announce(); } } /* accumulate total counter value */ clock_accumulated_count += default_load_value * _sys_idle_elapsed_ticks; #else /* !CONFIG_TICKLESS_IDLE */ /* * No tickless idle: * Update the total tick count and announce this tick to the kernel. */ clock_accumulated_count += sys_clock_hw_cycles_per_tick; _sys_clock_tick_announce(); #endif /* CONFIG_TICKLESS_IDLE */ numIdleTicks = _NanoIdleValGet(); /* get # of idle ticks requested */ if (numIdleTicks) { _NanoIdleValClear(); /* clear kernel idle setting */ /* * Complete idle processing. * Note that for tickless idle, nothing will be done in * _timer_idle_exit. */ _sys_power_save_idle_exit(numIdleTicks); } __asm__(" cpsie i"); /* re-enable interrupts (PRIMASK = 0) */ #else /* !CONFIG_SYS_POWER_MANAGEMENT */ /* accumulate total counter value */ clock_accumulated_count += sys_clock_hw_cycles_per_tick; /* * one more tick has occurred -- don't need to do anything special since * timer is already configured to interrupt on the following tick */ _sys_clock_tick_announce(); #endif /* CONFIG_SYS_POWER_MANAGEMENT */ extern void _ExcExit(void); _ExcExit(); }