Skip to content

Software Interrupts (Timer Interrupts)

Introduction

GPTM (General-Purpose Timer Module)

The TM4C123GH6PM microcontroller includes programmable General-Purpose Timer Modules (GPTM) that support various timing and counting functions. The module offers both 16/32-bit and 32/64-bit "Wide" timers with different capabilities and resolutions.

Feature16/32-bit GPTM Blocks32/64-bit Wide GPTM Blocks
Timer Width16-bit timers (Timer A & B) or combined 32-bit timer32-bit timers (can combine as a 64-bit timer)
Prescaler Resolution8-bit prescaler for 16-bit timers16-bit prescaler for 32-bit timers

Both types of timers support a range of versatile features that enable precise timing and event counting:

Operating Modes

  • One-Shot Mode: Timer runs once and stops automatically.
  • Periodic Mode: Timer repeats continuously, restarting after each cycle.
  • Other Modes: Various modes for specific applications, including capture and PWM you can explore in the datasheet.

Clock Source

The timer can be clocked either from the system clock or an external clock source. The TM4C123 microcontroller typically uses a 16 MHz external crystal oscillator as its main clock input. However, the system clock frequency is configurable through the internal PLL and clock dividers, allowing the MCU to run at different speeds. In Keil uVision projects for the TM4C123, the system clock is commonly configured to run at 50 MHz using the 16 MHz crystal and PLL settings.

Timer Configuration (Step-by-Step Explanation)

Configuring the timer on the TM4C123 microcontroller might look complicated at first, but it’s just a matter of following these steps carefully.

1. Enable the Clocks

Before using any peripheral like GPIO or a timer, the microcontroller needs to enable its clock signals. Think of this as turning on the power switch for those components.

c
SYSCTL->RCGCGPIO |= (1 << 5);    // Enable clock for GPIO Port F (where LEDs are connected)
SYSCTL->RCGCTIMER |= (1 << 1);   // Enable clock for Timer1 module
  • SYSCTL->RCGCGPIO controls clocks to GPIO ports; bit 5 corresponds to Port F.
  • SYSCTL->RCGCTIMER controls clocks to timers; bit 1 corresponds to Timer1.

IMPORTANT

After enabling the clocks, it’s good to wait briefly to ensure the clocks are stable. We do this with a simple delay loop.

2. Configure the GPIO Pin for the LED

We want to blink the Blue LED, which is connected to PF2. So, we need to tell the microcontroller to set that pin as an output and enable its digital function.

c
GPIOF->DIR |= 0x04;   // Set PF2 (Blue LED) as output
GPIOF->DEN |= 0x04;   // Enable digital function for PF2
  • DIR register configures pin direction: 1 means output, 0 means input.
  • DEN register enables digital functionality on the pin.

3. Disable the Timer Before Configuring

Before making any changes, we turn off the timer. This prevents any unwanted operation during setup.

c
TIMER1->CTL = 0;   // Disable TIMER1A (bit 0 controls timer enable)

4. Set Timer Configuration

We must tell the timer how it should operate:

  • The timer can be 16-bit or 32-bit. We choose 16-bit here.
  • We select Periodic Mode, which means the timer counts down repeatedly and generates interrupts each cycle.
c
TIMER1->CFG = 0x4;    // Configure Timer1 as 16-bit timer
TIMER1->TAMR = 0x2;   // Set Timer1A to Periodic Timer mode
  • CFG = 0x4 means “16-bit timer configuration.”
    • 0x4 is for 16-bit timer mode.
    • 0x0 would be 32-bit timer mode.
  • TAMR = 0x2 means “Periodic mode.”
    • 0x1 would be One-Shot mode.
    • 0x2 is Periodic mode.
    • 0x3 is Capture mode.

5. Set the Prescaler and Reload Value

Timers count down from a starting value (reload value) at a frequency determined by the system clock and the prescaler.

  • Prescaler: Divides the clock frequency further, making the timer count slower.
  • Reload value (ILR): The value from which the timer counts down to zero.

With the system clock at 50 MHz:

c
TIMER1->TAPR = 256 - 1;      // Prescaler value (255)
TIMER1->TAILR = 65536 - 1;   // Reload value (65535)

The prescaler effectively extends the timer's range. It slows down how frequently the main timer counter decrements.

How does this affect timing?

Interrupt Frequency=System ClockPrescaler×Reload Value

Interrupt frequency =

50,000,000(255+1)×65536=50,000,000256×655362.98 Hz

So, the timer fires approximately 2.98 times per second, meaning every interrupt is about 12.98335 milliseconds apart. This is the longest delay achievable using the 16-bit timer mode with the full 8-bit prescaler.

For longer delays, we must use the 32-bit timer configuration, which allows us to set a larger reload value. But removes the prescaler option. In this case, the timing expression becomes:

Interrupt Frequency=System ClockReload Value

For example, if we want a 1-second delay, we can set the reload value to 50,000,000 (for a 50 MHz clock), remove the prescaler, and set the timer to 32-bit mode.

c
TIMER1->CFG = 0x0;    // Configure Timer1 as 32-bit timer
TIMER1->TAMR = 0x2;   // Set Timer1A to Periodic Timer mode
TIMER1->TAILR = 50000000 - 1;   // Reload value (50,000,000)

6. Clear Interrupt Flag and Enable Timer Interrupt

Before enabling interrupts, clear any existing interrupt flags to avoid immediate triggers.

c
TIMER1->ICR = 0x1;    // Clear timeout interrupt flag
TIMER1->IMR |= 0x1;   // Enable timeout interrupt
  • ICR clears interrupts by writing 1 to the bit.
  • IMR enables interrupt masks; setting bit 0 allows the timeout interrupt.

7. Enable Timer and Interrupt in NVIC

Now, turn the timer on and enable the interrupt in the microcontroller’s interrupt controller.

c
TIMER1->CTL |= 0x1;            // Enable Timer1A
NVIC->ISER[0] |= (1 << 21);   // Enable interrupt number 21 (Timer1A) in NVIC
  • CTL |= 0x1 enables the timer.
  • NVIC->ISER[0] enables interrupts for Timer1A (IRQ number 21).

Summary

  • The timer counts down from TAILR at a frequency divided by the prescaler.
  • When it reaches zero, it triggers an interrupt.
  • Your interrupt handler will run and can toggle the LED or do any other action.
  • The timer automatically reloads and repeats this cycle (because of periodic mode).

Timer Registers

Register NameDescription
CFGConfigures the timer mode (0x4: 16-bit or 0x0: 32-bit).
TAMRTimer A Mode Register, sets the timer mode (0x1: One-Shot, 0x2: Periodic).
TAPRTimer A Prescale Register, sets the prescaler value.
TAILRTimer A Interval Load Register, sets the reload value.
ICRInterrupt Clear Register, clears the interrupt flag.
IMRInterrupt Mask Register, enables/disables interrupts. (0x1: Timeout)
MISMasked Interrupt Status Register, shows which interrupts are active.
CTLControl register for enabling/disabling the timer. (0x1: Enable, 0x0: Disable)
NVIC->ISERInterrupt Set-Enable Register, enables specific interrupts in the NVIC.

Example Code

Maximum 16-bit Timer Delay

main.c
c
#include "TM4C123.h"

#define RED 0x02
#define BLUE 0x04
#define GREEN 0x08
#define YELLOW RED + GREEN
#define MAGENTA BLUE + RED
#define CYAN GREEN + BLUE
#define WHITE RED + GREEN + BLUE
#define SW1 0x10
#define SW2 0x01
#define DELAY 900000



const int sequence[] = {RED, BLUE, GREEN, YELLOW, MAGENTA, CYAN, WHITE};
int index = 0;

void delay( volatile unsigned long ulLoop ){
	for (ulLoop = 0; ulLoop < DELAY; ulLoop++) {
		for (ulLoop = 0; ulLoop < DELAY; ulLoop++) {
  		}
 	}
}

int main(void)
{
	SYSCTL->RCGCGPIO |= (1<<5);
	SYSCTL->RCGCTIMER |= (1<<1);
	delay(0);
	GPIOF->DIR |= BLUE;
	GPIOF->DEN |= BLUE;

	TIMER1->CTL = 0;        		// Disable the timer
	TIMER1->CFG = 0x4;       		// Choose 16-bit mode
	TIMER1->TAMR = 0x02;       		// Periodic mode
	TIMER1->TAPR = 256  - 1;	// Prescaler
	TIMER1->TAILR = 65536 - 1;  // Initial Value
	TIMER1->ICR = 0x1;           	// Clear Any Prior Interrupts
	TIMER1->IMR |=(1<<0);			// Enable Timeout Interrupt
	TIMER1->CTL |= 0x01;          	// Enable the timer
	NVIC->ISER[0] |= (1<<21);
    while(1)
    {
    }
}


void TIMER1A_Handler()
{
	if(TIMER1->MIS & 0x1)
		GPIOF->DATA  ^= BLUE;
 	TIMER1->ICR = 0x1;
}

Lab Work

  1. Modify the code above to make the GREEN LED blinks every 100ms.
  2. Modify the code above to make the RED LED blinks every 4s.
  3. Use the onboard LED and another two external LEDs with the TM4C123G board to make one LED flashes every 10 seconds, one flashes every 5 seconds, and one flashes every one second.