Example #1
0
/**
 *
 * @brief Initialize and enable the system clock
 *
 * This routine is used to program the timer to deliver interrupts at the
 * rate specified via the 'sys_clock_us_per_tick' global variable.
 *
 * @return 0
 */
int _sys_clock_driver_init(struct device *device)
{
	ARG_UNUSED(device);

	/* determine the timer counter value (in timer clock cycles/system tick)
	 */

	cycles_per_tick = sys_clock_hw_cycles_per_tick;

	tickless_idle_init();

#ifndef CONFIG_MVIC
	divide_configuration_register_set();
#endif
	initial_count_register_set(cycles_per_tick - 1);
	periodic_mode_set();
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
	loapic_timer_device_power_state = DEVICE_PM_ACTIVE_STATE;
#endif
	IRQ_CONNECT(TIMER_IRQ, TIMER_IRQ_PRIORITY, _timer_int_handler, 0, 0);

	/* Everything has been configured. It is now safe to enable the
	 * interrupt
	 */
	irq_enable(TIMER_IRQ);

	return 0;
}
Example #2
0
/**
 *
 * @brief Initialize and enable the system clock
 *
 * This routine is used to program the timer to deliver interrupts at the
 * rate specified via the 'sys_clock_us_per_tick' global variable.
 *
 * @return 0
 */
int _sys_clock_driver_init(struct device *device)
{
    ARG_UNUSED(device);

    /* determine the timer counter value (in timer clock cycles/system tick)
     */

    cycles_per_tick = sys_clock_hw_cycles_per_tick;

    tickless_idle_init();

    divide_configuration_register_set();
    initial_count_register_set(cycles_per_tick - 1);
    periodic_mode_set();

    IRQ_CONNECT(CONFIG_LOAPIC_TIMER_IRQ, CONFIG_LOAPIC_TIMER_IRQ_PRIORITY,
                _timer_int_handler, 0, 0);

    /* Everything has been configured. It is now safe to enable the
     * interrupt
     */
    irq_enable(CONFIG_LOAPIC_TIMER_IRQ);

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

    /*
     * Increment the tick because _timer_idle_exit() does not account
     * for the tick due to the timer interrupt itself. Also, if not in
     * one-shot mode, _sys_idle_elapsed_ticks will be 0.
     */
#ifdef CONFIG_MICROKERNEL
    _sys_idle_elapsed_ticks++;
#else
    _sys_idle_elapsed_ticks = 1;
#endif
    /* track the accumulated cycle count */
    accumulated_cycle_count += cycles_per_tick * _sys_idle_elapsed_ticks;

    /*
     * 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();
    }
#else
    /* track the accumulated cycle count */
    accumulated_cycle_count += cycles_per_tick;

    _sys_clock_tick_announce();
#endif /*CONFIG_TICKLESS_IDLE*/


#ifdef LOAPIC_TIMER_PERIODIC_WORKAROUND
    /*
     * On platforms where the LOAPIC timer periodic mode is broken,
     * re-program the ICR register with the initial count value. This
     * is only a temporary workaround.
     */

    initial_count_register_set(cycles_per_tick - 1);
    periodic_mode_set();
#endif /* LOAPIC_TIMER_PERIODIC_WORKAROUND */
}