/** * * @brief System clock periodic tick handler * * This routine handles the system clock periodic tick interrupt. It always * announces one tick. * * @return N/A */ void _timer_int_handler(void *unused) { ARG_UNUSED(unused); /* clear the interrupt by writing 0 to IP bit of the control register */ timer0_control_register_set(_ARC_V2_TMR_CTRL_NH | _ARC_V2_TMR_CTRL_IE); #ifdef CONFIG_TICKLESS_KERNEL if (!programmed_ticks) { if (_sys_clock_always_on) { _sys_clock_tick_count = _get_elapsed_clock_time(); program_max_cycles(); } return; } _sys_idle_elapsed_ticks = programmed_ticks; /* * Clear programmed ticks before announcing elapsed time so * that recursive calls to _update_elapsed_time() will not * announce already consumed elapsed time */ programmed_ticks = 0; timer_expired = 1; _sys_clock_tick_announce(); /* _sys_clock_tick_announce() could cause new programming */ if (!programmed_ticks && _sys_clock_always_on) { _sys_clock_tick_count = _get_elapsed_clock_time(); program_max_cycles(); } #else #if defined(CONFIG_TICKLESS_IDLE) timer0_limit_register_set(cycles_per_tick - 1); __ASSERT_EVAL({}, u32_t timer_count = timer0_count_register_get(), timer_count <= (cycles_per_tick - 1), "timer_count: %d, limit %d\n", timer_count, cycles_per_tick - 1); _sys_clock_final_tick_announce(); #else _sys_clock_tick_announce(); #endif update_accumulated_count(); #endif }
/** * @brief Enable sys Clock. * * This is used to program RTC clock to maximum Clock time in case Clock to * remain On. */ void _enable_sys_clock(void) { if (!expected_sys_ticks) { /* Programe sys tick to Maximum possible value*/ program_max_cycles(); } }
/* * @brief Announces the number of sys ticks that have passed since the last * announcement, if any, and programs the RTC to trigger the interrupt on the * next sys tick. * * The ISR is set pending due to a regular sys tick and after exiting idle mode * as scheduled. * * Since this ISR can be preempted, we need to take some provisions to announce * all expected sys ticks that have passed. * * Consider the following example: * * sys tick timeline: (1) (2) (3) (4) (5) (6) * rtc tick timeline : 0----100----200----300----400----500----600 * !********** * 450 * * The last sys tick was anounced at 200, i.e, rtc_past = 200. The ISR is * executed at the next sys tick, i.e. 300. The following sys tick is due at * 400. However, the ISR is preempted for a number of sys ticks, until 450 in * this example. The ISR will then announce the number of sys ticks it was * delayed (2), and schedule the next sys tick (5) at 500. */ void rtc1_nrf5_isr(void *arg) { ARG_UNUSED(arg); RTC_CC_EVENT = 0; #ifdef CONFIG_EXECUTION_BENCHMARKING extern void read_timer_start_of_tick_handler(void); read_timer_start_of_tick_handler(); #endif sys_trace_isr_enter(); #ifdef CONFIG_TICKLESS_KERNEL if (!expected_sys_ticks) { if (_sys_clock_always_on) { program_max_cycles(); } return; } _sys_idle_elapsed_ticks = expected_sys_ticks; /* Initialize expected sys tick, * It will be later updated based on next timeout. */ expected_sys_ticks = 0; /* Anounce elapsed of _sys_idle_elapsed_ticks systicks*/ _sys_clock_tick_announce(); /* _sys_clock_tick_announce() could cause new programming */ if (!expected_sys_ticks && _sys_clock_always_on) { program_max_cycles(); } #else rtc_announce_set_next(); #endif #ifdef CONFIG_EXECUTION_BENCHMARKING extern void read_timer_end_of_tick_handler(void); read_timer_end_of_tick_handler(); #endif sys_trace_isr_exit(); }
void _timer_idle_exit(void) { #ifdef CONFIG_TICKLESS_KERNEL if (!programmed_ticks && _sys_clock_always_on) { if (!(timer0_control_register_get() & _ARC_V2_TMR_CTRL_IE)) { timer0_control_register_set(_ARC_V2_TMR_CTRL_NH | _ARC_V2_TMR_CTRL_IE); } program_max_cycles(); } #else if (straddled_tick_on_idle_enter) { /* Aborting the tickless idle due to a straddled tick. */ straddled_tick_on_idle_enter = 0; __ASSERT_EVAL({}, u32_t timer_count = timer0_count_register_get(), timer_count <= programmed_limit, "timer_count: %d, limit %d\n", timer_count, programmed_limit); return; } u32_t control; u32_t current_count; current_count = timer0_count_register_get(); control = timer0_control_register_get(); if (control & _ARC_V2_TMR_CTRL_IP) { /* * The timer has expired. The handler _timer_int_handler() is * guaranteed to execute. Track the number of elapsed ticks. The * handler _timer_int_handler() will account for the final tick. */ _sys_idle_elapsed_ticks = programmed_ticks - 1; update_accumulated_count(); _sys_clock_tick_announce(); __ASSERT_EVAL({}, u32_t timer_count = timer0_count_register_get(), timer_count <= programmed_limit, "timer_count: %d, limit %d\n", timer_count, programmed_limit); return; } /* * A non-timer interrupt occurred. Announce any * ticks that have elapsed during the tickless idle. */ _sys_idle_elapsed_ticks = current_count / cycles_per_tick; if (_sys_idle_elapsed_ticks > 0) { update_accumulated_count(); _sys_clock_tick_announce(); } /* * Ensure the timer will expire at the end of the next tick in case * the ISR makes any threads ready to run. */ timer0_limit_register_set(cycles_per_tick - 1); timer0_count_register_set(current_count % cycles_per_tick); __ASSERT_EVAL({}, u32_t timer_count = timer0_count_register_get(), timer_count <= (cycles_per_tick - 1), "timer_count: %d, limit %d\n", timer_count, cycles_per_tick-1); #endif }
void _enable_sys_clock(void) { if (!programmed_ticks) { program_max_cycles(); } }