BCM2835 System Timer

From Embedded Xinu
Revision as of 17:04, 3 August 2013 by Ebiggers (talk | contribs) (→‎Use in Embedded Xinu: : Add links)
Jump to navigation Jump to search

The BCM2835 System Timer is a memory-mapped peripheral available on the BCM2835 System-on-a-Chip used in the Raspberry Pi. It features a 64-bit free-running counter that runs at 1 MHz and four separate "output compare registers" that can be used to schedule interrupts. However, two output compare registers are already used by the VideoCore GPU, leaving only two available for the ARM CPU to use.

Hardware details

The interface to the BCM2835 System Timer is a set of 32-bit memory-mapped registers beginning at physical address 0x20003000.

Offset Name Description
+0x00 CS System Timer Control and Status
+0x04 CLO System Timer Counter Lower 32 bits
+0x08 CHI System Timer Counter Upper 32 bits
+0x0C C0 System Timer Compare 0; corresponds to IRQ line 0.
+0x10 C1 System Timer Compare 1; corresponds to IRQ line 1.
+0x14 C2 System Timer Compare 2; corresponds to IRQ line 2.
+0x18 C3 System Timer Compare 3; corresponds to IRQ line 3.

CLO and CHI form a 64-bit free-running counter, which increases by itself at a rate of 1 MHz, that software can read to get the current number of timer ticks. There are, however, two caveats:

  • Appropriate memory barriers should be inserted to guarantee that read data is not re-ordered with that from a different peripheral.
  • Reading CLO can be done in a single 32-bit access. However, we are not currently aware of a way to read CLO and CHI together atomically. To work around this when the full 64-bit time is desired, software can read CHI, then CLO, then read CHI and retry if CHI changed.

To schedule an interrupt using the System Timer, software can write the value of CLO at which an interrupt will be generated into one of the System Timer Compare registers. However, the CPU actually only use C1 and C3, since C0 and C2 are used by the GPU. Also, to actually receive the scheduled interrupt, the software must have previously enabled the corresponding IRQ line using the BCM2835 Interrupt Controller. To clear the interrupt, software must write 1 to the bit in CS that has the index the same as that of the System Timer Compare register. That is, to clear an interrupt set in C1, software must write 0x20 to CS, and to clear an interrupt set in C3, software must write 0x80 to CS.

Use in Embedded Xinu

In the Raspberry Pi port of Embedded Xinu, the BCM2835 System Timer is used to implement preemptive multitasking and keep the system time. The code can be found in system/platforms/arm-rpi/timer.c and is fairly simple, as it only needs to implement clkcount() and clkupdate().