Exemple #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 */

}
Exemple #2
0
void _timer_idle_exit(void)
{
	uint64_t currTime = _hpetMainCounterAtomic();
	int32_t elapsedTicks;
	uint64_t counterNextValue;

	/* see if idling ended because timer expired at the desired tick */

	if (currTime >= *_HPET_TIMER0_COMPARATOR) {
		/*
		 * update # of ticks since last tick event was announced,
		 * so that this value is available to ISRs that run before the
		 * timer interrupt handler runs (which is unlikely, but could
		 * happen)
		 */

		_sys_idle_elapsed_ticks = programmed_ticks - 1;

		/*
		 * Announce elapsed ticks to the microkernel. Note we are
		 * guaranteed that the timer ISR will execute first before the
		 * tick event is serviced.
		 */
		_sys_clock_tick_announce();

		/* timer interrupt handler reprograms the timer for the next
		 * tick
		 */

		return;
	}

	/*
	 * idling ceased because a non-timer interrupt occurred
	 *
	 * compute how much idle time has elapsed and reprogram the timer
	 * to expire on the next tick; if the next tick will happen so soon
	 * that HPET might miss the interrupt declare that tick prematurely
	 * and program the timer for the tick after that
	 *
	 * note: a premature tick declaration has no significant impact on
	 * the microkernel, which gets informed of the correct number of elapsed
	 * ticks when the following tick finally occurs; however, any ISRs that
	 * access _sys_idle_elapsed_ticks to determine the current time may be
	 * misled during the (very brief) interval before the tick-in-progress
	 * finishes and the following tick begins
	 */

	elapsedTicks =
		(int32_t)((currTime - counter_last_value) / counter_load_value);
	counter_last_value += (uint64_t)elapsedTicks * counter_load_value;

	counterNextValue = counter_last_value + counter_load_value;

	if ((counterNextValue - currTime) <= HPET_COMP_DELAY) {
		elapsedTicks++;
		counterNextValue += counter_load_value;
		counter_last_value += counter_load_value;
	}

	*_HPET_TIMER0_CONFIG_CAPS |= HPET_Tn_VAL_SET_CNF;
	*_HPET_TIMER0_COMPARATOR = counterNextValue;
	stale_irq_check = 1;

	/*
	 * update # of ticks since last tick event was announced,
	 * so that this value is available to ISRs that run before the timer
	 * expires and the timer interrupt handler runs
	 */

	_sys_idle_elapsed_ticks = elapsedTicks;

	if (_sys_idle_elapsed_ticks) {
		/* Announce elapsed ticks to the microkernel */
		_sys_clock_tick_announce();
	}

	/*
	 * Any elapsed ticks have been accounted for so simply set the
	 * programmed ticks to 1 since the timer has been programmed to fire on
	 * the next tick boundary.
	 */

	programmed_ticks = 1;
}
Exemple #3
0
/**
 *
 * @brief System clock tick handler
 *
 * This routine handles the system clock tick interrupt. A TICK_EVENT event
 * is pushed onto the microkernel 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;

	/*
	 * 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.
	 */
#ifdef CONFIG_MICROKERNEL
	_sys_idle_elapsed_ticks++;
#else
	_sys_idle_elapsed_ticks = 1;
#endif /* CONFIG_MICROKERNEL */

	/*
	 * If we transistion from 0 elapsed ticks to 1 we need to announce the
	 * tick
	 * event to the microkernel. Other cases will have already been covered
	 * by
	 * _timer_idle_exit
	 */

	if (_sys_idle_elapsed_ticks == 1) {
		_sys_clock_tick_announce();
	}

#endif /* !CONFIG_TICKLESS_IDLE */

}