Actions

EmSys

Lab Practicals Using TivaC LaunchPad Board

From EdWiki

Revision as of 06:36, 2 March 2020 by Jshankar (Talk | contribs) (On-Chip Peripheral Programming)

On-Chip Peripheral Programming

Programming the GPIO in TM4C123

In this article we are going to write our first program for accessing GPIOs on the EK-TM4C123GXL LaunchPad Board.

Memory Map

The ARM Cortex-M4 has 4GB (Giga bytes) of memory space. It uses memory mapped I/O, which means that the I/O peripheral ports are mapped into the 4GB memory space.

The TI EK-TM4C123GXL LaunchPad uses the TM4C123GH6PM microcontroller, which has 256K bytes (256KB) of on-chip Flash memory for code, 32KB of on-chip SRAM for data, and a large number of on-chip peripherals.

Allocated size Allocated address
Flash 256 KB 0x0000.0000 To 0x0003.FFFF
SRAM 32 KB 0x2000.0000 To 0x2000.7FFF
I/O All the peripherals 0x4000.0000 to 0x400F.FFFF

GPIO & Special Purpose I/O

While memory holds code and data for the CPU to process, the I/O ports are used by the CPU to access input and output devices. In the microcontroller we have two types of I/O :

  • General Purpose I/O (GPIO)
    The GPIO ports are used for interfacing devices such as LEDs, Switches, LCD, Keypad, and so on.
  • Special purpose I/O
    These I/O ports have designated function such as ADC (Analog-to-Digital), Timer, UART, PWM and so on.

TM4C123GH6PM Block Diagram

Tm4c123gh6pm io pins.png

TM4C123GH6PM Micro controller

ARM chip used in TI Tiva LaunchPad is Tiva C series TM4C123GH6PM microcontroller.

Tm4c123gh6pm pin Diagram.png

The pins are designated as:
➢ PA0 - PA7
➢ PB0 - PB7
➢ PC0 - PC7
➢ PD0 - PD7
➢ PE0 - PE5
➢ PF0 – PF4

Port-E and Port-F do not have all the 8 pins implemented.

GPIO APB & AHB Bus

The ARM chips have two buses:

  1. Advanced Peripheral Bus (APB) and
  2. Advanced High-Performance Bus (AHB).

The AHB bus is much faster than APB. The AHB allows one clock cycle access to the peripherals. The APB is slower and its access time is minimum of two clock cycles.

GPIO APB Memory Map

The I/O ports addresses assigned to the Port A - Port F for APB are as follow:

  • GPIO Port A : 0x4000.4000
  • GPIO Port B : 0x4000.5000
  • GPIO Port C : 0x4000.6000
  • GPIO Port D : 0x4000.7000
  • GPIO Port E : 0x4002.4000
  • GPIO Port F : 0x4002.5000

GPIO AHB Memory Map

The Base addresses for the GPIOs of AHB is as follow:

  • GPIO Port A : 0x4005.8000
  • GPIO Port B : 0x4005.9000
  • GPIO Port C : 0x4005.A000
  • GPIO Port D : 0x4005.B000
  • GPIO Port E : 0x4005.C000
  • GPIO Port F : 0x4005.D000

4K bytes of memory space is assigned to each of the GPIO port. Each GPIO has a large number of special function registers (SFR) associated with it and the GPIO DATA register supports bit-banding. The GPIO DATA register is 8-bit wide. With bit-banding, it will need 256 words (4 bytes each, 1 KB total). There are many registers associated with each of the above I/O ports and they have designated addresses in the memory map. The above addresses are the Base addresses meaning that within that base address we have registers associated with that port.

Digital I/O Pads

The TM4C123GH6PM microcontroller contains six ports and thus six of these physical GPIO blocks. Note that not all pins are implemented on every block. Some GPIO pins can function as I/O signals for the on-chip peripheral modules.

Tm4c123gh6pm gpio block diagram.png
Figure: TM4C123GH6PM Micro controller Digital I/O Pads

GPIO Register Map

Name Offset Tivaware Name Description
GPIODATA 0x000 GPIO_PORTn_DATA_R GPIO Data
GPIODIR 0x400 GPIO_PORTn_DIR_R GPIO Direction
GPIOIS 0x404 GPIO_PORTn_IS_R GPIO Interrupt Sense
GPIOIBE 0x408 GPIO_PORTn_IBE_R GPIO Interrupt Both Edges
GPIOIEV 0x40C GPIO_PORTn_IEV_R GPIO Interrupt Event
GPIOIM 0x410 GPIO_PORTn_IM_R GPIO Interrupt Mask
GPIORIS 0x414 GPIO_PORTn_RIS_R GPIO Raw Interrupt Status
GPIOMIS 0x418 GPIO_PORTn_MIS_R GPIO Masked Interrupt Status
GPIOICR 0x41C GPIO_PORTn_ICR_R GPIO Interrupt Clear
GPIOAFSEL 0x420 GPIO_PORTn_AFSEL_R GPIO Alternate Function Select
GPIODR2R 0x500 GPIO_PORTn_DR2R_R GPIO 2-mA Drive Select
GPIODR4R 0x504 GPIO_PORTn_DR4R_R GPIO 4-mA Drive Select
GPIODR8R 0x508 GPIO_PORTn_DR8R_R GPIO 8-mA Drive Select
GPIOODR 0x50C GPIO_PORTn_ODR_R GPIO Open Drain Select
GPIOPUR 0x510 GPIO_PORTn_PUR_R GPIO Pull-Up Select
GPIOPDR 0x514 GPIO_PORTn_PDR_R GPIO Pull-Down Select
GPIOSLR 0x518 GPIO_PORTn_SLR_R GPIO Slew Rate Control Select
GPIODEN 0x51C GPIO_PORTn_DEN_R GPIO Digital Enable
GPIOLOCK 0x520 GPIO_PORTn_LOCK_R GPIO Lock
GPIOCR 0x524 GPIO_PORTn_CR_R GPIO Commit
GPIOAMSEL 0x528 GPIO_PORTn_AMSEL_R GPIO Analog Mode Select
GPIOPCTL 0x52C GPIO_PORTn_PCTL_R GPIO Port Control
where n = A or B or C or D or E or F


Accessing GPIO of this microcontroller includes much more steps as this microcontroller provides a lot of feature in a single board, hence requires lots of configuration.

For accessing and configuring the microcontroller pins, we have to load some values in the registers, associated with that particular pin.

Initialization of an I/O port

To initialize an I/O port for general use:

  1. Activate the clock for the port in the Run Mode Clock Gating Control Register 2 (RCGC2).
  2. Unlock the port (LOCK = 0x4C4F434B). This step is only needed for pins PC0-3, PD7 and PF0 on TM4C123GXL LaunchPad.
  3. Disable the analog function of the pin in the Analog Mode Select register (AMSEL), because we want to use the pin for digital I/O. If this pin is connected to the ADC or analog comparator, its corresponding bit in AMSEL must be set as 1. In our case, this pin is used as digital I/O, so its corresponding bit must be set as 0.
  4. Clear bits in the port control register (PCTL) to select regular digital function. Each GPIO pin needs four bits in its corresponding PCTL register. Not every pin can be configured to every alternative function.
  5. Set its direction register (DIR). A DIR bit of 0 means input, and 1 means output.
  6. Clear bits in the alternate Function Select register (AFSEL).
  7. Enable digital port in the Digital Enable register (DEN).
  • Please note that we need to add a short delay between activating the clock and setting the port registers.
  • PC0-PC3 is used for JTAG connections to the debugger on the LaunchPad. So we’d better do not use these pins normally.

See Also

  1. EK-TM4C123GXL LaunchPad Board
  2. Switch Inputs and LED Outputs in TM4C123

EK-TM4C123GXL Blinky Program

  1. /* 
  2. Toggling LEDs using special function registers by their names defined in the TivaWare header file
  3. Runs on TI EK-TM4C123GXl LaunchPad Board
  4. */
  5.  
  6.  
  7. #include <stdint.h>
  8. #include "inc/tm4c123gh6pm.h"
  9.  
  10. void delayMs(int n);
  11.  
  12. int main(void)
  13. {
  14.     SYSCTL_RCGC2_R |= 0x00000020;     /* enable clock to GPIOF at clock gating control register */
  15.  
  16.     GPIO_PORTF_DIR_R = 0x0E;          /* enable the GPIO pins for the LED (PF3, 2, 1) as output */
  17.     GPIO_PORTF_DEN_R = 0x0E;         /* enable the GPIO pins for digital function */
  18.  
  19.     while(1) {
  20.         GPIO_PORTF_DATA_R = 0x0E;     /* turn on all LEDs */
  21.         delayMs(500);
  22.         GPIO_PORTF_DATA_R = 0;        /* turn off all LEDs */
  23.         delayMs(500);
  24.     }
  25. }
  26.  
  27. /* delay n milliseconds (16 MHz CPU clock) */
  28. void delayMs(int n)
  29. {
  30.     int i, j;
  31.     for(i = 0 ; i < n; i++)
  32.         for(j = 0; j < 3180; j++) {}   /* do nothing for 1 ms */
  33. }

See Also

  1. TM4C123GH6PM GPIO Programming
  2. EK-TM4C123GXL LaunchPad Board
  3. Switch Inputs and LED Outputs in TM4C123

Switch Inputs and LED Outputs

There are four ways to interface a switch to the microcontroller as shown in the following Figure:

Interface of a switch to a microcomputer input

We can use either positive or negative logic, and we can use an external resistor or select an internal resistor. Notice the positive logic circuit with external resistor is essentially the same as the positive logic circuit with internal resistance; the difference lies with whether the pull-down resistor is connected externally as a 10 kΩ resistor or internally by setting the corresponding PDR bit during software initialization.

SW1 and SW2 on LaunchPad

SW1 and SW2 on LaunchPad
  • SW1 push-button switch is connected to PF0 pin.
  • SW2 push-button switch is connected to PF4 pin.
  • There is no pull-up resistor connected to SW1 & SW2
  • To use the SW1 and SW2, we need to enable the internal pull-up resistor for PF0 and PF4 pins.

Read SW1 & Display it on the Green LED

To read SW1 and display it on the green LED, the following steps must be taken.

  1. Enable the clock to PortF
  2. Set the Direction register PF4 as input, and PF3 as output
  3. Enable the digital I/O feature of PortF
  4. Enable the pull up resistor option in PUR register since the switch circuit does not have pull-up resistor
  5. Read SW1 on PortF
  6. Invert the value since the switch is active low and the LED is active high
  7. Shift right the switch bit (PF4) to green LED bit(PF3) of the value
  8. Write the value to green LED of PortF
  9. Repeat steps 5 to 8

Source Code

  1. /* Read a switch and write it to the LED */
  2. /* This program reads SW1 of Tiva LaunchPad and writes the inverse of the value to the green
  3.    LED. SW1 is low when pressed (Normally High). LED is ON when high.
  4. */
  5.  
  6. #include <stdint.h>
  7. #include "inc/tm4c123gh6pm.h"
  8.  
  9. int main(void)
  10. {
  11.     unsigned int value;
  12.  
  13.     SYSCTL_RCGC2_R |= 0x00000020;;   /* enable clock to GPIOF */
  14.  
  15.     GPIO_PORTF_DIR_R = 0x08;         /* set PORTF3 pin as output (LED) pin */
  16.                                      /* and PORTF4 as input, SW1 is on PORTF4 */
  17.     GPIO_PORTF_DEN_R = 0x18;         /* set PORTF pins 4-3 as digital pins */
  18.     GPIO_PORTF_PUR_R = 0x10;         /* enable pull up for pin 4 */
  19.  
  20.     While(1) {
  21.         value = GPIO_PORTF_DATA_R;  /* read data from PORTF */
  22.         value = ~value;             /* switch is low active; LED is high active */
  23.         value = value >> 1;         /* shift it right to display on green LED */
  24.         GPIO_PORTF_DATA_R = value;  /* put it on the green LED */
  25.     }
  26. }

Read SW2 and Write it on Red LED

To read SW2 and display it on the Red LED, the program is similar to the previous program except extra steps needed to take care of PortF0 as described below:

  • The SW2 is connected to PortF0 pin, which is shared with NMI (non-maskable interrupt).
  • To prevent accidental write to configuration registers and thus disables NMI, the configuration register bits for PortF0 are normally locked.
  • They may be unlocked by writing a pass code value of 0x4C4F434B to the LOCK Register followed by setting bit 0 of the Commit Register (GPIOCR).


Source Code

  1. /* Read a switch and write it to the LED */
  2. /* This program reads SW2 of Tiva LaunchPad and write the inverse of the value to the red LED.
  3.    SW2 is low when pressed. LED is on when high. */
  4. /* SW2 is connected to PORTF0, which is an NMI pin. */
  5. /* In order to use this pin for any function other than NMI, the pin needs be unlocked first. */
  6.  
  7. #include <stdint.h>
  8. #include "inc/tm4c123gh6pm.h"
  9.  
  10. int main(void)
  11. {
  12.     unsigned int value;
  13.  
  14.     SYSCTL_RCGC2_R |= 0x00000020;       /* enable clock to GPIOF */
  15.  
  16.     GPIO_PORTF_LOCK_R = 0x4C4F434B;     /* unlock commit register */
  17.     GPIO_PORTF_CR_R = 0x01;             /* make PORTF0 configurable */
  18.     GPIO_PORTF_DIR_R = 0x02;            /* set PORTF1 pin as output (LED) pin */
  19.                                         /* and PORTF0 as input, SW2 is on  PORTF0 */
  20.     GPIO_PORTF_DEN_R = 0x03;            /* set PORTF pins 1-0 as digital pins */
  21.     GPIO_PORTF_PUR_R = 0x01;            /* enable pull up for pin 0 */
  22.  
  23.     while(1) {
  24.         value = GPIO_PORTF_DATA_R;      /* read data from PORTF */
  25.         value = ~value;                 /* switch is low active; LED is high active */
  26.         value = value << 1;             /* shift it left to display on red LED */
  27.         GPIO_PORTF_DATA_R = value;      /* put it on red LED */
  28.     }
  29. }

GPIO Tasks

Interrupts in TM4C123GH6PM Launchpad

In this article we are going to deal with GPIO PORTF interrupt that will toggle the on board blue led on rising edge whenever a user switch is pressed. Since the GPIO related initialization has already been discussed in our GPIO section. Here we will look at the initialization rituals for GPIO interrupts only.

As we already know that a micro controller has a built in capability to perform several tasks without waiting for completion of ongoing task. Generally there are two methods by which a peripheral device can receive a service from micro controller, they are:

  1. Polling
  2. Interrupts

In polling method a micro controller continuously monitors the status of a device or a particular condition and waits until the required status or condition is met and then it performs the service, after performing this task it executes the next task. For example, just take a look at our section of UART code you can see that we are continuously monitoring the bit 5 of UART0_FR_R register to ensure that any previous transmission has been completed.

    while((UART0_FR_R & 0x00000010) != 0) {
        ;
    }
    UART0_DR_R = data;

If yes, then transmit the next incoming data, while in interrupt the same thing is serviced by a microcontroller without continuously monitoring the status of a device though it serves when it gets notified by the device by receiving an interrupt signal.

Interrupt service routine (ISR)

For every interrupt there must be a program associated with it. When an interrupt occurs this program is executed to perform certain service for the interrupt. This program is commonly referred to as an interrupt service routine (ISR) or interrupt handler. When an interrupt occurs, the CPU runs the interrupt service routine. Now the question is, how the ISR gets executed? As shown in the Table 7.1, in the ARM CPU there are pins that are associated with hardware interrupts. They are input signals into the CPU. When the signals are triggered, CPU pushes the PC register onto the stack and loads the PC register with the address of the interrupt service routine. This causes the ISR to get executed.

Interrupt Vector Table

Since there is a program (ISR) associated with every interrupt and this program resides in memory (RAM or ROM), there must be a look-up table to hold the addresses of these ISRs. This look-up table is called interrupt vector table. In the ARM, the lowest 1024 bytes (256 * 4 = 1024) of memory space are set aside for the interrupt vector table and must not be used for any other function. Of the 256 interrupts, some are used for software interrupts and some are for hardware IRQ interrupts.

Nested Vectored Interrupt Controller (NVIC)

It is a control unit for a cortex-M4 MCU, It provides the group of programmable registers where all the exceptions and interrupts, including maskable and non-maskable interrupts are handled and preprocessed in a specific sequences.

Nvic in arm cortex.png
Table 7.1: NVIC in ARM Cortex-M
  • Interrupts on the Cortex-M are controlled by the Nested Vectored Interrupt Controller (NVIC).
  • Each exception has an associated 32-bit vector that points to the memory location where the ISR that handles the exception is located.

With CCS IDE, a new project will get a C startup code tm4c123gh6pm_startup_ccs_gcc.c created by the project wizard. For each interrupt, there is a dummy interrupt hander that does not perform any thing and will never return from the handler. The addresses of these interrupt handlers are listed in the interrupt vector table named g_pfnVectors in the file. You need to carefully find the appropriate vector position and replace IntDefaultHandler with the name of your Interrupt handler. The linker will overwrite the interrupt vector table with the new interrupt handler. The interrupt handler is written with a format of a function in C language.

A detailed default vector table can be found at tm4c123gh6pm_startup_ccs_gcc.c file.

Interrupt and Exception assignments in ARM Cortex-M

The NVIC of the ARM Cortex-M has room for the total of 255 interrupts and exceptions. The interrupt numbers are also referred to as INT type (or INT #) in which the type can be from 1 to 255 or 0x01 to 0xFF. The NVIC in ARM Cortex-M assigns the first 15 interrupts for internal use. The memory locations 0 to 3 are used to store the value to be loaded into the stack pointer when the device is coming out of reset. See Table 7.2

Interrupt # Interrupt Memory Location Priority Level
0
Stack Pointer Initial Value 0x00000000
1
Reset 0x00000004 -3 Highest
2
NMI 0x00000008 -2
3
Hard Fault 0x0000000C -1
4
Memory Management Fault 0x00000010 Programmable
5
Bus Fault 0x00000014 Programmable
6
Usage Fault (undefined instructions,
divide by zero, unaligned memory
access, ....)
0x00000018 Programmable
7
Reserved 0x0000001C Programmable
8
Reserved 0x00000020 Programmable
9
Reserved 0x00000024 Programmable
10
Reserved 0x00000028 Programmable
11
SVCall 0x0000002C Programmable
12
Debug Moniter 0x00000030 Programmable
13
Reserved 0x00000034 Programmable
14
PendSV 0x00000038 Programmable
15
SysTick 0x0000003C Programmable
16
IRQ for peripherals 0x00000040 Programmable
17
IRQ for peripherals 0x00000044 Programmable
...
...
...
...
255
IRQ for peripherals 0x000003FC Programmable
Table 7.2: Interrupt Vector Table for ARM Cortex-M.

IRQ Peripheral interrupts

  • An ISR can be launched as a result of an event at the peripheral devices such as timer timeout or analog-to-digital converter (ADC) conversion complete. The largest number of the interrupts in the ARM Cortex-M belong to this category.
  • Notice from Table 7.2 that ARM Cortex-M NVIC has set aside the first 15 interrupts (INT 1 to INT 15) for internal use and exceptions and is not available to chip designer. The Reset, NMI, undefined instructions, and so on are part of this group of exceptions. The rest of the interrupts can be used for peripherals.
  • Many of the INT 16 to INT 255 are used by the chip manufacturer to be assigned to various peripherals such as timers, ADC, Serial COM, external hardware interrupts, and so on. There is no standard in assigning the INT 16 to INT 255 to the peripherals.
  • Each peripheral device has a group of special function registers that must be used to access the device for configuration.
  • For a given peripheral interrupt to take effect, the interrupt for that peripheral must be enabled. The special function registers for that device provide the way to enable the interrupts.

Interrupt Priority for ARM Cortex-M

  • All exceptions and interrupts in the Cortex-M4 system have certain priority levels, either maskable or unmaskable sources.
  • Most maskable interrupts have programmable priority levels, but all Non-Maskable Interrupts (NMIs) have fixed priority levels.
  • When an exception or interrupt occurs, the NVIC performs a comparison between the priority level of current exception or interrupt and the priority level of the new coming exception/interrupt. The current running task will be suspended and the control will be transferred to the service routine of the new coming exception/interrupt if the priority level of the new coming exception/interrupt is higher.
  • In the ARM Cortex-M4 system, the interrupt priority levels are controlled by the Interrupt Priority Registers, as shown in Table 7.3.
  • Each priority register can use 3 bits, 4 bits, or 8 bits to cover all priority levels used in the priority control system.
  • A total of 8 priority levels can be used if 3 bits are used in this register, and 16 priority levels can be obtained if 4 bits are used in this register.
  • Devices within the Tiva family support up to 154 interrupt sources and 8 priority levels, which means that 3 bits are used in the priority register in the TM4C123GH6PM MCU.
  • To activate an interrupt source we need to set its priority and enable that source in the NVIC. This activation is in addition to the arm and enable steps.
    To arm a device means to allow the hardware trigger to interrupt. Conversely, to disarm a device means to shut off or disconnect the hardware trigger from the interrupts
  • Table 7.3 lists some of the interrupt sources available on the TM4C family of micro controllers. Interrupt numbers 0 to 15 contain the faults, software interrupt and SysTick; these interrupts will be handled differently from interrupts 16 and up.
Vector
address
Vector
(Exception)
Number
Interrupt #
(IRQ)
Address
(Priority Register)
Interrupt Source Priority Register
(Tivaware Name)
Priority
Bits
0x00000038
14
-2
0xE000.ED20 PendSV NVIC_SYS_PRI3_R 23 - 21
0x0000003C
15
-1
0xE000.ED20 SysTick NVIC_SYS_PRI3_R 31 - 29
0x00000040
16
0
0xE000.E400 GPIO Port A NVIC_PRI0_R 7 - 5
0x00000044
17
1
0xE000.E400 GPIO Port B NVIC_PRI0_R 15 - 13
0x00000048
18
2
0xE000.E400 GPIO Port C NVIC_PRI0_R 23 - 21
0x0000004C
19
3
0xE000.E400 GPIO Port D NVIC_PRI0_R 31 - 29
0x00000050
20
4
0xE000.E404 GPIO Port E NVIC_PRI1_R 7 - 5
0x00000054
21
5
0xE000.E404 UART0, Rx Tx NVIC_PRI1_R 15 - 13
0x00000058
22
6
0xE000.E404 UART1, Rx Tx NVIC_PRI1_R 23 - 21
0x0000005C
23
7
0xE000.E404 SSI0, Rx Tx NVIC_PRI1_R 31 - 29
0x00000060
24
8
0xE000.E408 I2C0 NVIC_PRI2_R 7 - 5
0x00000064
25
9
0xE000.E408 PWM Fault NVIC_PRI2_R 15 - 13
0x00000068
26
10
0xE000.E408 PWM Gen 0 NVIC_PRI2_R 23 - 21
0x0000006C
27
11
0xE000.E408 PWM Gen 1 NVIC_PRI2_R 31 - 29
0x00000070
28
12
0xE000.E40C PWM0 Gen 2 NVIC_PRI3_R 7 - 5
0x00000074
29
13
0xE000.E40C Quad Encoder 0 NVIC_PRI3_R 15 - 13
0x00000078
30
14
0xE000.E40C ADC Seq 0 NVIC_PRI3_R 23 - 21
0x0000007C
29
15
0xE000.E40C ADC Seq 1 NVIC_PRI3_R 31 - 29
0x00000080
32
16
0xE000.E410 ADC Seq 2 NVIC_PRI4_R 7 - 5
0x00000084
33
17
0xE000.E410 ADC Seq 3 NVIC_PRI4_R 15 - 13
0x00000088
34
18
0xE000.E400 Watchdog NVIC_PRI4_R 23 - 21
0x0000008C
35
19
0xE000.E410 Timer 0A NVIC_PRI4_R 31 - 29
0x00000090
36
20
0xE000.E414 Timer 0B NVIC_PRI5_R 7 - 5
0x00000094
37
21
0xE000.E414 Timer 1A NVIC_PRI5_R 15 - 13
0x00000098
38
22
0xE000.E414 Timer 1B NVIC_PRI5_R 23 - 21
0x0000009C
39
23
0xE000.E414 Timer 2A NVIC_PRI5_R 31 - 29
0x000000A0
40
24
0xE000.E418 Timer 2B NVIC_PRI6_R 7 - 5
0x000000A4
41
25
0xE000.E418 Comp 0 NVIC_PRI6_R 15 - 13
0x000000A8
42
26
0xE000.E418 Comp 1 NVIC_PRI6_R 23 - 21
0x000000AC
43
27
0xE000.E418 Comp 2 NVIC_PRI6_R 31 - 29
0x000000B0
44
28
0xE000.E41C System Control NVIC_PRI7_R 7 - 5
0x000000B4
45
29
0xE000.E41C Flash Control NVIC_PRI7_R 15 - 13
0x000000B8
46
30
0xE000.E41C GPIO Port F NVIC_PRI7_R 23 - 21
0x000000BC
47
31
0xE000.E41C GPIO Port G NVIC_PRI7_R 31 - 29
0x000000C0
48
32
0xE000.E420 GPIO Port H NVIC_PRI8_R 7 - 5
0x000000C4
49
33
0xE000.E420 UART2, Rx Tx NVIC_PRI8_R 15 - 13
0x000000C8
50
34
0xE000.E420 SSI1, Rx Tx NVIC_PRI8_R 23 - -21
0x000000CC
51
35
0xE000.E420 Timer 3A NVIC_PRI8_R 31 - 29
0x000000D0
52
36
0xE000.E424 Timer 3B NVIC_PRI9_R 7 - 5
0x000000D4
53
37
0xE000.E424 I2C1 NVIC_PRI9_R 15 - 13
0x000000D8
54
38
0xE000.E424 Quad Encoder 1 NVIC_PRI9_R 23 - 21
0x000000DC
55
39
0xE000.E424 CAN0 NVIC_PRI9_R 31 - 29
0x000000E0
56
40
0xE000.E428 CAN1 NVIC_PRI10_R 7 - 5
0x000000E4
57
41
0xE000.E428 CAN2 NVIC_PRI10_R 15 - 13
0x000000E8
58
42
0xE000.E428 Ethernet NVIC_PRI10_R 23 - 21
0x000000EC
59
43
0xE000.E428 Hibernate NVIC_PRI10_R 31 - 29
0x000000F0
60
44
0xE000.E42C USB0 NVIC_PRI11_R 7 - 5
0x000000F4
61
45
0xE000.E42C PWM Gen 3 NVIC_PRI11_R 15 - 13
0x000000F8
62
46
0xE000.E42C uDMA Soft Tfr NVIC_PRI11_R 23 - 21
0x000000FC
63
47
0xE000.E42C uDMA Error NVIC_PRI11_R 31 - 29
Table 7.3: The relationship between vectors and NVIC definitions.

The following five conditions must be true for an interrupt to be generated:

  1. Device arm
    Each potential interrupt trigger has a separate arm bit that the software can activate or deactivate. The software will set the arm bits for those devices from which it wishes to accept interrupts, and will deactivate the arm bits within those devices from which interrupts are not to be allowed. In other words it uses the arm bits to individually select which devices will and which devices will not request interrupts.
  2. NVIC enable
    For most devices there is a enable bit in the NVIC that must be set (periodic SysTick interrupts are an exception, having no NVIC enable).
  3. Global enable
    Bit 0 of the special register PRIMASK is the interrupt mask bit, I. If this bit is 1 most interrupts and exceptions are not allowed, which we will define as disabled. If the bit is 0, then interrupts are allowed, which we will define as enabled.
  4. Interrupt priority level must be higher than current level executing
    The BASEPRI register prevents interrupts with lower priority interrupts, but allows higher priority interrupts. For example if the software sets the BASEPRI to 3, then requests with level 0, 1, and 2 can interrupt, while requests at levels 3 and higher will be postponed. The software can also specify the priority level of each interrupt request. If BASEPRI is zero, then the priority feature is disabled and all interrupts are allowed.
  5. Hardware event trigger.
    Hardware triggers are bits in the GPIO_PORTx_RIS_R register that are set on rising or falling edges of digital input pins.

For an interrupt to occur, these five conditions must be simultaneously true but can occur in any order.


GPIO Port Interrupt Programming

Interrupt numbers 16 to 255 are assigned to the peripherals. The INT (IRQ) 46 is assigned to the GPIO Port of F. Although PortF has 8 pins, we have only one interrupt assigned to the entire PortF. In other words, when any of the PortF pins trigger an interrupt, they all go to the same address location in the interrupt vector table. It is the job of our Interrupt Service Routine (ISR or interrupt Handler) to find out which pin caused the interrupt.

Interrupt trigger point

When an input pin is connected to an external device to be used for interrupt, we have 5 choices for trigger point. They are:

  • low-level trigger (active Low level),
  • high-level trigger (active High level),
  • rising-edge trigger (positive-edge going from Low to High),
  • falling-Edge trigger (negative-edge going from High to Low),
  • Both edge (rising and falling) trigger.

Upon Reset, all the interrupts are disabled. To enable any interrupt:

  1. Enable the interrupt for a specific peripheral module.
  2. Enable the interrupts at the NVIC module.
  3. Enable the interrupt globally

GPIO Interrupt Control Registers

GPIO Register Tivaware Name Each Bit Value (Lowest 8-Bit) and Each Pin Function
GPIOIS GPIO_PORTx_IS_R Interrupt sense register
Determines level or edge triggered
0: Detect an edge (edge-sensitive) on the pin,
1: Detect a level (level-sensitive) on the pin.
GPIOIBE GPIO_PORTx_IBE_R 0: Interrupt is controlled by GPIOIEV,
1: Both edges on the corresponding pin trigger an interrupt
GPIOIEV GPIO_PORTx_IEV_R GPIO Interrupt Event Register
Determines the detecting edges or levels.
0: A falling edge or a LOW level,
1: A rising edge or a HIGH level triggers an interrupt
GPIOIM GPIO_PORTx_IM_R GPIO Interrupt Mask Register
Masks (disables) or unmask (enable) an interrupt.
0: Interrupt is masked (disabled),
1: Interrupt is unmasked (enabled).
GPIORIS GPIO_PORTx_IS_R GPIO Raw Interrupt Status Register
Indicates the raw interrupt status for a pin.
0: No interrupt occurred on the pin,
1: An interrupt is occurred on the pin.
For the edge-triggered interrupts,
write a 1 to the pin to clear that interrupt.
For level-triggered interrupt, no action is needed.
GPIOMIS GPIO_PORTx_MIS_R GPIO Masked Interrupt Status Register
Indicates the state of the interrupt.
0: No interrupt occurred or the pin has been masked,
1: An interrupt has been occurred.
GPIOICR GPIO_PORTx_ICR_R GPIO Interrupt Clear Register
Clears an edge-triggered interrupt.
0: No action,
1: The corresponded edge-triggered interrupt is cleared.
Table: The bit values and functions for GPIO interrupt controls.
  • All of these registers are 32-bit, but only lowest 8 bits are used and each bit corresponds to each pin in the selected GPIO Port: bit 0 is for pin 0, bit 1 is for pin 1, and so on. The above table shows the bit values and their functions for these registers.
  • Before any exception or interrupt can be applied to any pin on any GPIO Port, all GPIO pins on selected GPIO Port should be initialized and configured via related GPIO registers.

GPIO Interrupt Control Registers Description

GPIO Interrupt sense register (GPIOIS)

Tm4c gpiois r.png

Bit Bit Name Description
7-0 IS GPIO Interrupt Sense
0: The edge on the corresponding pin is detected (edge-sensitive).
1: The level on the corresponding pin is detected (level-sensitive).

First, we must use GPIO Interrupt Sense (GPIOIS) register to decide the level or edge. Only after using the GPIOIS register we need to indicate which level or edge. To do that, we use the GPIO Interrupt Event (GPIOIEV) to decide low-level, high-level, falling, or rising-edge. The GPIO Interrupt Both Edges (GPIOIBE) register bits overwrite the decision in GPIOIEV. Unless both edge interrupt is desired, the bit in GPIOIBE needs to be cleared.

GPIO Interrupt Event Register (GPIOIEV)

Tm4c gpioiev r.png

GPIOIS
(interrupt sense)
GPIOIEV
(Interrupt Event)
0
0
Falling edge
0
1
Rising edge
1
0
Low level
1
1
High level
Table 7.4: Using GPIOIM and GPIOIEV Registers.
  • Since we need a rising edge triggered interrupt at PF4, so writing 1 to the respective bit field will do the same for us.

GPIO Interrupt Both Edge (GPIOIBE)

Tm4c gpioibe r.png

Bit Bit Name Description
7-0 IBE GPIO Interrupt Both Edges
0: Interrupt generation is controlled by the GPIO Interrupt Event (GPIOIEV) register
1: Both edges on the corresponding pin trigger an interrupt


  • Setting the corresponding bit field enables the interrupts for both edges i.e. rising edge and falling edge but our concern is to enable the interrupts for rising edge only. Making the corresponding bit field i.e. PF4 to 0 will allow us to use this register in conjunction with the GPIOIEV register.

GPIO Interrupt Clear Register (GPIOICR)

Tm4c gpioicr r.png

  • The corresponding bit fields in this register clears the interrupt for the respective pin. To ensure that any previous interrupt has been cleared writing 1 to the respective bit field will clear the interrupt on that pin.
  • It is critical that the interrupt handler clears the interrupt flag before returning from interrupt handler. Otherwise the interrupt appears as if it is still pending and the interrupt handler will be executed again and again forever and the program hangs.

GPIO Interrupt Mask Register (GPIOIM)

Tm4c gpioim r.png

  • We need to enable the interrupt capability of a given peripheral at the module level. This should be done after other configurations of that peripheral are done. In the case of I/O ports, each pin can be used as a source of external hardware interrupt. This is done with the GPIO Interrupt Mask (GPIOIM) register.
  • Notice that, the lower 8 bits of this register is used to enable the interrupt capability of each pin of the I/O port. To enable the interrupts for PF0 and PF4 pins, we will need the following:
GPIO_PORTF_IM_R |= 0x11;  /* unmask interrupt */

GPIO Raw Interrupt Status (GPIORIS)

Tm4c gpioris r.png


Bit Bit Name Description
7-0 RIS GPIO Interrupt Raw Status
0: An interrupt condition has not occurred on the corresponding pin.
1: An interrupt condition has occurred on the corresponding pin.


  • For edge-detect interrupts, this bit is cleared by writing a 1 to the corresponding bit in the GPIOICR register.
  • For a GPIO level-detect interrupt, the bit is cleared when the level is deasserted.

GPIO Masked Interrupt Status (GPIOMIS)

Tm4c gpiomis r.png


Bit Bit Name Description
7-0
MIS
GPIO Masked Interrupt Status
0: An interrupt condition on the corresponding pin is masked or has not occurred.
1: An interrupt condition on the corresponding pin has triggered an interrupt to the interrupt controller.


  • For edge-detect interrupts, this bit is cleared by writing a 1 to the corresponding bit in the GPIOICR register.
  • For a GPIO level-detect interrupt, the bit is cleared when the level is deasserted.

NVIC Interrupt Priority Register

TM4C Interrupt Priority.jpg

Bit/Field Name Description
7:5 INTA Interrupt Priority for Interrupt [4n]
This field holds a priority value, 0-7, for the interrupt with the number [4n], where n is the number of the Interrupt Priority register (n=0 for PRI0, and so on). The lower the value, the greater the priority of the corresponding interrupt.
15:13 INTB Interrupt Priority for Interrupt [4n+1]
This field holds a priority value, 0-7, for the interrupt with the number [4n+1], where n is the number of the Interrupt Priority register (n=0 for PRI0, and so on). The lower the value, the greater the priority of the corresponding interrupt.
23:21 INTC Interrupt Priority for Interrupt [4n+2]
This field holds a priority value, 0-7, for the interrupt with the number [4n+2], where n is the number of the Interrupt Priority register (n=0 for PRI0, and so on). The lower the value, the greater the priority of the corresponding interrupt.
31:29 INTD Interrupt Priority for Interrupt [4n+3]
This field holds a priority value, 0-7, for the interrupt with the number [4n+3], where n is the number of the Interrupt Priority register (n=0 for PRI0, and so on). The lower the value, the greater the priority of the corresponding interrupt.


PRIn Register Bit Field Interrupt Source Priority Register Macros
Bits 31:29 Interrupt[IRQ] = Interrupt[4n+3]
NVIC_PRIn_R
Bits 23:21 Interrupt[IRQ] = Interrupt[4n+2]
Bits 15:13 Interrupt[IRQ] = Interrupt[4n+1]
Bits 7:5 Interrupt[IRQ] = Interrupt[4n]
Table 7.5: Priority register bit fields.
  • Table 7.5 represents the priority register bit fields against the interrupt sources. This priority register bit field is 3-bits wide which means that for an interrupt there can be eight priority levels from 000 to 111 and it can be programmed as per the need.
  • n represents the group number of priority registers, for each group n registers NVIC_PRIn can control up to 4 peripheral ranging from 4n to 4n+3.
    To understand this better just take an example, suppose that for an interrupt handler whose IRQ number is 0, in order to satisfy the equation interrupt[4n]=0 the value of n must be zero which corresponds to the NVIC_PRI0_R also this same register can configure the priority levels for 4n to 4n+3 peripherals.
  • In this case the value of n is 0 therefore the same priority level register can be used to configure the interrupts whose IRQ Number are within 4×0 to 4×0+3, which corresponds to the IRQ number 0,1,2,3.
  • In tm4c123gh6pm_startup_ccs_gcc.c file the IRQ number 0 to 3 represents the interrupt handlers for GPIOA to GPIOD respectively. In a program for each interrupt the priority level can be set in the corresponding bit fields.

Table 7.6 shows some of the priority registers on the NVIC. Each register contains an 8-bit priority field for four devices. On the TM4C micro controllers, only the top three bits of the 8-bit field are used. This allows us to specify the interrupt priority level for each device from 0 to 7, with 0 being the highest priority.

Address 31 - 29 23 - 21 15 - 13 7 - 5 Name
0xE000E400 GPIO Port D GPIO Port C GPIO Port B GPIO Port A NVIC_PRI0_R
0xE000E404 SSI0, Rx Tx UART1, Rx Tx UART0, Rx Tx GPIO Port E NVIC_PRI1_R
0xE000E408 PWM Gen 1 PWM Gen 0 PWM Fault I2C0 NVIC_PRI2_R
0xE000E40C ADC Seq 1 ADC Seq 0 Quad Encoder 0 PWM0 Gen 2 NVIC_PRI3_R
0xE000E410 Timer 0A Watchdog ADC Seq 3 ADC Seq 2 NVIC_PRI4_R
0xE000E414 Timer 2A Timer 1B Timer 1A Timer 0B NVIC_PRI5_R
0xE000E418 Comp 2 Comp 1 Comp 0 Timer 2B NVIC_PRI6_R
0xE000E41C GPIO Port G GPIO Port F Flash Control System Control NVIC_PRI7_R
0xE000E420 Timer 3A SSI1, Rx Tx UART2, Rx Tx GPIO Port H NVIC_PRI8_R
0xE000E424 CAN0 Quad Encoder 1 I2C1 Timer 3B NVIC_PRI9_R
0xE000E428 Hibernate Ethernet CAN2 CAN1 NVIC_PRI10_R
0xE000E42C uDMA Error uDMA Soft Tfr PWM Gen 3 USB0 NVIC_PRI11_R
0xE000ED20 SysTick PendSV --- Debug NVIC_SYS_PRI3_R
Table 7.6: Most popular priority registers used in the TM4C123GH6PM NVIC.
  • The interrupt number is loaded into the IPSR register. The servicing of interrupts does not set the I bit in the PRIMASK, so a higher priority interrupt can suspend the execution of a lower priority ISR.
  • If a request of equal or lower priority is generated while an ISR is being executed, that request is postponed until the ISR is completed. In particular, those devices that need prompt service should be given high priority.

Enabling and Disabling an Interrupt

Upon Reset, all the interrupts are disabled. To enable any interrupt we should:

  1. Enable the interrupt for a specific peripheral module.
    This is done with the GPIO Interrupt Mask (GPIOIM) register.
  2. Enable the interrupts at the NVIC module.
  3. Enable the interrupt globally .

Interrupt enabling with all 3 levels

Tm4c123 int enable 3level.png

Figure:Interrupt enabling with all 3 levels


Tm4c gpiom.png

Figure:GPIO Interrupt Mask (GPIOIM)

Interrupt Set Enable Register

It is the interrupt set enable register ranging from NVIC_EN0_R ... NVIC_EN3_R, each ISER register is 32 bit wide that can be used to set the interrupt against the respective IRQ numbers. Each ISER register can be used to enable 32 different types of interrupt sources. For example NVIC_EN0_R is used to enable the interrupt sources whose IRQ numbers are 0-31, similarly the interrupt sources whose IRQ numbers are 32-63 can be enabled by NVIC_EN1_R and so on. The corresponding bit field is required to be set according to the IRQ number of the interrupt sources since each register is 32 bit wide. If the interrupt source whose IRQ number is greater than 31 the corresponding bit number can be calculated by this formula:

bit number = IRQ number - 32(n-1) 

where n=1 for interrupt sources having IRQ number 0-31. Similarly n=2 for interrupt sources having IRQ number 32-63 and so on. For enabling interrupt at PF4 pin writing 1 to the bit field 30 of NVIC_EN0_R will do the same for us, as its IRQ number is 30.

To disable interrupts there are another registers: NVIC_DIS0_R to NVIC_DIS3_R (Interrupt Clear Enable). Writing zeros to the NVIC_EN0_R through NVIC_EN3_R registers has no effect. To disable interrupts we write ones to the corresponding bit in the NVIC_DIS0_R through NVIC_DIS3_R register.

Enable Register 32-Enable Bits Address
0
1
2
3
4
5
6-29
30
31
NVIC_EN0_R PORTA PORTB PORTC PORTD PORTE UART0 ... PORTF PORTG 0xE000E100
NVIC_EN1_R PORTH UART2 SSI1 Timer3A Timer3B I2C1 ... UART6 UART7 0xE000E104
NVIC_EN2_R ... ... ... ... I2C2 I2C3 ... WTimer0A WTimer0B 0xE000E108
NVIC_EN3_R WT1A WT1B WT2A WT2B WT3A WT3B ... GPIOQ2 GPIOQ3 0xE000E10C
Table 7.7: Relationship between each bit on interrupt enable register and related peripheral.

Global interrupt enable/disable

Global interrupt enable/disable allows us with a single instruction to mask all interrupts during the execution of some critical task such as manipulating a common pointer shared by multiple threads. In ARM Cortex M, we do the global enable/disable of interrupts with assembly language instructions of CPSID I (Change processor state-disable interrupts) and CPSIE I (Change processor state-enable interrupts). In C language we use inline assembly language instructions:

void DisableInterrupts(void){__asm ("CPSID  I\n");}
void EnableInterrupts(void){__asm  ("CPSIE  I\n");}

Initialize and Configure GPIO Interrupt Control Registers

To initialize and configure GPIO interrupt controls, one needs to program the GPIOIS, GPIOIBE, GPIOEV, and GPIOIM registers to configure the type, event, and mask of the interrupts for each port. The following steps should be used to do this initialization and configuration process:

  • Configure the GPIOIM register to disable (mask) the undesired pins.
  • Configure the GPIOIS register to indicate the interrupt-triggering type, edge, or level.
  • Configure the GPIOIBE register to indicate if this interrupt is triggered by both edges.
  • Reset the GPIORIS register to 0 to make it ready to set a flag if any interrupt occurred.
  • Configure the GPIOIM register to enable (unmask) the desired pins.

How to configure and set up an interrupt and its handler

Now let’s provide an example to illustrate how to configure and set up an interrupt and its handler based on the above Tables. For example, we want to set up and configure an interrupt for GPIO PortF. Perform the following operations to complete this job:

  1. Find the IRQ number for this interrupt from Table 7.3. The IRQ number for the GPIO PortF is 30.
  2. Based on Table 7.6, obtain the group number of the priority register (n). The IRQ number is 30. In order to make the equation 30 = interrupt[4n + 2] hold, n must be 7. This means that we need to use group 7 priority register NVIC_PRI7_R with bits 23-21 to configure the priority level for the GPIO PortF. Since the IRQ number of this port is 30, we can set the priority level for this port as 5, (101B), in bits 23-21 on the NVIC_PRI7_R. This setup can be written as NVIC_PRI7_R = (NVIC_PRI7_R & 0xFF00FFFF) | 0x00A00000 in the user’s program.
  3. Based on Table 7.7, obtain the bit field in the NVIC Set Enable Register to enable this port. Since the IRQ number of the Port F is 30, the bit 30 in the NVIC_EN0_R register should be set to 1 to enable this port. This setup can be written as NVIC_EN0_R = 0x40000000.
  4. Open tm4c123gh6pm_startup_ccs_gcc.c for editing. This file contains the vector table among other things. Open the file and look for the GPIO PortF vector. You need to carefully find the appropriate vector position and replace IntDefaultHandler with the name of your Interrupt handler.
  5. After going through all these steps an EnableInterrupts() function is called to perform the global interrupt enable function. Note that we have to enable the pull up at PF4 in order to provide high or low input signal.
  6. It is critical that the interrupt handler clears the interrupt flag before returning from interrupt handler. Otherwise the interrupt appears as if it is still pending and the interrupt handler will be executed again and again forever and the program hangs. The PORTF interrupt flag is cleared by writing a 1 to the bit that corresponds to the pin that triggered the interrupt in the GPIO Interrupt Clear Register (GPIOICR). In the case of SW1 (PF4), the interrupt flag is cleared by:
GPIO_PORTF_ICR_R = 0x10;

Note:The ARM Cortex writes are buffered. That means a write does not take effect immediately. It may take many clock cycles before the write to ICR to clear the interrupt flags. When return from interrupt handler and the interrupt flag is still pending, the interrupt handler will be executed again. One way to ensure that interrupt flags are cleared before returning from interrupt handler is to perform a read to force the write to take effect.


  1. /* sw1_int.c
  2.  *
  3.  * Runs on EK-TM4C123GXL LaunchPad
  4.  *
  5.  * GPIO PORTF interrupt that will toggle the on board Blue LED
  6.  * on rising edge whenever a user switch (SW1) is pressed.
  7.  *
  8.  */
  9. #include <stdint.h>
  10. #include "inc/tm4c123gh6pm.h"
  11.  
  12. void DisableInterrupts(void);
  13. void EnableInterrupts(void);
  14. void WaitForInterrupt(void);
  15. void GPIOPortF_Init(void);
  16. void GPIOPortF_Handler(void);
  17.  
  18. void GPIOPortF_Init(void)
  19. {
  20.  
  21.     SYSCTL_RCGC2_R |= 0x00000020;   /* 1) activate clock for Port F */
  22.  
  23.     GPIO_PORTF_LOCK_R = 0x4C4F434B; /* 2) unlock GPIO Port F */
  24.     GPIO_PORTF_CR_R = 0x1F;         /* allow changes to PF4-0 */
  25.     GPIO_PORTF_AMSEL_R = 0x00;      /* 3) disable analog on PF */
  26.     GPIO_PORTF_PCTL_R = 0x00000000; /* 4) PCTL GPIO on PF4-0 */
  27.     GPIO_PORTF_DIR_R = 0x0E;        /* 5) PF4,PF0 in, PF3-1 out */
  28.     GPIO_PORTF_AFSEL_R = 0x00;      /* 6) disable alt funct on PF7-0 */
  29.     GPIO_PORTF_PUR_R = 0x11;        /* enable pull-up on PF0 and PF4 */
  30.     GPIO_PORTF_DEN_R = 0x1F;        /* 7) enable digital I/O on PF4-0 */
  31.  
  32.     GPIO_PORTF_IS_R &= ~0x10;       /*  PF4 is edge-sensitive */
  33.     GPIO_PORTF_IBE_R &= ~0x10;      /*  PF4 is not both edges */
  34.     GPIO_PORTF_IEV_R &= ~0x10;      /*  PF4 falling edge event */
  35.     GPIO_PORTF_ICR_R = 0x10;        /*  Clear flag4 */
  36.     GPIO_PORTF_IM_R |= 0x10;        /*  arm interrupt on PF4 */
  37.     NVIC_PRI7_R = (NVIC_PRI7_R & 0xFF1FFFFF) | 0x00A00000; /*  priority 5 */
  38.     NVIC_EN0_R = 0x40000000;        /*  Enable interrupt 30 in NVIC */
  39.  
  40.     EnableInterrupts();             /* Enable global Interrupt flag (I) */
  41. }
  42.  
  43. void GPIOPortF_Handler(void)
  44. {
  45.     volatile int readback;
  46.  
  47.     GPIO_PORTF_ICR_R = 0x10;        /* clear PF4 int */
  48.     GPIO_PORTF_DATA_R ^= (1<<2);    /* toggle Blue LED */
  49.     readback = GPIO_PORTF_ICR_R;    /* a read to force clearing of interrupt flag */
  50.     readback = readback;
  51. }
  52.  
  53. int main(void)
  54. {
  55.     GPIOPortF_Init();               /* initialize GPIO Port F interrupt */
  56.  
  57.     while(1) {
  58.         WaitForInterrupt();
  59.     }
  60. }
  61.  
  62. /*********** DisableInterrupts ***************
  63. *
  64. * disable interrupts
  65. *
  66. * inputs:  none
  67. * outputs: none
  68. */
  69.  
  70. void DisableInterrupts(void)
  71. {
  72.     __asm ("    CPSID  I\n");
  73. }
  74.  
  75. /*********** EnableInterrupts ***************
  76. *
  77. * emable interrupts
  78. *
  79. * inputs:  none
  80. * outputs: none
  81. */
  82.  
  83. void EnableInterrupts(void)
  84. {
  85.     __asm  ("    CPSIE  I\n");
  86. }
  87.  
  88. /*********** WaitForInterrupt ************************
  89. *
  90. * go to low power mode while waiting for the next interrupt
  91. *
  92. * inputs:  none
  93. * outputs: none
  94. */
  95.  
  96. void WaitForInterrupt(void)
  97. {
  98.     __asm  ("    WFI\n");
  99. }

1. Sample program (SW1 Interrupt)

  • Create a CCS Project with "Empty Project"
  • Download sw1_int.c program and Add this file to your project.
  • Open tm4c123gh6pm_startup_ccs_gcc.c for editing and replace IntDefaultHandler with the GPIOPortF_Handler in the GPIO PortF vector position.
  • Build and Debug (Run) the program.
    Run this code and load it into the flash of microcontroller. You will see that the blue LED gets turned on when user switch is pressed first then if it is pressed again it gets turned off.

2. GPIOF interrupt from SW1 and SW2

  • Rewrite sw1_int.c program to distinguish the interrupt pin. Toggle Red LED on PF1 continuously. Upon pressing either SW1 or SW2, the Green or Blue LED will toggle three times. main program toggles Red LED while waiting for interrupt from SW1 or SW2.

3. Interrupt from External Source

  • Write a program to toggle an LED at the same rate as the input frequency by connecting a square wave of 3.3V to a pin of Portx. (You can make it to toggle on positive or negative edge)
    Hint: Configure PORTD6 to trigger interrupt by falling edge. In the interrupt handler, the green LED (PF3) is toggled. The green LED should have half the frequency of the input signal at PORTD6. IRQ3 is assigned to PORTD6.

See Also

  1. EK-TM4C123GXL LaunchPad Board
  2. GPIO Programming



This is the SysTick panel of the basic tab example. This is the second panel of the basic tab example.

This is the UART panel of the basic tab example. This is the third panel of the basic tab example.

This is the GPTM panel of the basic tab example. This is the fourth panel of the basic tab example.

This is the PWM panel of the basic tab example. This is the third panel of the basic tab example.

This is the ADC panel of the basic tab example. This is the fourth panel of the basic tab example.