Timer and clock

The kernel uses the timer kernel callouts to work with the hardware timer (the timer/counter chip).

In many cases, a board can have several hardware timers. You choose one of these timers to use for timer_*() functions in the startup code (for example, timer_start()) and timer_*() kernel callouts.

In general, hardware timers either count up or count down and may or may not be auto-reset (also called periodic).

The kernel uses one of the hardware timers to generate a period interrupt (that is, the clock tick). The tasks that the kernel uses this interrupt for include:

  • Updating the system time and other software clocks
  • Firing software timers
  • Thread scheduling

Kernel callouts

The kernel interacts with the specified hardware timer through a set of timer kernel callouts.

timer_load()
The kernel assumes that the hardware timer starts at 0, counts up to a number (the divisor value), and then generates an interrupt. The kernel uses the following method to specify a divisor value for the hardware timer:
  1. The kernel places the divisor value to load into the hardware timer in the timer_load field in the qtime_entry element of the system page.
  2. The kernel calls timer_load().
  3. Because the kernel doesn't know the characteristics of the hardware timer, timer_load() validates the divisor value. For example, if the divisor value provided by the kernel is too high, the kernel callout writes the maximum divisor value supported by the hardware timer to the hardware timer.
  4. The kernel callout writes the value written to the hardware timer into the timer_load field in qtime_entry so that the kernel can see which value was actually used.
  5. The kernel reads the timer_load field in qtime_entry to see what the kernel callout wrote to the hardware timer.
timer_reload()
The kernel assumes that the hardware timer auto-resets (that is, is periodic). If the timer does not auto-reset, you implement the timer_reload() kernel callout. The kernel calls timer_reload() at the beginning of the interrupt.
If timer_reload() returns 1, the interrupt is treated as a clock tick. This return value is useful when several interrupts sources can generate the same interrupt, to distinguish a clock tick interrupt from other interrupt sources.
timer_value()
If the kernel wants to know when to expect the next interrupt, it calls the timer_value() kernel callout and the following formula:
jiffies_until_interrupt = divisor_value - timer_value()
where a jiffy is how long it takes for the timer count to increment by one.
If the hardware timer counts down, the timer_value() kernel callout performs a calculation to provide a value that is equivalent to one from a count-up timer. The following code is an example of the timer_value calculation for a timer_value() kernel callout:
curr_hw_timer_value = // read hardware timer value here
value = divisor_value - curr_hw_timer_value
return value;