-
Notifications
You must be signed in to change notification settings - Fork 11
Edge Triggered Interrupts
Note: The example on this page illustrates how you can use an edge triggered interrupt to monitor/count how many times a switch (PF4) has been pressed. The example code will increment "FallingEdges" anytime a falling edge interrupt trigger is invoked. A breakdown of the registers used in the example is listed below.
// NVIC Registers
#define NVIC_EN0_R (*((volatile unsigned long *)0xE000E100)) // IRQ 0 to 31 Set Enable Register
#define NVIC_PRI7_R (*((volatile unsigned long *)0xE000E41C)) // IRQ 28 to 31 Priority Register
// Standard GPIO Port Registers
#define GPIO_PORTF_DIR_R (*((volatile unsigned long *)0x40025400))
#define GPIO_PORTF_AFSEL_R (*((volatile unsigned long *)0x40025420))
#define GPIO_PORTF_PUR_R (*((volatile unsigned long *)0x40025510))
#define GPIO_PORTF_PDR_R (*((volatile unsigned long *)0x40025514))
#define GPIO_PORTF_DEN_R (*((volatile unsigned long *)0x4002551C))
#define GPIO_PORTF_AMSEL_R (*((volatile unsigned long *)0x40025528))
#define GPIO_PORTF_PCTL_R (*((volatile unsigned long *)0x4002552C))
// GPIO Port Interrupt Registers
#define GPIO_PORTF_IS_R (*((volatile unsigned long *)0x40025404))
#define GPIO_PORTF_IBE_R (*((volatile unsigned long *)0x40025408))
#define GPIO_PORTF_IEV_R (*((volatile unsigned long *)0x4002540C))
#define GPIO_PORTF_IM_R (*((volatile unsigned long *)0x40025410))
#define GPIO_PORTF_RIS_R (*((volatile unsigned long *)0x40025414))
#define GPIO_PORTF_ICR_R (*((volatile unsigned long *)0x4002541C))
// Clock Gating Registers
#define SYSCTL_RCGC2_R (*((volatile unsigned long *)0x400FE108))
NVIC Base Address: 0xE000.E000
- Enable Offsets (pg 132)
- EN0: 0x100 - Interrupt 0-31 Set Enable
- Priority Offset (pg 132)
- PRI7: 0x41C - Interrupt 28-31 Priority
GPIO PORTF (APB) Base Address: 0x4002.5000
-
Port Configuration Offsets (pg 657)
-
GPIODIR: 0x400 - Direction
-
GPIOAFSEL: 0x420 - Alternate Function Select
-
GPIOPUR: 0x510 - Pull-Up Select
-
GPIOPDR: 0x514 - Pull-Down Select
-
GPIODEN: 0x51C - Digital Enable
-
GPIOAMSEL: 0x528 - Analog Mode Select
-
GPIOPCTL: 0x52C - Port Control
-
Edge Triggering Offsets (pg 657)
-
GPIOIS: 0x404 - Interrupt Sense
-
GPIOIBE: 0x408 - Interrupt Both Edges
-
GPIOIEV: 0x40C - Interrupt Event
-
GPIOIM: 0x410 - Interrupt Mask
-
GPIORIS: 0x414 - Raw Interrupt Status
-
GPIOICR: 0x41C - Interrupt Clear
System Control: 0x400F.E000
- Run Mode Clock Gating Control Register 2 (pg 234 & 462)
- RCGC2: 0x108
void EdgeCounter_Init(void){
SYSCTL_RCGC2_R |= 0x00000020; // (a) activate clock for port F
FallingEdges = 0; // (b) initialize counter
GPIO_PORTF_DIR_R &= ~0x10; // (c) make PF4 in (built-in button)
GPIO_PORTF_AFSEL_R &= ~0x10; // disable alt funct on PF4
GPIO_PORTF_DEN_R |= 0x10; // enable digital I/O on PF4
GPIO_PORTF_PCTL_R &= ~0x000F0000; // configure PF4 as GPIO
GPIO_PORTF_AMSEL_R = 0; // disable analog functionality on PF
GPIO_PORTF_PUR_R |= 0x10; // enable weak pull-up on PF4
GPIO_PORTF_IS_R &= ~0x10; // (d) PF4 is edge-sensitive
GPIO_PORTF_IBE_R &= ~0x10; // PF4 is not both edges
GPIO_PORTF_IEV_R &= ~0x10; // PF4 falling edge event
GPIO_PORTF_ICR_R = 0x10; // (e) clear flag4
GPIO_PORTF_IM_R |= 0x10; // (f) arm interrupt on PF4
NVIC_PRI7_R = (NVIC_PRI7_R&0xFF00FFFF)|0x00A00000; // (g) priority 5
NVIC_EN0_R = 0x40000000; // (h) enable interrupt 30 in NVIC
EnableInterrupts(); // (i) Clears the I bit
}
a) Activate clock for Port F:
- Set bit 5 (GPIOF), on the RCGC2 register to activate the clock for Port F.
SYSCTL_RCGC2_R |= 0x00000020;
b) Initialize a counter:
- Create a falling edges variable
volatile unsigned long FallingEdges = 0;
and set it to 0 FallingEdges = 0;
c) Setup PF4 as input:
- Clear the 4th bit in the GPIODIR register to make it an input
GPIO_PORTF_DIR_R &= ~0x10;
- Clear the 4th bit in the GPIOAFSEL register to disable alternate functions
GPIO_PORTF_AFSEL_R &= ~0x10;
- Set the 4th bit in the GPIODEN register to make the pin digital enabled
GPIO_PORTF_DEN_R |= 0x10;
- Clear bits 16-19 (PMC4) in the GPIOPCTL register to disable peripheral control for PF4
GPIO_PORTF_PCTL_R &= ~0x000F0000;
- Write a 0 in the GPIOAMSEL register to disabled analog mode function
GPIO_PORTF_AMSEL_R = 0;
- Set the 4rth bit in the GPIOPUR register to enable a weak pull up resistor in the MCU
GPIO_PORTF_PUR_R |= 0x10;
d) Setup PF4 as edge-trigger:
- Clear the 4th bit in the GPIOIS register to have PF4 be edge-sensitive (edge trigger)
GPIO_PORTF_IS_R &= ~0x10;
- Clear the 4th bit in the GPIOIBE register so we don't trigger on both the falling and rising edge; interrupt generation is controlled by the IEV
GPIO_PORTF_IBE_R &= ~0x10;
- GPIO_PORTF_IEV_R &= ~0x10;
e) Clear Flag 4
- GPIO_PORTF_ICR_R = 0x10;
f) Arm interrupt on PF4:
- GPIO_PORTF_IM_R |= 0x10;
g) Set priority 5
- In the Interrupts table (pg 102) we notice that GPIO Port F is Interrupt Number 30. We will use this information to select the correct PRI(n) register to write to.
- The datasheet (pg 150) will tell us to use "Register 36: Interrupt 28-31 Priority (PRI7), offset 0x41C" so we will write to memory address 0xE000.E41C which is defined as NVIC_PRI7_R.
- We will write "5" to INTC slot (INTA = 28 | INTB = 29 | INTC = 30 | INTD = 31) in Register 36.
- A priority of 5 is chosen for this example:
- Priority of 5 = [1][0][1][RO] = A (bit 20 is Read Only)
NVIC_PRI7_R = (NVIC_PRI7_R&0xFF00FFFF)|0x00A00000;
h) Enable interrupt 30 in NVIC
- NVIC_EN0_R = 0x40000000;
i) Clear the I bit
- EnableInterrupts();
Note: The guides in these wiki are quick reference guides I made for myself and should not be used for teaching as they may contain errors that could misinform students. If you are a student, make sure you confirm everything you read on this wiki using the datasheet before fully committing to the information on this wiki.
TM4C123G (datasheet)
TM4C123G is a 32bit MCU based on the ARM® Cortex®-M4F architecture. Make sure to read C++ Support on TI Compilers if you plan on using C++