Example #1
0
/**
 *
 * @brief System clock tick handler
 *
 * This routine handles the system clock tick interrupt. A TICK_EVENT event
 * is pushed onto the kernel stack.
 *
 * @return N/A
 */
void _timer_int_handler(void *unused)
{
	ARG_UNUSED(unused);

#if defined(CONFIG_HPET_TIMER_LEVEL_LOW) || defined(CONFIG_HPET_TIMER_LEVEL_HIGH)
	/* Acknowledge interrupt */
	*_HPET_GENERAL_INT_STATUS = 1;
#endif

#ifdef CONFIG_INT_LATENCY_BENCHMARK
	uint32_t delta = *_HPET_MAIN_COUNTER_VALUE - main_count_expected_value;

	if (_hw_irq_to_c_handler_latency > delta) {
		/* keep the lowest value observed */
		_hw_irq_to_c_handler_latency = delta;
	}
	/* compute the next expected main counter value */
	main_count_expected_value += main_count_first_irq_value;
#endif


#ifndef CONFIG_TICKLESS_IDLE

	/*
	 * 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();

#else

	/* see if interrupt was triggered while timer was being reprogrammed */

	if (stale_irq_check) {
		stale_irq_check = 0;
		if (_hpetMainCounterAtomic() < *_HPET_TIMER0_COMPARATOR) {
			return; /* ignore "stale" interrupt */
		}
	}

	/* configure timer to expire on next tick */

	counter_last_value = *_HPET_TIMER0_COMPARATOR;
	*_HPET_TIMER0_CONFIG_CAPS |= HPET_Tn_VAL_SET_CNF;
	*_HPET_TIMER0_COMPARATOR = counter_last_value + counter_load_value;
	programmed_ticks = 1;

	_sys_clock_final_tick_announce();
#endif /* !CONFIG_TICKLESS_IDLE */

}
Example #2
0
void _timer_int_handler(void *unused /* parameter is not used */
				 )
{
	ARG_UNUSED(unused);

#ifdef CONFIG_TICKLESS_IDLE
	if (timer_mode == TIMER_MODE_ONE_SHOT) {
		if (!timer_known_to_have_expired) {
			uint32_t  cycles;

			/*
			 * The timer fired unexpectedly. This is due to one of two cases:
			 *   1. Entering tickless idle straddled a tick.
			 *   2. Leaving tickless idle straddled the final tick.
			 * Due to the timer reprogramming in _timer_idle_exit(), case #2
			 * can be handled as a fall-through.
			 *
			 * NOTE: Although the cycle count is supposed to stop decrementing
			 * once it hits zero in one-shot mode, not all targets implement
			 * this properly (and continue to decrement).  Thus, we have to
			 * perform a second comparison to check for wrap-around.
			 */

			cycles = current_count_register_get();
			if ((cycles > 0) && (cycles < programmed_cycles)) {
				/* Case 1 */
				_sys_idle_elapsed_ticks = 0;
			}
		}

		/* Return the timer to periodic mode */
		initial_count_register_set(cycles_per_tick - 1);
		periodic_mode_set();
		timer_known_to_have_expired = false;
		timer_mode = TIMER_MODE_PERIODIC;
	}

	_sys_clock_final_tick_announce();

	/* track the accumulated cycle count */
	accumulated_cycle_count += cycles_per_tick * _sys_idle_elapsed_ticks;
#else
	/* track the accumulated cycle count */
	accumulated_cycle_count += cycles_per_tick;

	_sys_clock_tick_announce();
#endif /*CONFIG_TICKLESS_IDLE*/

}
Example #3
0
/**
 *
 * @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
}
Example #4
0
/**
 *
 * @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();
}