The timer is a peripheral that allows the user to measure real-time as a number of clock cycles. A user loads the timer with the number of clock cycles they'd like to wait, and then polls the "Timeout" bit or optionally enables an interrupt to indicate to the processor that the period has elapsed.
Device | Timer | |||||||||||||||||||||
Configuration | 6 32-bit mapped registers (only lower 16 bits used) | |||||||||||||||||||||
Input/Output | Both | |||||||||||||||||||||
Address Base | Tiner 1: 0xFF202000 and Timer2: 0xxFF202020 | |||||||||||||||||||||
Address Map |
| |||||||||||||||||||||
Initialization | None (though a period must be written before running the timer, or it will immediately timeout) | |||||||||||||||||||||
Interrupts |
| |||||||||||||||||||||
Hardware Setup | None | |||||||||||||||||||||
Reference | Full documentation from Altera |
The timer counts downwards on a 100MHz clock, and runs in terms of clock cycles (a period of 100000000 will cause the timer to timeout in 1 second).
The full 32-bit period of the timer is given by the combination of "Periodh" and "Periodl". Both those registers are only 16-bits, even though they take up 32-bits of the address space.
When a timeout occurs, the Timeout bit in the Control Register will stay as 1 until the user writes 0 to the status register.
When a timeout occurs, the timer's counter is reset to the period, regardless of the "continue" bit. The continue bit determines whether the timer will then wait until 1 is written to the start bit again, or continue running immediately.
Reading the time remaining in the timer can not be done by reading the Periodh/l registers. Instead, the Counter Snapshot is used to copy the current time remaining, which can then be safely read by the user. By writing to either one of the snapshot registers (the written value is ignored), the current value of Periodh and Periodl, will be copied into the corresponding snapshot registers, which can then be read as in example 2 below.
WARNING: Do not try to read the Periodh/l registers directly.
ldr r0, =0xFF202000 // Set timer base address mov r1, #1000 str r1, [r0, #8] // set lower bits of timeout mov r1, #0 str r1, [r0, #12] // set higher bits of timeout mov r1, #4 str r1, [r0, #4] // Start the timer (continuous no interrupts)
#define Timer 0xFF202000 #define TimerStatus ((volatile short*) (Timer)) #define TimerControl ((volatile short*) (Timer+4)) #define TimerTimeoutL ((volatile short*) (Timer+8)) #define TimerTimeoutH ((volatile short*) (Timer+12)) #define TimerSnapshotL ((volatile short*) (Timer+16)) #define TimerSnapshotH ((volatile short*) (Timer+20)) #define ADDR_LEDR ((volatile long *) 0xFF200000) long numclks,numchigh,numclow; int main() { int i; // Configure the timeout period to maximum *(TimerTimeoutL)=0xffff; *(TimerTimeoutH)=0xffff; // Configure timer to start counting and to always continue *(TimerControl)=6; while (1) { *(TimerSnapshotL)=0; //write to timer to get snapshot numclow = *(TimerSnapshotL); //get low part numchigh = *(TimerSnapshotH); //get high part numclks = numclow | (numchigh << 16); //assemble full number *ADDR_LEDR = numclks; } }