Tiva-C Launchpad Using Timers to generate precise Time Delay
In the world of embedded systems the most important parameter is time. It’s the time that qualifies a systems from simple blinky led to complex inter-systems communication. Its time which defines how fast/slow a job can be done on target processor. Obviously what’s the purpose of time if you can’t count it? This where timers comes into action. Timers provide the facility to measure time relatively from one reference point to another. This relative time measure enables us to generate an event or a specific time interval (like signal) or conversely measure an event time. This makes timers one of the crucial part of Embedded Systems.
The basic idea behind timers is that its logic is provided with some clock and upon each clock it increments/ decrements a counter register value. At the end the counted number of cycles is multiplied with input clock Time period to get the total time elapsed.
Total Time: Counter Value * 1/Frequency
A term that usually confuses newbies is the difference between a Timer and a Counter. As a matter of fact there is no such thing as Timers…!!! We only have counters in embedded systems. The source of confusion is that both these terms are NOT so often used INTERFACHANGABLY. The basic functions of both is to count time based events. A minor difference that is usually considered to differentiate timers and counters is frequency source. While in case of timers the input events (clock pulses) have same frequency i.e. clock to timers is fixed; and when the timer is feed from some external events which may or may not of fixed time intervals, the timer is known be as Counter (Counting events). But the basic idea behind both of them is same – They just count events. That’s it.
Tiva-C LaunchPad Timers:
The TM4C123GH6PM General-Purpose Timer Module (GPTM) contains six 16/32-bit GPTM blocks and six 32/64-bit Wide GPTM blocks. Each 16/32-bit GPTM block provides two 16-bit timers/counters (referred to as Timer A and Timer B) that can be configured to operate independently as timers or event counters, or concatenated to operate as one 32-bit timer or one 32-bit Real-Time Clock (RTC). Each 32/64-bit Wide GPTM block provides 32-bit timers for Timer A and Timer B that can be concatenated to operate as a 64-bit timer.
Timer A and Timer B can be used individually, in which case they have a 16-bit counting range for the 16/32-bit GPTM (General-Purpose Timer Module) blocks and a 32-bit counting range for 32/64-bit Wide GPTM blocks. In addition, Timer A and Timer B can be concatenated to provide a 32-bit counting range for the 16/32-bit GPTM blocks and a 64-bit counting range for the 32/64-bit Wide GPTM blocks.
Timers on TM4C123GH6PM can operate in one of the following modes.
- One-Shot/Periodic Timer Mode
- Real-Time Clock Timer Mode
- Input Edge-Count Mode
- Input Edge-Time Mode
- PWM Mode
Of all the above given modes the simplest one is “One-Shot/Periodic Timer Mode”. In this mode the timer simple counts pre-defined number of cycles once/repeatedly. We will use this mode to continuously measure number of cycles equivalent to 1-sec as stated by the following tutorial scenario.
In this tutorial we will use Timer-0 in concatenated mode (Timer-A and Timer-B are concatenated to form one 32-bits Timer) to generate blink on-board RED LED at the rate of 1-second i.e. After each 1-second, Time-0 generate an interrupt which toggles the on-board RED LED.
Let’s get started. Following are tutorial steps.
1. Before we can configure Timer-0, clock must be enabled to it. Clock to Timer-0 can be enabled by setting General-Purpose Timer Run Mode Clock Gating Control (RCGCTIMER) Register bit-0 to 1- Figure-2.
- Rx = 0: 16/32-bit general-purpose timer x is disabled. (x= 0-5)
- Rx = 1: Enable and provide a clock to 16/32-bit general-purpose timer x in Run mode. (x= 0-5)
RCGCTIMER_REG EQU 0x400FE604 ;enable clock to Timer-0 LDR R1, =RCGCTIMER_REG LDR R0, [R1] ORR R0, R0, #0x1 ; set bit-0 STR R0, [R1]
2. Once we have enabled clock to Timer-0, let’s move to further configurations. Timer-0 is 16/32-bit timer module which means it can be run in 32-bits as a single timer or two 16-bits timers (Timer A, Timer B). In 16-bits each timer i.e. Timer-A, Timer-B can count upto 65535 (2^16) which is not sufficient to generate 1-sec delay as will be clear in subsequent steps. So we will operate Timer-0 in concatenated mode.
The concatenated mode can be selected via GPTM Configuration (GPTMCFG) Register – Figure-3.
- GPTMCFG[0-2] = 0x0 : concatenated mode
- GPTMCFG[0-2] = 0x1 : RTC mode
- GPTMCFG[0-2] = 0x4 : Timer-A and Timer-B operates in isolation
Let’s configure Timer-0 in concatenated mode.
TIMER0CFG_REG EQU 0x40030000 ; configure timer-A,B in concatenated mode for Timer-0 LDR R1, =TIMER0CFG_REG MOV R0, #0 STR R0, [R1]
3. Next step is to select a mode for Timer-0. Each timer is capable of operating in one of specific modes mentioned here. As we want to continuously toggle LED after each 1-sec, so Timer-0 needs to be configured in periodic mode.
In concatenated configuration, Timer mode can be selected via GPTM Timer A Mode (GPTMTAMR) Register TAMR bits – Figure-4.
- TAMR = 0x1 : One-Shot Timer mode
- TAMR = 0x2 : Periodic Timer mode
- TAMR = 0x3 : Capture mode
As we need period mode, so TAMR bits need to be set to 0x2.
TIMER0AMR_REG EQU 0x40030004 ; periodic mode -> 1000ms continuous delay LDR R1, =TIMER0AMR_REG LDR R0, [R1] BIC R0, R0, #0x3 ; clear the lower two bits ORR R0, R0, #0x2 ; set bit-1 STR R0, [R1]
4. Next step is to set number of cycles to be counted by timer that will result in 1-sec (1000ms) delay. The cycles count can be set via UGPTM Timer A Interval Load (GPTMTAILR) Register – Figure-5.
When the timer is counting down, this register is used to load the starting count value into the timer. When the timer is counting up, this register sets the upper bound for the timeout event. When a 16/32-bit GPTM is configured to one of the 32-bit modes, GPTMTAILR appears as a 32-bit register (the upper 16-bits correspond to the contents of the GPTM Timer B Interval Load (GPTMTBILR) register). In a 16-bit mode, the upper 16 bits of this register read as 0s and have no effect on the state of GPTMTBILR.
The number of cycles count can be calculated via the following formula.
Counts = (Time Required in Seconds) x (Timer Frequency) – 1
In our case as we want to 1-second delay so the calculation is:
Note: By default timer-0 receives 16Mhz clock.
Counts = 1 x 16000000 – 1 Counts = 15999999
TIMER0AIL_REG EQU 0x40030028 TIMER_DELAY_VAL EQU 16000000 ; value to count for 1000ms delay @16Mhz clock LDR R1, =TIMER0AIL_REG LDR R0, =TIMER_DELAY_VAL STR R0, [R1]
5. Now that we have configured Timer-0 for desired delay value, its time to enable interrupt which will be called every time timer counts our desired value configured in previous step. Various interrupt for Timers can be enabled/disabled via GPTM Interrupt Mask (GPTMIMR) Register – Figure-6. In this case we want the interrupt to be triggered once the timer reaches its configured count value i.e. Time-out. So we will set TATOIM field of GPTM Interrupt Mask (GPTMIMR) Register.
- TATOIM = 0 : Interrupt is disabled.
- TATOIM = 1 : Interrupt is enabled.
TIMER0IMR_REG EQU 0x40030018 ; enable Interrupt for Timer-A LDR R1, =TIMER0IMR_REG LDR R0, [R1] ORR R0, R0, #0x1 ; set bit-0 STR R0, [R1]
6. Now that we have successfully configured Timer-0 to generate an interrupt upon Time-out but the interrupt will only reach ARM Cortex-M core once it is also enabled on NVIC side. If you don’t know about ARM NVIC, refer to the following tutorial.
Interrupt in NVIC can be enabled/disabled via ENx (where x=0-4) Registers – Figure-7. Each of ENx register is capable of enabling/disabling 32 interrupts (1-bit for each interrupt). Each Interrupt is assigned a number – see Table 2-9 (Pg#105) in TM4C123GH6PM datasheet . In order to enable an interrupt, respective bit in one of the ENx register needs to be set as per the following interrupts distribution.
- EN0 = Interrupt 0-31.
- EN1 = Interrupt 32-63.
- EN2 = Interrupt 64-95.
- EN3 = Interrupt 96-127.
- EN4 = Interrupt 128-138.
- 0: Interrupt is disabled.
- 1: Interrupt is enabled.
From Table 2-9 (Pg#105) in TM4C123GH6PM datasheet , the interrupt No for Timer-0 port is 19 – Figure-8, which is covered by EN0 (Interrupt 0-31). Let’s enable Timer-0 interrupt on NVIC side by setting bit-19.
;NVIC Registers NVIC_EN0_REG EQU 0xE000E100 ; 16/32-Bit Timer 0A at NVIC side ; assuming the core in privileged mode LDR R1, =NVIC_EN0_REG MOV R2, #0x1 LSLS R2, R2, #19 STR R2, [R1]
7. That’s every thing we need to configure Timer for period mode. Let’s finally enable Timer-0 to start counting. To enable timer set TAEN field of GPTM Control (GPTMCTL) Register – Figure-9.
- TAEN = 0 : Timer is disabled.
- TAEN = 1 : Timer is enabled.
TIMER0CTL_REG EQU 0x4003000C ; enable Timer-0 LDR R1, =TIMER0CTL_REG LDR R0, [R1] ORR R0, R0, #0x1 ; set bit-0 STR R0, [R1]
8. That’s pretty much everything we needed to configure. Now we need an ISR which will be called once interrupt is triggered by Timer-0. From TM4C123GH6PM startup file in Keil, the ISR name for Timer-0 is TIMER0A_Handler.
Within TIMER0A_Handler ISR two thing are done.
1) Interrupt is cleared so that next interrupt can call the ISR.
2) Red LED (PF.1) is toggled.
The following code snippet shows TIMER0A_Handler ISR which will be called each time Time-0 counts the pre-configured value.
TIMER0A_Handler PROC EXPORT TIMER0A_Handler ; clear the interrupt LDR R1, =TIMER0ICR_REG LDR R0, [R1] ORR R0, R0, #0x1 ; set bit-0 STR R0, [R1] ; Toggle PF.1 LDR R1, =GPIOFDATA_APB_REG LDR R0, [R1] EOR R0, R0, #0x2 STR R0, [R1] BX LR ENDP ALIGN END
Note: For PF.1 to be toggled, the pin needs to be configured as a Digital Output. This tutorial doesn’t cover GPIO configuration as a Digital input (required for PF.0) or as a Digital output (required for PF.1). These are covered in the tutorials here and here.
Congratulation we have successfully configured Timer-0 for precise 1-second delay.
For complete source code refer to the Github links given at the start of this tutorial.
Click the full screen button to have more clear view.