Actions

EmSys

Difference between revisions of "Lab Practicals Using TivaC LaunchPad Board"

From EdWiki

m (On-Chip Peripheral Programming)
m (On-Chip Peripheral Programming)
Line 210: Line 210:
 
  </div>
 
  </div>
 
</div>
 
</div>
<!-- GPIO Sub Tabs Ends Here -->
+
<!-- UART Sub Tabs Ends Here -->
 
   </div>
 
   </div>
 
   <div class="content" id="GPTMTab">
 
   <div class="content" id="GPTMTab">
    <p>This is the GPTM panel of the basic tab example. This is the fourth panel of the basic tab example.</p>
+
<!-- GPTM Sub Tabs Start Here -->  
 +
<ul class="tabs" data-tab>
 +
  <li class="tab-title active">Overview</li>
 +
  <li class="tab-title">GPIO Pins</li>
 +
  <li class="tab-title">GPTM Int</li>
 +
  <li class="tab-title">Tasks</li>
 +
</ul>
 +
<div class="tabs-content">
 +
  <div class="content active" id="GPTMSubTab1">
 +
{{EmSys:TM4C123 Timer Programming}}
 +
  </div>
 +
  <div class="content" id="GPTMSubTab2">
 +
{{EmSys:TM4C123 Use of GPTM with GPIO Pins}}
 +
  </div>
 +
  <div class="content" id="GPTMSubTab3">
 +
{{EmSys:TM4C123 GPTM Interrupt Programming}}
 +
  </div>
 +
  <div class="content" id="GPTMSubTab4">
 +
=== 1. Build a General Purpose Timer Project ===
 +
 
 +
Use GPTM block 0 Timer A (Timer0A) as a 16-bit count-down counter to periodically generate a timeout interrupt to turn on three LEDs, PF3∼PF1, via GPIO Port F. The input clock to the timer is the 16 MHz system clock, and the period to be counted in the Timer0A counter is 65.536 ms.
 +
 
 +
To perform this periodic interrupt for each 65.536 ms, one needs to:
 +
# Enable and clock the Timer0A for GPTM Block 0.
 +
# Enable and clock the GPIO Port F.
 +
# Disable the Timer0A module before any configuration can be performed.
 +
# Configure the Timer0A to work as a 16-bit count-down periodic counter.
 +
# Load 65535 (65536 – 1) into the GPTMTAILR register as the start value since we want to get the maximum period of time, which is 65.536 ms, for each period.
 +
# Load 15 (16 – 1) into the GPTMTAPR register as a prescale value. After this 16 MHz system clock is divided by this prescaler (16), the working clock for this counter is 1 MHz with a 1-μs period.
 +
# Clear any previous timeout interrupt for Timer0A by writing 1 to an appropriate bit in the GPTMICR register.
 +
# Enable Timer0A timeout interrupt by writing 1 to an appropriate bit in the GPTMIMR register.
 +
# Use NVIC_PRI4_R (Bit 31 - 29 ) to set the interrupt priority level as 3 for the Timer0A.
 +
# Use NVIC_EN0_R (IRQ19) to enable the timeout interrupt for the Timer0A.
 +
# Enable the Timer0A module after these configuration and the Timer0A begins to count.
 +
# Use EnableInterrupts() function to globally enable all interrupts.
 +
# Use an infinitive while() loop to wait for any interrupt coming.
 +
 
 +
In addition to the main program, one also needs to build the Timer0A interrupt handler:
 +
# Clear the timeout interrupt for Timer0A by writing 1 to an appropriate bit in the GPTMICR register to enable it to be generated in the future.
 +
# Turn on the related LED via GPIO Port F.
 +
 
 +
=== 2. Use Timer1A and Timer2A timeout events to trigger interrupts ===
 +
* Configure Timer1A to timeout once every second. In the interrupt handler, toggle the red LED.
 +
* Configure Timer2A to timeout at 10 Hz. In the interrupt handler, toggle the green LED.
 +
<!--
 +
* The infinite loop in the main program should blink the blue LED while the interrupts are going on.
 +
-->
 +
 
 +
=== 3. Measure pulse width using interrupts with a precision of 24 bits and a resolution of 12.5 ns ===
 +
* The pulse width measurement is performed from rising edge to falling edge.
 +
* The resolution is 12.5 ns, determined by the system bus clock.
 +
* The range is about 25 ns to 209ms with no overflow checking.
 +
'''Hints:'''
 +
* The digital-level input signal is connected to two input capture pins, CCP0 and CCP1.
 +
* The bus clock is selected to be 80 MHz so the measurement resolution will be 12.5 ns.
 +
* The rising edge time will be measured by Timer0B without the need of an interrupt and the falling edge interrupts will be handled by Timer0A.
 +
* The pulse width is calculated as the difference in TIMER0_TBR_R - TIMER0_TAR_R latch values.
 +
 
 +
 
 +
[[image:tm4c_measuring_pulse_width.png|center]]
 +
 
 +
=== 4. Measure the period of a square wave input signal ===
 +
 
 +
'''Hint''': To measure the period of a signal we must measure the time between two falling or rising edges.
 +
 
 +
[[image:tm4c_measuring_square_wave.png|center]]
 +
<div style="text-align: center;">'''Figure 10.5''': Measuring Period and Pulse Width </div>
 +
 
 +
=== 5. Generate PWM ===
 +
* Generate an output PWM with a 1-ms period and a 66% duty cycle (TAPWML = 0) assuming a 50 MHz input clock. The duty cycle could be 33% if the TAPWML = 1.
 +
*:'''Hint:'''
 +
*# The start value is GPTMTAILR = 0xC350 and the match value in GPTMTAMATCHR is 0x411A.
 +
*# Use PLL
 +
*# Use Timer A
 +
 
 +
[[image:task_timer_pwm.png|center]]
 +
  </div>
 +
</div>
 +
<!-- GPTM Sub Tabs Start Here -->
 
   </div>
 
   </div>
 
   <div class="content" id="PWMTab">
 
   <div class="content" id="PWMTab">

Revision as of 07:09, 2 March 2020

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



Using Systick Timer with TM4C123GH6PM Launchpad

So far we have learned that how to program general purpose input output(GPIO) of ARM Cortex M-4. But we have not generated the delay in micro controller. In this section we will generate delay using different methods and blink on board LEDs. There are two types of delays that can be generated by our program:

  1. Software delay
  2. Hardware delay

Software delay

This type of delay is nothing but making the controller busy, doing the task which will occupy a certain duration. For example if we want our friend to wait for us then instead of telling him to wait we can simply engage him in other task. But the generated time may or may not be so accurate.

Example: In C code if we can use this for loop for generating a delay of 1 second.

  1.  void delay_1sec(void)
  2.  {
  3.     for( unsigned long i = 0; i <= 3000000; i++ )
  4.         ;
  5.  }

This method doesn’t generate the accurate time delay, but approximate. For generation of accurate delay in microsecond we prefer hardware delay.

Hardware delay

The hardware delay is most precise method to generate delay. In this method we use timer which is the most popular and useful feature of microcontrollers. Generally delay with timer is like waiting a bucket to be empty if we make a small hole to leak its filled liquid more the liquid more time it will take to empty the bucket. In this article, we are going to use a special timer called systick timer. In our micro controller we have six 64 bit and six 32 bit timer excluding systick timer. This timer is very useful and plays very important role in RTOS design. We will see other timers later. In our micro controller, Systick timer is 24 bit wide. For the generation of delay, at first we need to make sure that our controller is working on the clock frequency as we are expecting. This step is required to select the clock source only at external crystal without PLL.

SysTick Timer

SysTick is a simple counter that we can use to create time delays and generate periodic interrupts. It exists on all Cortex-M microcontrollers, so using SysTick means the system will be easy to port to other microcontrollers.

SysTick Timer Internal Structure

As we learned earlier that modifying registers are the key for configuration and desired functionality. Hence systick timer can be used by modifying these registers.

  1. Systick Reload value (STRELOAD)
  2. Systick Control and Status Register (STCTRL)
  3. Systick Current Value (STCURRENT)

Systick Reload Value Register

This register acts like a bucket filled with a liquid that will be empty after some time duration and we will get acknowledgement by a change in flag bit in STCTRL Register. This register is 24 bit wide.
Tm4c systick streload r.png

Since this register is 24 bit wide it can store upto 0xFFFFFF or 16777215. when we load any value into this register and trigger the timer it starts to count down and when the value reaches to 0 it sets the COUNT FLAG. We will see how to reload and check flag bit in the next few steps.

Systick control and Status register

This register is shown in the following figure
Tm4c systick stctl r.png
Bit Name Description
0 Enable Enable
0: the counter is disabled
1: enables SysTick to begin counting Down
1 INTEN Interrupt Enable
0: Interrupt generation is disabled
1: when SysTick counts to 0 an interrupt is generated
2 CLK_SRC Clock Source
0: Precision internal oscillator (PIOSC) divided by 4
1: System clock
16 COUNT Count Flag
0: the SysTick has not counted Down to zero since the last time this bit was read
1: the SysTick has counted Down to Zero
Note: this flag is cleared by reading the STRCTL or writing to STCURRENT Register

We need to set our main clock to system clock by setting CLK_SRC to 1. And we don’t want interrupt method so INTEN bit will be 0. Now we are going to trigger our timer by writing ENABLE bit 1 so writing 0x5 will trigger our timer at the same time it will also set the configuration. Now the loaded value will be started to count down. When the timer gets rollover the bit 16 will set to one. hence we need to monitor 16th bit.

If INTEN=1, when the COUNT flag is set, it causes an interrupt via the NVIC. INTEN is D1 of the STCTRL register.

Systick Register Summary

Address 31-24 23-17 16 15-13 2 1 0 Name
$E000E010 o 0 COUNT 0 CLK_SRC INTEN ENABLE NVIC_ST_CTRL_R
$E000E014 o 24-bit RELOAD value NVIC_ST_RELOAD_R
$E000E018 o 24-bit CURRENT value of SysTick counter NVIC_ST_CURRENT_R

Delay time calculation

Since we are working with external clock i.e. 16 MHz, each pulse generated by the clock source will have:

1/XTAL frequency = 1/(16*10^6) = 62.5ns time period. 

So if we load 253 into the RELOAD register and trigger the counter it will count down with next pulse and will take 62.5ns to change its value from 253 to 252. Hence, In order to generate the delay, we can calculate the approximate value that has to be loaded into this register by the formula-

Reload Value = XTAL*Time delay

one extra clock delay is already included to set the flag for rollover, hence we get one extra clock delay. By subtracting by one will give exact time delay.

Reload Value = (XTAL*Time Delay)-1

Remember that in one shoot, it can only take 0xFFFFFF maximum value. Therefore in one shoot, we can only generate maximum of Time delay

TimeDelay = (ReloadValue+1)/XTAL=16777215+(1/(16*10^6))
TimeDelay = 1.048575937 sec.

Example: For generating 1 sec of delay the value that has to be loaded into the RELOAD Register

Reload Value = (XTAL*Time delay)-1
Reload Value = (16*10^6*1)-1
Reload Value = 15999999

SysTick timer Initialization

There are four steps to initialize the SysTick timer.

  1. Clear the ENABLE (NVIC_ST_CTRL_R) bit to turn off SysTick during initialization.
  2. Set the RELOAD (NVIC_ST_RELOAD_R) register.
  3. Write to the NVIC_ST_CURRENT_R value to clear the counter.
  4. Write the desired mode to the control register, NVIC_ST_CTRL_R.
    • Set the CLK_SRC bit specifying the core clock will be used.
    • We must set CLK_SRC=1 bit specifying the core clock will be used, because CLK_SRC=0 external clock mode is not implemented on the LM3S/TM4C family.
    • Set INTEN (NVIC_ST_CTRL_R) to enable interrupts, but in this first example we clear INTEN so interrupts will not be requested.
    • Set the ENABLE (NVIC_ST_CTRL_R) bit so the counter will run.

When the CURRENT (NVIC_ST_CURRENT_R) value counts down from 1 to 0, the COUNT flag is set. On the next clock, the CURRENT is loaded with the RELOAD value. In this way, the SysTick counter (CURRENT) is continuously decrementing. If the RELOAD value is n, then the SysTick counter operates at modulo n+1 (...n, n-1, n-2 ... 1, 0, n, n-1, ...). In other words, it rolls over every n+1 counts.

The COUNT flag could be configured to trigger an interrupt. However, in this first example interrupts will not be generated.

Source Code

Delay in 62.5ns units

  1. /* delay is in 62.5ns units */
  2. void SysTick_Wait(uint32_t delay)
  3. { 
  4.     NVIC_ST_CTRL_R = 0;            /* (1) disable SysTick during setup */
  5.     NVIC_ST_RELOAD_R = delay-1;    /* (2) number of counts to wait */
  6.     NVIC_ST_CURRENT_R = 0;         /* (3) any value written to CURRENT clears */
  7.     NVIC_ST_CTRL_R |= 0x5;         /* (4) enable SysTick with core clock */
  8.  
  9.     while((NVIC_ST_CTRL_R&0x00010000)==0) {
  10.         ;                          /* wait for COUNT flag */
  11.     }
  12. }


One Second Delay

  1. void One_Second_Delay(void)
  2. {
  3.     NVIC_ST_CTRL_R = 0;            /* disable SysTick during setup */
  4.     NVIC_ST_RELOAD_R = 15999999;    /* Reload Value goes here */
  5.     NVIC_ST_CTRL_R |= 0x5;          /* enable SysTick with core clock */
  6.     while( (NVIC_ST_CTRL_R & (1<<16) ) == 0)
  7.         ;                           /* Monitoring bit 16 to be set */
  8.     NVIC_ST_CTRL_R = 0;             /* Disabling SysTick Timer */
  9. }


See Also

Using SysTick with Interrupt

In the previous article, we used SysTick in a blocking mode. In this article, we will use SysTick with interrupt.

The SysTick interrupt can be used to initiate an action on a periodic basis. This action is performed internally at a fixed rate without external signal. For example, in a given application we can use SysTick to read a sensor every 200 msec. SysTick is used widely for an operating system so that the system software may interrupt the application software periodically (often 10 ms interval) to monitor and control the system operations.

If INTEN=1, when the COUNT flag is set, it causes an interrupt via the NVIC. INTEN is D1 of the STCTRL register. Examining interrupt vector table for ARM Cortex, we see the SysTick is the interrupt #15 assigned to the system itself.

Source Code

  1. /* systick_int.c
  2.  *
  3.  * Toggle the red LED using the SysTick interrupt
  4.  *
  5.  * This program sets up the SysTick to interrupt at 1 Hz.
  6.  * The system clock is running at 16 MHz.
  7.  * 1sec/62.5ns = 16,000,000 for RELOAD register.
  8.  * In the interrupt handler, the red LED is toggled.
  9. */
  10.  
  11. #include <stdint.h>
  12. #include "inc/tm4c123gh6pm.h"
  13.  
  14. void enable_irq(void);
  15.  
  16. int main (void)
  17. {
  18.     /* enable clock to GPIOF at clock gating control register */
  19.     SYSCTL_RCGC2_R |= 0x20;
  20.     /* enable the GPIO pins for the LED (PF3, 2, 1) as output */
  21.     GPIO_PORTF_DIR_R = 0x0E;
  22.     /* enable the GPIO pins for digital function */
  23.     GPIO_PORTF_DEN_R = 0x0E;
  24.  
  25.     /* Configure SysTick */
  26.     NVIC_ST_RELOAD_R = 16000000-1;  /* reload with number of clocks per second */
  27.     NVIC_ST_CTRL_R = 7;             /* enable SysTick interrupt, use system clock */
  28.  
  29.     enable_irq();                   /* global enable interrupt */
  30.  
  31.     while(1) {
  32.         ;
  33.     }
  34. }
  35.  
  36. void SysTick_Handler(void)
  37. {
  38.     GPIO_PORTF_DATA_R ^= 2;         /* toggle the red LED */
  39. }
  40.  
  41. /* global enable interrupts */
  42. void inline enable_irq(void)
  43. {
  44.     __asm  ("    CPSIE  I\n");
  45. }

The above program uses the SysTick to toggle the red LED of PF1 every second. We need the RELOAD value of 16,000,000-1 since 1sec / 62.5nsec = 16,000,000. We assume the CPU clock is 16MHz (1/16MHz=62.5ns). The COUNT flag is raised every 16,000,000 clocks and an interrupt occurs. Then the RELOAD register is loaded with 16,000,000-1 automatically.

Notice the enabling of interrupt in SysTick Control register. Since SysTick is an internal interrupt, the COUNT flag is cleared automatically when the interrupt occurs. Also notice the SysTick is part of INT1-INT15 and not part of IRQ. For this reason we must use the CTLR register to enable it.

Note: Open tm4c123gh6pm_startup_ccs_gcc.c for editing. This file contains the vector table among other things. Open the file and look for the SysTick vector. You need to carefully find the appropriate vector position and replace IntDefaultHandler with the name of your Interrupt handler (SysTick_Handler).

See Also

  1. We used Software delay in our blinky, read_sw1, and read_sw2 programs. Replace Software Delay with SysTick Timer Delay.
  2. If we are sure the execution speed of our function is less than (224 bus cycles), we can use this timer to collect timing information with only a modest amount of intrusiveness. Use the SysTick timer to measure the Software Delay functions we used in the earlier programs.
  3. If we activate the PLL and change the bus clock to 50 MHz (20ns), what is the longest elapsed time we could measure?

UART in TM4C123GH6PM Launchpad

A serial port programming is a method of transferring data serially by the means of a few wire, unlike a parallel port which requires many wires for data transfer and limited to a short distance, serial port programming can be used for transferring the data to a larger distance. The advantage of using this serial port is that it is very cheap as compare to the parallel port since it requires a single data line for data transmission making the hardware configuration easy and simple.

Serial data communication uses two methods, asynchronous and synchronous. The synchronous method transfers a block of data (characters) at a time while the asynchronous transfers a single byte at a time.

In this article we are going to use a UART module for serial port communication that uses two pins i.e. RX and TX for data transfer but before proceeding you should have the knowledge of following terms related to the UART.

Half and full-duplex transmission

In data transmission, a duplex transmission is one in which the data can be transmitted and received. This is in contrast to a simplex transmissions such as printers, in which the computer only sends data. Duplex transmissions can be half or full duplex. If data is transmitted one way at a time, it is referred to as half duplex. If the data can go both ways at the same time, it is full duplex. Of course, full duplex requires two wire conductors for the data lines (in addition to ground), one for transmission and one for reception, in order to transfer and receive data simultaneously.

Asynchronous serial communication and data framing

The data coming in at the receiving end of the data line in a serial data transfer is all 0s and 1s; it is difficult to make sense of the data unless the sender and receiver agree on a set of rules, a protocol, on how the data is packed, how many bits constitute a character, and when the data begins and ends.

Start and stop bits

Asynchronous serial data communication is widely used for character-oriented transmissions. In the asynchronous method, each character, such as ASCII characters, is packed between start and stop bits. This is called framing. The start bit is always one bit but the stop bit can be one or two bits. The start bit is always a 0 (low) and the stop bit(s) is 1 (high). For example, look at the following figure where the ASCII character "A", binary 0100 0001, is framed between the start bit and 2 stop bits. Notice that the LSB is sent out first.

Uart framing ascii.png

In the above figure, when there is no data transfer, the signal stays 1 (high), which is referred to as MARK. The 0 (low) is referred to as SPACE. Notice that the transmission begins with a start bit followed by D0, the LSB, then the rest of the bits until the MSB (D7), and finally, the 2 stop bits indicating the end of the character "A".

In asynchronous serial communications, peripheral chips can be programmed for data that is 5, 6, 7, or 8 bits wide. While in older systems ASCII characters were 7-bit, the modern systems usually send non-ASCII 8-bit data. The old Baud code uses 5- or 6-bit characters but they are rarely seen these days even though most of the hardware still supporting them. In some older systems, due to the slowness of the receiving mechanical device, 2 stop bits were used to give the device sufficient time to organize itself before transmission of the next byte. However, in modern PCs the use of 1 stop bit is common. Assuming that we are transferring a text file of ASCII characters using 1 stop bit, we have a total of 10 bits for each character since 8 bits are for the ASCII code, and 1 and 2 bits are for start and stop bits, respectively. Therefore, for each 8-bit character there are an extra 2 bits, or 25% overhead. (2/8x100=25%)

Parity bit

In some systems in order to maintain data integrity, the parity bit of the character byte is included in the data frame. This means that for each character (7- or 8-bit, depending on the system) we have a single parity bit in addition to start and stop bits. The parity bit may be odd or even. In the case of an odd-parity the number of data bits, including the parity bit, has an odd number of 1s. Similarly, in an even-parity the total number of bits, including the parity bit, is even. For example, the ASCII character "A", binary 0100 0001, has 0 for the even-parity bit. UART chips allow programming of the parity bit for odd-, even-, and no-parity options, as we will see in the next section. If a system requires the parity, the parity bit is transmitted after the MSB, and is followed by the stop bit.

Data transfer rate

The rate of data transfer in serial data communication is stated in bps (bits per second). Another widely used terminology for bps is Baud rate. However, the baud and bps rates are not necessarily equal. This is due to the fact that baud rate is defined as number of signal changes per second. In modems, it is possible for each signal to transfer multiple bits of data. As far as the conductor wire is concerned, the baud rate and bps are the same.

Baud Rate

The baud rate is defined as the rate of data transfer in serial communication, we can choose the desired baud rate for our data transmission as specified in the data sheet, later we will show you how to select this baud rate for our micro-controller.

RS232 and other serial I/O standards

To allow compatibility among data communication equipment made by various manufacturers, an interfacing standard called RS232 was set by the Electronics Industries Association (EIA) in 1960.

Today, RS232 is the most widely used serial I/O interfacing standard. However, since the standard was set long before the advent of the TTL logic family, the input and output voltage levels are not TTL compatible. In the RS232 at the receiver, a 1 is represented by –3 to –25 V, while the 0 bit is +3 to +25 V, making –3 to +3 undefined.

For this reason, to connect any RS232 to a TTL-level chip (microprocessor or UART) we must use voltage converters such as MAX232 or MAX233 to convert the TTL logic levels to the RS232 voltage level, and vice versa. MAX232 and MAX233 IC chips are commonly referred to as line drivers.

Uart max232 2to uc.png

RS232 pins

The table below provides the pins and their labels for the RS232, commonly referred to as the DB-9 connector.

Uart db9 con.png
Pin Description
1 Data carrier detect (DCD)
2 Received data (RxD)
3 Transmitted data (TxD)
4 Data terminal ready (DTR)
5 Signal ground (GND)
6 Data set ready (DSR)
7 Request to send (RTS)
8 Clear to send (CTS)
9 Ring indicator (RI)

Data communication classification

Current terminology classifies data communication equipment as DTE (data terminal equipment) or DCE (data communication equipment). DTE refers to terminals and computers that send and receive data, while DCE refers to communication equipment, such as modems, that is responsible for transferring the data. Notice that all the RS232 pin function definitions of from the above table are from the DTE point of view.

The simplest connection between two PCs (DTE and DTE) requires a minimum of three pins, TxD, RxD, and ground. Notice that the connection between two DTE devices, such as two PCs, requires pins 2 and 3 to be interchanged. In looking at the following figure, keep in mind that the RS232 signal definitions are from the point of view of DTE.

Uart dte dce and dce dce con.png
Figure: DTE-DCE and DTE-DTE Connections

RS232 handshaking signals

To ensure fast and reliable data transmission between two devices, the data transfer must be coordinated. Some of the pins of the RS-232 are used for handshaking signals. They are described below. Due to the fact that in serial data communication the receiving device may have no room for the data there must be a way to inform the sender to stop sending data. So some of these handshaking lines may be used for flow control tool

  • DTR (data terminal ready)
    When the terminal (or a PC COM port) is turned on, after going through a self-test, it sends out signal DTR to indicate that it is ready for communication. If there is something wrong with the COM port, this signal will not be activated. This is an active-low signal and can be used to inform the modem that the computer is alive and kicking. This is an output pin from DTE (PC COM port) and an input to the modem.
  • DSR (data set ready)
    When a DCE (modem) is turned on and has gone through the self-test, it asserts DSR to indicate that it is ready to communicate. Therefore, it is an output from the modem (DCE) and an input to the PC (DTE). This is an active-low signal. If for any reason the modem cannot make a connection to the telephone, this signal remains inactive, indicating to the PC (or terminal) that it cannot accept or send data.
  • RTS (request to send)
    When the DTE device (such as a PC) has a byte to transmit, it asserts RTS to signal the modem that it has a byte of data to transmit. RTS is an active-low output from the DTE and an input to the modem.
  • CTS (clear to send)
    In response to RTS, when the modem has room for storing the data it is to receive, it sends out signal CTS to the DTE (PC) to indicate that it can receive the data now. This input signal to the DTE is used by the DTE to start transmission.
  • CD (carrier detect, or DCD, data carrier detect)
    The modem asserts signal DCD to inform the DTE (PC) that a valid carrier has been detected and that contact between it and the other modem is established. Therefore, DCD is an output from the modem and an input to the PC (DTE).
  • RI (ring indicator)
    An output from the modem (DCE) and an input to a PC (DTE) indicates that the telephone is ringing. It goes on and off in synchronization with the ringing sound. Of the six handshake signals, this is the least often used, due to the fact that modems take care of answering the phone. However, if in a given system the PC is in charge of answering the phone, this signal can be used.

From the above description, PC and modem communication can be summarized as follows:
While signals DTR and DSR are used by the PC and modem, respectively, to indicate that they are alive and well, it is RTS and CTS that actually control the flow of data. When the PC wants to send data it asserts RTS, and in response, if the modem is ready (has room) to accept the data, it sends back CTS. If, for lack of room, the modem does not activate CTS, the PC will deassert DTR and try again. RTS and CTS are also referred to as hardware control flow signals.

Uart null modem con.png
Figure: Null Modem Connection with Flow Control Signals


EK-TM4C123GXL Launchpad UART Programming

Many of the TI ARM chips come with up to eight on-chip UART ports. They are designated as UART0 - UART7. In the EK-TM4C123GXL LaunchPad board, the UART0 port is connected to the ICDI (In-Circuit Debug Interface), which is connected to a USB connector. This ICDI USB connection contains three distinct functions:

  1. Programming (downloading) using LM Flash Programming software
  2. Debugging using JTAG (Stellaris In-Circuit Debug Interface)
  3. To use as a virtual COM port

Virtual COM Port

  • When the USB cable connects the EK-TM4C123GXL LaunchPad board, the device driver at the host PC establishes a virtual connection between the PC and the UART0 of the TM4C123GH6PM micro controller.
  • On the EK-TM4C123GXL LaunchPad, the connection appears as UART0 (PA0-PA1).
  • On the host PC, it appears as a COM (/dev/ttyACM0) port and will work with communication software on the PC such as a terminal emulator (gtkterm, PuTTY, minicom, etc).
  • It is called a virtual connection because there is no need for an additional cable to make this connection.

UART Base Addresses

TI TM4C123GH6PM micro controller can have up to 8 UART ports. They are designated as UART0 to UART7. The following shows their Base addresses in the memory map

  • UART0 base: 0x4000.C000
  • UART1 base: 0x4000.D000
  • UART2 base: 0x4000.E000
  • UART3 base: 0x4000.F000
  • UART4 base: 0x4001.0000
  • UART5 base: 0x4001.1000
  • UART6 base: 0x4001.2000
  • UART7 base: 0x4001.3000

UART Register Map

Name Offset Tivaware Name Description
UARTDIR 0x000 UARTn_DR_R UART Data
UARTRSR
USRTECR
0x004 UARTn_RSR_R
UARTn_ECR_R
UART Receive Status
UARTError Clear
UARTFR 0x018 UARTn_FR_R UART Flag
UARTILPR 0x020 UARTn_ILPR_R UART IrDA Low-Power Register
UARTIBRD 0x024 UARTn_IBRD_R UART Integer Baud-Rate Divisor
UARTFBRD 0x028 UARTn_FBRD_R UART Fractional Baud-Rate Divisor
UARTLCRH 0x02C UARTn_LCRH_R UART Line Control
UARTCTL 0x030 UARTn_CTL_R UART Control
UARTIFLS 0x034 UARTn_IFLS_R UART Interrupt FIFO Level Select
UARTIM 0x038 UARTn_IM_R UART Interrupt Mask
UARTRIS 0x03C UARTn_RIS_R UART Raw Interrupt Status
UARTMIS 0x040 UARTn_MIS_R UART Masked Interrupt Status
UARTICR 0x044 UARTn_ICR_R UART Interrupt Clear
UARTDMACTL 0x048 UARTn_DMACTL_R UART DMA Control
UART9BITADDR 0x0A4 UARTn_9BITADDR_R UART 9-Bit Self Address
UART9BITAMASK 0x0A8 UARTn_9BITAMASK_R UART DMA Control
UARTPP 0xFC0 UARTn_PP_R UART Peripheral Properties
UARTCC 0xFC8 UARTn_CC_R UART Clock Configuration
where n = 0 to 7

UART Registers Setup

There are many special function registers associated with each of the above UARTs. We will be using the UART0 as an example since a virtual connection is available on the TI Tiva LaunchPad.

Baudrate Generator (UARTIBRD)

Two registers are used to set the baud rate:

  • They are UART Integer Baud-Rate Divisor (UARTIBRD) and UART Fractional Baud-Rate Divisor (UARTFBRD).
  • Of the 32-bit of the UARTIBRD, only lower 16 bits are used and of the 32-bit of the UARTFBRD, only the lower 6 bits are used.
  • That gives us total of 22 bits (16 bits integer + 6 bits of fraction).
  • To reduce the rate of error and use the standard baud rate, we should use both of the above divisor registers when we program the baud rate.


Tm4c uartibrd r.png

Baudrate Generator (UARTFBRD)

Tm4c uartfbrd r.png

Baudrate Calculation

The baud rate can be calculated using the following formula:

Desired Baud Rate = SysClk/(16 — ClkDiv)

where the SysCLK is the working system clock connected to the UART and ClkDiv is the values we load into divisor registers. The system clock fed to the CPU can come from XTAL, PLL, or an internal RC. For TI Tiva LaunchPad, the default system clock is 16 MHz. So we can rearrange the above formula as:

Desired Baud Rate = 16MHz/(16 - ClkDiv) = 1MHz/ClkDiv

The ClkDiv value gives us both the integer and fractional values needed for the UARTIBRD and UARTFBRD registers. While the integer portion of the divisor is easy to calculate using a simple calculator, the calculation of the fraction part requires some mathematical manipulation. One way would be, to multiply the fraction by 64 and round it by adding 0.5 to it.

Baudrate Calculation Example

Assume SysCLK Frequency = 16MHz. Find the values for the divisor registers of UARTIBRD and UARTFBRD for the following standard baud rates:

(a) 4800 (b) 9600 (c) 57,600 (d) 115,200

By default, 16 MHz System Clock is divided by 16 before it is fed to the UART.
Therefore, we have 16MHz/16 = 1MHz and ClkDiv = 1MHz.

(a) 1MHz/4800 = 208.3333, UARTIBRD = 208 and UARTFBRD = (0.3333 * 64) + 0.5 = 21.8312 = 21
(b) 1MHz/9600 = 104.166666, UARTIBRD = 104 and UARTFBRD = (0.16666 * 64) + 0.5 = 11
(c) 1MHz/57600 = 17.361, UARTIBRD = 17 and UARTFBRD = (0.361* 64) + 0.5 = 23
(d) 1MHz/115200 = 8.680,UARTIBRD = 8 and UARTFBRD = (0.680 * 64) + 0.5 = 44

In the above Example, it must be noted that default clock is divide-by-16. We can change it to divide-by-8 by setting to 1 the HSE bit of the UART Control (UARTCTL) register.

UART Control (UARTCTL)

The next important register in UART is the control register. It is a 32-bit register and many of the bits are unused. For us the most important bits are RXE, TXE, HSE, and UARTEN.

Tm4c uartctl r.png
  • UARTEN (D0) UART enable
    This allows one to enable or disable the UART. During the initialization we must disable it while modifying some of the UART registers.
  • HSE (D5) High Speed enable
    For the baud rate divisor, by default the system clock is divided by 16 before it is fed to the UART. We can change it to divide-by-8 by setting the HSE = 1 to run higher Baud rate with a low system clock frequency.
  • RXE (D8) Receive enable
    We must enable this bit to receive data.
  • TXE (D9) Transmit Enable
    We must enable this bit to transmit data.
  • The other bits of this register are used for MODEM signals such as CTS (clear to send), RTS (request to send), parity bit, and so on.

UART Line Control (UARTLCRH)

Tm4c uartlcrh r.png

This is the register we use to set the number of bits per character (data length) in a frame and number of stop bits among other things.

  • STP2 (D3) stop bit2:
    The stop bit can be 1 or 2. The default is 1 stop bit at the end of each frame. If the receiving device is slow, we can use 2 stop bits by making the STP2 = 1.
  • WLEN (D6 -D5) Word Length
    The number of bits per character data in each frame can be 5, 6, 7, or 8. Generally, we use 8 bits for each character data frame. Notice that default is 5 bits and we must change it to 8 bits as shown below:
D6 D5
0 0 5 bits
0 1 6 bits
1 0 7 bits
1 1 8 bits
  • FEN (D4) FIFO enable
    TI Tiva UART has an internal 16-byte FIFO (first in first out) buffer to store data for transmission. There is also another 16-byte FIFO buffer to save all the received bytes. By enabling FEN bit, we can write up to 16 bytes of data block into its transmission FIFO buffer and let it transfer one byte at a time.
  • The programmer may set up a threshold for the UART to notify the CPU when the level of the FIFO passes the threshold.
  • There is also a 16 byte FIFO for the receiver to buffer the incoming data.
  • Upon Reset, the default for FIFO buffer size is 1 byte (character mode).

UART Data (UARTDR)

Tm4c uartdr r.png

To transmit a byte of data we must place it in UART Data register. Although it is a 32-bit register, only the lower 8 bits (D0 - D7) are used. It must be noted that "A write to this register initiates a transmission from the UART." In the same way, the received byte is placed in this register and must be retrieved by reading it before it is lost. For transmit, only the lower 8 bits are used. For the receive, the lower 8 bits holds the received byte and other extra 4 bits of D8 - D11 are used for error detection such as framing error, parity error, and so on. There is another register called UARTRSR/UARTRCR (UART Receive Status Error/Error Clear) that can be used to check the source of error.

UART Flag Register (UARTFR)

Tm4c uartfr r.png
  • TXFE (D7) TX FIFO empty
    When we write a byte to Data register to be transmitted, the byte is placed in transmission FIFO buffer. When the transmitter is not busy, it loads one byte from the FIFO buffer and the FIFO becomes empty and the TXFE is raised. The transmitter then frames the byte and sends it out via TxD pin bit-by-bit serially.
  • RXFF (D6) RX FIFO full
    When a byte of data is received, this byte is placed in Data register and RXFF (RX FIFO full) flag bit is raised. In other words, when RXFF is HIGH, it means a byte has been received.
  • TXFF (D5) TX FIFOI full
    When we write a byte to Data register to be transmitted, the byte is placed in transmission FIFO buffer. When the transmitter is not busy, it loads one byte from the FIFO buffer and the FIFO is not full anymore and the TXFF is lowered. The transmitter then frames the byte and sends it out via TxD pin bit by bit serially. This is essentially the opposite of TXFE flag bit when FIFO buffer is disabled. We can monitor TXFF flag and upon going LOW we can write another byte to the Data register while the last byte is being transmitted.
  • RXFE (D4) RX FIFO empty
    The received byte of data comes in serially into a Receive buffer (first bit coming in is the start bit, 8-bit data, and stop bit). After the last bit (stop bit) has been received by the receiver, the UART circuitry discards the start and stop bits and delivers a byte of data to the Data register and lowers the RXFE bit (RX FIFO empty). This is essentially the opposite of RXFF flag bit. We can monitor RXFE flag and upon going LOW (buffer not empty) we should read (retrieve) the data from Data register.
  • Busy (D3)
    When a byte is written to the Data register the Busy flag goes High. While UART busy transmitting data this bit remains high until the stop bit is gone. Upon transmission of the last bit (stop bit), it goes low indicating the transmission is completed. This is only used when it is essential to complete the transmission before starting the next task.

Enabling Clock to UART (RCGCUART)

Tm4c rcgcuart r.png

The RCGCUART register is used to enable the clock to the UART. In this register, there is a bit for each of the UART0 to UART7 modules. If a given UART is not used, we should disable the clock to it to save power. To use UART0, we set to high the D0 of this register.

The GPIO pins used for UART (TxD & RxD)

In addition to the UART registers setup, we must also configure the I/O pins used for UART for their alternate functions. In the case of UART, we need to set up GPIO pins for the alternate functions of TxD and RxD signals. In the previous examples, we used GPIO as simple I/O. We showed the minimum configuration for each port as Digital I/O and providing the Clock to it. When GPIO pins are used for their alternate peripheral functions such as UART, Timer, and ADC, we need to configure five more registers. They are PORTx Run Mode Clock Gating Control, PORTx Digital Enable, PORTx ADC Mode Selection, PORTx Alternate Selection and PORTx Port Control registers.

GPIOAMSEL (GPIO Analog Mode Select)

Tm4c gpioamsel r.png

The TI ARM comes with on-chip ADC (analog to digital converter). Assume a given pins can be used for both ADC and UART and we want to use it for UART. In this case, we must isolate the ADC function since it is not used for analog operation. This is done with GPIOAMSEL (GPIO Analog Mode Selection). Although each port has its own PORTxAMSEL register, not all the pins of each port has ADC capability. Upon Reset, the PORTxAMSEL register has all 0s which means ADC function for the pin, if there is one, is disabled.

GPIO Alternate Function Select (GPIOAFSEL)

Tm4c gpioafsel r.png

In addition to Digital I/O and Clock enable, we must also configure the alternate function select register. Upon Reset, the GPIO pins are configured for simple I/O. To use the alternate function (e.g. UART) of given pin of a given Port, there are two steps to be taken. First we must set the corresponding bits in the alternate function select HIGH. In the case of UART0, PA0 and PA1 pins are used for RxD and TxD signals, respectively. Therefore, we must set both of them high in order to be used for the alternate functions of RxD and TxD. A one in the alternate function select register tells the port pin to perform a function other than simple I/O. GPIO Alternate Function Select Register (GPIOAFSEL) needs to work with the GPIO Port Control Register (GPIOPCTL) together to determine the operational mode and related peripheral functions for the selected GPIO pins.

GPIOPCTL Register

Tm4c gpiopctl r.png

The alternate function is selected by the Port Control Register. Each 32-bit GPIOPCTL register defines the alternate function for the eight pins of that port, 4 bits for each pin. If we wished to specify PA5-2 as SSI0, we would set Port A PCTL bits 23-16 to 0x2222 like this:

GPIO_PORTA_PCTL_R = (GPIO_PORTA_PCTL_R & 0xFF0000FF) + 0x00222200;

For most of the pins, UART function select number is 1. The only exceptions are PC4 and PC5. PC4 and PC5 may be used for either UART4 or UART1. When they are used for UART4, the select number is 1. When they are used for UART1, the select number is 2.

More information on GPIO Alternate functions is available here.


UART Interrupt Programming

Examining the UARTIM (UART Interrupt Mask) register, we see bit 4 allows us to enable the receive interrupt. If the receive interrupt for UART is enabled, when a byte is received, the receive flag is directed to NVIC and that causes the interrupt handler associated with the UART to be executed. In the UART handler we must read the received byte and clear the interrupt flag.

UART Interrupt Mask Register

Tm4c uartim r.png

bit Name Description
1 CTSIM UART Clear to Send Modem Interrupt Mask
1: An interrupt is sent to the interrupt controller when the CTSRIS bit in the UARTRIS register is set.
0: The CTSRIS interrupt is suppressed and not sent to the interrupt controller.
4 RXIM UART Receive Interrupt Mask
1: An interrupt is sent to the interrupt controller when the RXRIS bit in the UARTRIS register is set.
0: The RXRIS interrupt is suppressed and not sent to the interrupt controller.
5 TXIM UART Transmit Interrupt Mask
1: An interrupt is sent to the interrupt controller when the TXRIS bit in the UARTRIS register is set.
0: The TXRIS interrupt is suppressed and not sent to the interrupt controller.
6 RTIM UART Receive Time-Out Interrupt Mask
1: An interrupt is sent to the interrupt controller when the RTRIS bit in the UARTRIS register is set
0: The RTRIS interrupt is suppressed and not sent to the interrupt controller.
7 FEIM UART Framing Error Interrupt Mask
1: An interrupt is sent to the interrupt controller when the RTRIS bit in the UARTRIS register is set.
0: The FERIS interrupt is suppressed and not sent to the interrupt controller.
8 PEIM UART Parity Error Interrupt Mask
1: An interrupt is sent to the interrupt controller when the PERIS bit in the UARTRIS register is set.
0: The PERIS interrupt is suppressed and not sent to the interrupt controller.
9 BEIM UART Break Error Interrupt Mask
1: An interrupt is sent to the interrupt controller when the BERIS bit in the UARTRIS register is set.
0: The BERIS interrupt is suppressed and not sent to the interrupt controller.
10 OEIM UART Overrun Error Interrupt Mask
1: An interrupt is sent to the interrupt controller when the OERIS bit in the UARTRIS register is set.
0: The OERIS interrupt is suppressed and not sent to the interrupt controller.
12 9BITIM 9-Bit Mode Interrupt Mask
1: An interrupt is sent to the interrupt controller when the 9BITRIS bit in the UARTRIS register is set.
0: The 9BITRIS interrupt is suppressed and not sent to the interrupt controller.

UART Masked Interrupt Status (UARTMIS)

Tm4c uartmis r.png

bit Name Value Description
1 CTSMIS UART Clear to Send Modem Masked Interrupt Status
1: An unmasked interrupt was signaled due to Clear to Send.
0: An interrupt has not occurred or is masked.
4 RXMIS UART Receive Masked Interrupt Status
1: An unmasked interrupt was signaled due to passing through the specified receive FIFO level.
0: An interrupt has not occurred or is masked.
5 TXMIS UART Transmit Masked Interrupt Status
1: An unmasked interrupt was signaled due to passing through the specified transmit FIFO level (if the EOT bit is clear) or due to the transmission of the last data bit (if the EOT bit is set).
0: An interrupt has not occurred or is masked.
6 RTMIS UART Receive Time-Out Masked Interrupt Status
1: An unmasked interrupt was signaled due to a receive time out.
0: An interrupt has not occurred or is masked.
7 FEMIS UART Framing Error Masked Interrupt Status
1: An unmasked interrupt was signaled due to a framing error.
0: An interrupt has not occurred or is masked.
8 PEMIS UART Parity Error Masked Interrupt Status
1: An unmasked interrupt was signaled due to a parity error.
0: An interrupt has not occurred or is masked.
9 BEMIS UART Break Error Masked Interrupt Status
1: An unmasked interrupt was signaled due to a break error.
0: An interrupt has not occurred or is masked.
10 OEMIS UART Overrun Error Masked Interrupt Status
1: An unmasked interrupt was signaled due to an overrun error.
0: An interrupt has not occurred or is masked.
12 9BITMIS 9-Bit Mode Masked Interrupt Status
1: An unmasked interrupt was signaled due to a receive address match.
0: An interrupt has not occurred or is masked.

UART Raw Interrupt Status (UARTRIS)

Tm4c uartris r.png

bit Name Description
1 CTSRIS UART Clear to Send Modem Raw Interrupt Status
1: Clear to Send used for software flow control.
0: No interrupt
4 RXRIS UART Receive Raw Interrupt Status
1: The receive FIFO level has passed through the condition defined in the UARTIFLS register.
0: No interrupt
5 TXRIS UART Transmit Raw Interrupt Status
1: If the EOT bit in the UARTCTL register is clear, the transmit FIFO level has passed through the condition defined in the UARTIFLS register.
If the EOT bit is set, the last bit of all transmitted data and flags has left the serializer.
0: No interrupt
6 RTRIS UART Receive Time-Out Raw Interrupt Status
1: A receive time out has occurred.
0: No interrupt
7 FERIS UART Framing Error Raw Interrupt Status
1: A framing error has occurred.
0: No Interrupt
8 PERIS UART Parity Error Raw Interrupt Status
1: A parity error has occurred.
0: No Interrupt.
9 BERIS UART Break Error Raw Interrupt Status
1: A break error has occurred.
0: No Interrupt.
10 OERIS UART Overrun Error Raw Interrupt Status
1: An overrun error has occurred.
0: No Interrupt.
12 9BITRIS 9-Bit Mode Raw Interrupt Status
1: A receive address match has occurred.
0: No Interrupt.

UART Interrupt Clear (UARTICR)

Tm4c uarticr r.png

bit Name Description
1 CTSMIC UART Clear to Send Modem Interrupt Clear
Writing a 1 to this bit clears the CTSRIS bit in the UARTRIS register and the CTSMIS bit in the UARTMIS register.
This bit is implemented only on UART1 and is reserved for UART0 and UART2.
4 RXIC Receive Interrupt Clear
Writing a 1 to this bit clears the RXRIS bit in the UARTRIS register and the RXMIS bit in the UARTMIS register.
5 TXIC Transmit Interrupt Clear
Writing a 1 to this bit clears the TXRIS bit in the UARTRIS register and the TXMIS bit in the UARTMIS register.
6 RTIC Receive Time-Out Interrupt Clear
Writing a 1 to this bit clears the RTRIS bit in the UARTRIS register and the RTMIS bit in the UARTMIS register.
7 FEIC Framing Error Interrupt Clear
Writing a 1 to this bit clears the FERIS bit in the UARTRIS register and the FEMIS bit in the UARTMIS register.
8 RTIC Parity Error Interrupt Clear
Writing a 1 to this bit clears the PERIS bit in the UARTRIS register and the PEMIS bit in the UARTMIS register.
9 BEIC Break Error Interrupt Clear
Writing a 1 to this bit clears the BERIS bit in the UARTRIS register and the BEMIS bit in the UARTMIS register.
10 OEIC Overrun Error Interrupt Clear
Writing a 1 to this bit clears the OERIS bit in the UARTRIS register and the OEMIS bit in the UARTMIS register.
12 9BITIC 9-Bit Mode Interrupt Clear
Writing a 1 to this bit clears the 9BITRIS bit in the UARTRIS register and the 9BITMIS bit in the UARTMIS register.



TM4C123G LaunchPad UART Tasks

Steps for transmitting & Receiving data

Here are the steps to configure the UART0 to transmit/recive a byte of data for TI Tiva TM4C123GH6PM on the LaunchPad:

  1. Provide clock to UART0 by writing a 1 to RCGCUART (SYSCTL_RCGCUART_R) register.
  2. Provide clock to PORTA by writing a 1 to RCGCGPIO (SYSCTL_RCGCGPIO_R) register.
  3. Disable the UART0 by writing 0 to UARTCTL (UART0_CTL_R) register of UART0.
  4. Write the integer portion of the Baud rate to the UARTIBRD (UART0_IBRD_R) register of UART0.
  5. Write the fractional portion of the Baud rate to the UARTFBRD (UART0_FBRD_R) register of UART0.
  6. Configure the line control value for 1 stop bit, no FIFO, no interrupt, no parity, and 8-bit data size. That gives us 0x60 for the UARTLCRH (UART0_LCRH_R) register of UART0.
  7. Set UARTEN bit in UARTCTL (UART0_CTL_R) register to enable the UART0.
    Set TxE and RxE bits in UARTCTL register to enable the transmitter and receiver of UART0.
  8. Make PA0 and PA1 pins to be used as Digital I/O (GPIO_PORTA_DEN_R).
  9. Select the alternate functions of PA0 (RxD) and PA1 (TxD) pins using the GPIOAFSEL (GPIO_PORTA_AFSEL_R).
  10. Configure PA0 and PA1 pins for UART function (GPIO_PORTA_PCTL_R).
  11. Disable analog functionality on PortA0-1 (GPIO_PORTA_AMSEL_R)
  12. Monitor the RXFE flag bit in UART Flag register (UART0_FR_R) and when it goes LOW (buffer not empty), read the received byte from Data register (UART0_DR_R) and save it.
  13. Monitor the TXFF flag bit in UART Flag register (UART0_FR_R) and when it goes LOW (buffer not full), write received byte to Data register (UART0_DR_R) to be transmitted.

Before starting the UART echo program, we need a serial communication software in order to receive/transmit the data at the PC end, we can use putty software for this purpose, you can download it from here.

So just install it and run putty software, now click on "serial", it will show COM1 in "serial line" and 9600 baud in the "speed" fields.

Putty hyper terminal 1.png

In order to get the COM Port Number of connected launchpad, launch device manager (PC), click on ports, “Stellaris Virtual Serial Port” will appear and so its COM Port number in brackets, here you will find the COM port number, in our case it is COM3. Just go to the putty and enter this COM port and select the speed as 115200.

Putty hyper terminal 2.png

  1. Write a program to read and write characters (echo) to UART0 Port.
  2. Write an Echo (read and write) program using other than UART0 (UART1, UART2 ..... UART7)
  3. UART0 Echo Program showed how UART0 receives data by polling the RXFE status flag. The disadvantage with that program is that it ties down the CPU polling the status flag. Modify it to make it an interrupt driven program.

Programming General-Purpose Timer Module (GPTM)

In TI Tiva micro controllers, the timers are called General-Purpose Timer Module (GPTM). The General-Purpose Timer Module (GPTM) contains six 16/32-bit GPTM blocks and six 32/64-bit Wide GPTM blocks. In otherwords, there are 12 Timer Blocks in the TI Tiva TM4C123G, 6 of them are 16/32-bit timers and the other 6 are 32/64-bit. Each 16/32-bit GPTM block can provide two 16-bit (half-width) timers/counters that are referred to as Timer A and Timer B. These timers/counters can be further configured to operate independently as timers or event counters, or concatenated together to operate as one 32-bit (full-width) timer or one 32-bit Real-Time Clock (RTC).

Similarly, each 32/64-bit Wide GPTM block provides two 32-bit timers, also called Timer A and Timer B, and they can be concatenated together to form a 64-bit timer. Timers can also be used to trigger μDMA transfers. All timers have interrupt controls and separate interrupt vectors as well as separate interrupt handlers.


Tm4c gptm blkdiagram.png
Figure: GPTM Module Block Diagram


The 16/32-bit timer blocks are designated as Timer 0, Timer 1, ..., and Timer 5. The following shows the base addresses for the 16/32-bit Timer blocks:

  • 16/32-bit Timer 0 base: 0x4003.0000
  • 16/32-bit Timer 1 base: 0x4003.1000
  • 16/32-bit Timer 2 base: 0x4003.2000
  • 16/32-bit Timer 3 base: 0x4003.3000
  • 16/32-bit Timer 4 base: 0x4003.4000
  • 16/32-bit Timer 5 base: 0x4003.5000
  • 32/64-bit Wide Timer 0: 0x4003.6000
  • 32/64-bit Wide Timer 1: 0x4003.7000
  • 32/64-bit Wide Timer 2: 0x4004.C000
  • 32/64-bit Wide Timer 3: 0x4004.D000
  • 32/64-bit Wide Timer 4: 0x4004.E000
  • 32/64-bit Wide Timer 5: 0x4004.F000

Timer A and Timer B

Each of the Timer blocks contains two timers. They are called Timer A and Timer B. These two timers A and B can work independent of each other as two 16-bit timers or together as one single 32-bit timer. TimerA and TimerB each contains a counter. When the clock is fed to them, they keep counting up/down. We can read their contents as they count and we can load a new value in them. We will examine TimerA and give some examples. The discussion about TimerA also applies equally to TimerB. First, we must remember that, we need to enable the clock to the Timers before they can be used. This is done with the RCGCTimer register.

RCGCTimer

RCGCTimer
Figure 8.1: RCGCTimer
Bit Name Description
0 R0 Timer0 clock control (0: clock disabled, 1: clock enabled)
1 R1 Timer1 clock control (0: clock disabled, 1: clock enabled)
2 R2 Timer2 clock control (0: clock disabled, 1: clock enabled)
3 R3 Timer3 clock control (0: clock disabled, 1: clock enabled)
4 R4 Timer4 clock control (0: clock disabled, 1: clock enabled)
5 R5 Timer5 clock control (0: clock disabled, 1: clock enabled)
Table 8.1: RCGCTimer (Timer Run Mode Clock Gating Control)


The RCGCTIMER is part of the System Control registers. We must enable the clock to Timer0 - Timer5 before we can use them. Notice, in RCGCTIMER registers, bit R0 is for Timer0 block, bit R1 is for Timer1 block, and so on.

Timers Register Map

Name Offset Tivaware Name Description
GPTMCFG 0x000 TIMERn_CFG_R GPTM Configuration
GPTMTAMR 0x004 TIMERn_TAMR_R GPTM Timer A Mode
GPTMTBMR 0x008 TIMERn_TBMR_R GPTM Timer B Mode
GPTMCTL 0x00C TIMERn_CTL_R GPTM Control
GPTMSYNC 0x010 TIMERn_SYNC_R GPTM Synchronize
GPTMIMR 0x018 TIMERn_IMR_R GPTM Interrupt Mask
GPTMRIS 0x01C TIMERn_RIS_R GPTM Raw Interrupt Status
GPTMMIS 0x020 TIMERn_MIS_R GPTM Masked Interrupt Status
GPTMICR 0x024 TIMERn_ICR_R GPTM Interrupt Clear
GPTMTAILR 0x028 TIMERn_TAILR_R GPTM Timer A Interval Load
GPTMTBILR 0x02C TIMERn_TBILR_R GPTM Timer B Interval Load
GPTMTAMATCHR 0x030 TIMERn_TAMATCHR_R GPTM Timer A Match
GPTMTBMATCHR 0x034 TIMERn_TBMATCHR_R GPTM Timer B Match
GPTMTAPR 0x038 TIMERn_TAPR_R GPTM Timer A Prescale
GPTMTBPR 0x03C TIMERn_TBPR_R GPTM Timer B Prescale
GPTMTAPMR 0x040 TIMERn_TAPMR_R GPTM TimerA Prescale Match
GPTMTBPMR 0x044 TIMERn_TBPMR_R GPTM TimerB Prescale Match
GPTMTAR 0x048 TIMERn_TAR_R GPTM Timer A
GPTMTBR 0x4C TIMERn_TBR_R GPTM Timer B
GPTMTAV 0x050 TIMERn_TAV_R GPTM Timer A Value
GPTMTBV 0x054 TIMERn_TBV_R GPTM Timer B Value
GPTMRTCPD 0x058 TIMERn_RTCPD_R GPTM RTC Predivide
GPTMTAPS 0x05C TIMERn_TAPS_R GPTM Timer A Prescale Snapshot
GPTMTBPS 0x060 TIMERn_TBPS_R GPTM Timer B Prescale Snapshot
GPTMTAPV 0x064 TIMERn_TAPV_R GPTM Timer A Prescale Value
GPTMTBPV 0x068 TIMERn_TBPV_R GPTM Timer B Prescale Value
Where n = 0 to 5


Each GPTM block is composed of different control and status registers and these control and status registers can be divided into six groups based on their functions. We only discuss those registers used for the TimerA since the same registers are used for the TimerB. These registers can be divided into the following groups:

  • TimerA Control Register group
  • TimerA Status Register group
  • Timers A and B Interrupt and Configuration Register group
  • External Controls group

TimerA Control Register Group

Eight registers are used to configure and control the operations of the Timer A:

  1. GPTM Configuration Register (GPTMCFG)
  2. GPTM Control Register (GPTMCTL)
  3. GPTM Timer A Mode Register (GPTMTAMR)
  4. GPTM Timer A Interval Load Register (GPTMTAILR)
  5. GPTM Timer A Match Register (GPTMTAMATCHR)
  6. GPTM Timer A Prescale Register (GPTMTAPR)
  7. GPTM Timer A Prescale Match Register (GPTMTAPMR)
  8. GPTM Timer A Prescale Snapshot Register (GPTMTAPS)

GPTM Control Register (GPTMCTL)

Tm4c123 gptmctl.png
Figure 8.2: GPTM Control Register (GPTMCTL)


Bit(s) Name Description
0 TAEN Timer A Enable
0: disabled
1: enabled
1 TASTALL Timer A Stall (useful while debugging)
0: Timer A continues counting if the CPU is halted by the debugger,
1: Timer A Stalls (stops counting) while the CPU is halted by the debugger.
2 & 3 TAEVENT Timer A Event Mode
0: positive edge
1: negative edge
2: reserved
3: both edges
4 RTCEN RTC Stall Enable (useful while debugging)
0: RTC Stalls (stops counting) while the CPU is halted by the debugger
1: RTC continues counting if the CPU is halted by the debugger.
5 TAOTE Timer A Output Trigger Enable
0: ADC trigger disabled
1: ADC trigger enabled
6 TAPWML GPTM Timer A PWM Output Level
0: Output is unaffected
1: Output is inverted
8 TBEN GPTM Timer B Enable
0: Timer B is disabled
1: Timer B is enabled.
9 TBSTALL GPTM Timer B Stall Enable
0: Timer B continues counting while the processor is halted by the debugger
1: Timer B freezes counting while the processor is halted by the debug
11 & 10 TBEVENT GPTM Timer B Event Mode
0x0: Positive going edge
0x1: Negative going edge
0x3: Both edges
0x2: Reserved.
13 TBOTE GPTM Timer B Output Trigger Enable
0: The output Timer B ADC trigger is disabled
1: The output Timer B ADC trigger is enabled.
14 TBPWML GPTM Timer B PWM Output Level
0: Output is unaffected
1: Output is inverted.
31:15 Reserved Reserved
Table 8.2: GPTM Control Register

Note:

  • During the initialization of the Timers we must disable them. Modifying the configurations of a running timer may cause unpredictable results.
  • We use bit D0 of GPTMCTL (GPTM Control) register to disable or enable the TimerA.

GPTM Configuration Register (GPTMCFG)

To configure TimerA as 16- or 32-bit, we must use GPTMCFG (GPTM Configuration) register. Bits D2, D1, and D0 are used to select either 16- or 32-bit option. To use the 16-bit option we need to have D2:D1:D0=0x4. As mentioned above, in 16-bit mode, TimerA and TimerB make two separate timers which work independently.


Tm4c123 gptmcfg.png

D2:D1:D0 Mode
000 32-bit Mode
001 RTC Counter
100 16-bit Mode
Table 8.3: GPTM Configuration Register

TimerA Mode selection register (GPTMTAMR)

The mode selection such as periodic, count up/down selection for TimerA is done with GPTM TimerA Mode (GPTMTAMR) register.


Tm4c123 gptmtamr.png


Bit(s) Name Description
0 & 1 TAMR Timer A Mode
2 TACMR Timer A Capture Mode (0: Edge Count, 1: Edge Time)
3 TAAMS Timer A Alternate Mode Select (0: Capture or Compare Mode, 1: PWM Mode)
4 TACDIR Timer A Count Direction (0: Count Down, 1: Count Up)
5 TAMIE Timer A Match Interrupt Enable (0: the match interrupt is disabled, 1: enabled)
6 TAWOT Timer A Wait-On-Trigger (0: It begins counting when enabled, 1: waits for trigger)
7 TASNAPS Timer A Snap-Shot Mode (0: Snap Shot is disabled)
8 TAILD Timer A Interval Load Write
9 TAPWMIE Timer A PWM Interrupt Enable (0: Capture Event Interrupt is Disabled, 1: Enabled)
10 TAMRSU Timer A Match Register Update
11 TAPLO Timer A PWM Legacy Operation
Table 8.4: GPTMTAMR (GPTM Timer A Mode)


The mode selection is done with D1:D0 bits of GPTMTAMR, as shown below:

Mode D1 D0 Mode Name
0 0 0 Reserved
1 0 1 One-Shot Mode
2 1 0 Periodic Mode
3 1 1 Capture Mode
Table 8.5: TAMR Bits of GPTMTAMR

The direction Count is done with D4 (TACDIR). Upon Reset, the default is down counter. By making D4=1, TimerA counts up.

GPTM Timer n Interval Load (GPTMTnILR)

When the timer is counting down (the timer counts down if the TACDIR bit of the GPTMTAMR register is 0), the timer counter begins counting from GPTMTnILR (GPTMTAILR / GPTMTBILR) and goes down until it reaches zero. Then, the timer counter is reloaded with the value from GPTMTnILR and the TnTORIS flag of the GPTMRIS register is set.

The role of gptmtnr.png
Figure 8.3: The role of GPTMTnR

When the timer is counting up, the timer counter begins counting from 0 and goes up until it reaches the GPTMTnILR value. Then, the timer counter is cleared to zero and the TnTORIS flag of the GPTMRIS register is set.

Upon reset, all bits of the GPTMTnILR register are initialized to 1s which makes the biggest value and has no effect on the timer counting. But the software can change the value of GPTMTnILR. The smaller values for the register leads the timer timeout faster and the TnTORIS flag sets sooner. In other words, changes of delay can be made by setting the GPTMTnILR register and monitoring the TnTORIS flag.

Timer A Status Register Group

Three registers are used to monitor and detect the status of the Timer A:

  • GPTM Timer A Register (GPTMTAR)
  • GPTM Timer A Value Register (GPTMTAV)
  • GPTM Timer A Prescale Value Register (GPTMTAPV).

GPTMTnV (GPTM Timer Value)

GPTMTAV and GPTMTBV are two 16-bit up/down counter registers. When a timer is in 16-bit mode, they work as 2 separate counters. When the timer is in 32-bit mode, they are cascaded to form a 32-bit counter. When read, this register shows the current, free-running value of Timer A in all modes. When written, the value written into this register is loaded into the GPTMTAR register on the next clock cycle.

Note: In 16-bit mode, only the lower 16-bits of the GPTMTAV register can be written with a new value. Writes to the prescaler bits have no effect.

GPTM TimerA Match Register (GPTMTAMATCHR)

The GPTM Timer A Match (GPTMTAMATCHR) register can be used to load a match value, and this value can be compared with the current timer value stored in the GPTM Timer A (GPTMTAR ) register to trigger a matching interrupt or set a flag to indicate that a time value matching has occurred if both values are equal. The GPTM Timer B has the similar registers and functions.

When TimerA keeps counting it is compared with the contents of this register. Whenever the contents of free-running TimerA counter and TimerA Match register are equal, the TAMRIS Flag goes up indicating there is a match. The D4 of GPTMRIS register belongs to this flag.

Note: Although the TimerA Match is a 32-bit register, only the lower 16 bits are used in the 16-bit configuration selection.

Tm4c123 tnr tnmatchr tnmris.png
Figure 8.1: The Relation Between TnR, TnMATCHR, and TnMRIS

GPTM Timer A Register (GPTMTAR)

  • This is a 32-bit register and all 32 bits are used to indicate the current value of the 16-bit free-running counter of the Timer A. This register shows the current value of the Timer A counter in all cases except for Input Edge Count and Input Edge Time modes.
  • In the Input Edge Count mode, this register contains the number of edges that have occurred. In the Input Edge Time mode, this register contains the time at which the last edge event took place.
  • In the 16-bit Input Edge Count, Input Edge Time, and PWM modes, bits 15:0 contain the value of the counter and bits 23:16 contain the value of the prescaler, which is the upper 8 bits of the count. Bits 31:24 always read as 0.
  • When a 16/32-bit GPTM is configured to one of the 32-bit modes, GPTMTAR works as a 32-bit register with the upper 16 bits corresponding to the contents of the GPTMTBR register.
  • To read the value of the prescaler in 16-bit One-Shot and Periodic modes, read bits [23:16] in the GPTMTAV register. To read the value of the prescalar in periodic snapshot mode, read the Timer A Prescale Snapshot (GPTMTAPS) register.

GPTM Raw Interrupt Status Register (GPTMRIS)

Tm4c gptmris r.png


This 32-bit register only used the lower 16 bits to monitor and set a raw or internal interrupt if a GPTM-related raw interrupt occurred. These bits are set whether or not the interrupt is masked in the GPTMIMR register. However, whether these set raw interrupts can be sent to the interrupt controller to be further processed, it depends on whether the corresponding bits on the GPTMIMR register are set (enabled) or not (disabled). Only for those bits that have been set on the GPTMIMR register, they can be sent to the NVIC. The bit field and functions for this register are similar to those in the GPTMIMR register. If a GPTM-related raw interrupt is generated, the corresponding bit on this register is set to 1. Each bit can be cleared by writing a 1 to its corresponding bit in GPTMICR register.


Bit Name Description
0 TATORIS Timer A Time-out Raw interrupt (0: not occurred, 1: occurred)
1 CAMRIS Timer A Capture Mode Match Raw Interrupt (0: not occurred, 1: occurred)
2 CAERIS Timer A Capture Mode Event Raw Interrupt (0: not occurred, 1: occurred)
3 RTCRIS RTC Raw Interrupt(0: not occurred, 1: occurred)
4 TAMRIS Timer A Match Raw Interrupt
8 TBTORIS Timer B Time-out Raw interrupt (0: not occurred, 1: occurred)
9 CBMRIS Timer B Capture Mode Match Raw Interrupt (0: not occurred, 1: occurred)
10 CBERIS Timer B Capture Mode Event Raw Interrupt (0: not occurred, 1: occurred)
11 TBMRIS Timer B Match Raw Interrupt
16 WUERIS 32/64-Bit Wide GPTM Write Update Error Raw Interrupt Status

Periodic mode vs. one shot mode

The timer can be in 4 different modes including the periodic and one shot modes. In periodic mode the timer continues counting after each timeout. But in one shot mode, the timer stops counting after timeout is reached. For example, when it is in up counting and one shot modes, it counts from 0 to GPTMTnILR and then goes to zero just once and then the TnEN bit of GPTMCTL is cleared causing the timer to stop.


Tm4c123 timer oneshot mode.png

Figure 8.4: Counting in One Shot Mode

Each timer module has:

  • A clock enable bit, SYSCTL_RCGCTIMER_R
  • A control register, TIMERn_CTL_R
  • A configuration register, TIMERn_CFG_R
  • A mode register, TIMERn_TAMR_R
  • A 32-bit reload register, TIMERn_TAILR_R
  • A resolution (prescale) register, TIMERn_TAPR_R
  • An interrupt clear register, TIMERn_ICR_R
  • An interrupt arm bit, TIMERn_IM_R
  • A flag bit, TIMERn_RIS_R

( where n = 0 to 5)

Initialization and Configuration for One-Shot/Periodic Timer Mode

Perform the following operational steps to complete the initialization and configuration process for this mode:

  1. Disable the selected timer by clearing the TnEN bit in the GPTMCTL register (TIMERn_CTL_R).
  2. Initialize the GPTMCFG register to set up timer(s) as 16/32-bit timers (TIMERn_CFG_R).
  3. Configure the TnMR field in the GPTMTnMR (TIMERn_TAMR_R) register by writing
    • 0x1 for one-shot mode.
    • 0x2 for periodic mode.
  4. Optionally configure the TnSNAPS, TnWOT, TnMTE, and TnCDIR bits in the GPTMTnMR (TIMERn_TAMR_R) register to select whether to capture the value of the free-running timer at timeout, use an external trigger to start counting, configure an additional trigger or interrupt, and count-up or count-down operational mode.
  5. Load the start value (time up value) into the GPTMTnILR (TIMERn_TAILR_R) and the GPTMTnPR (TIMERn_TAPR_R, if prescaler is used) registers for the count-down (count-up) operations.
  6. If interrupts are required, set the appropriate bits in the GPTMIMR (TIMERn_IMR_R) register to enable the selected interrupt source.
  7. After these initializations and configurations done, set the TnEN bit in the GPTMCTL (TIMERn_CTL_R) register to enable the timer and start counting.
  8. If no interrupt is used, one can poll the GPTMRIS (TIMERn_RIS_R) register to check the appropriate bits and wait for the time event to occur. If an interrupt is used, put appropriate codes inside the interrupt handler to process the interrupt. In both cases, the status flags are cleared by writing a 1 to the appropriate bit of the GPTMICR (TIMERn_ICR_R) register.


In One-Shot mode, the timer stops counting after the timeout event. If the timer is configured as a periodic mode, the timer reloads the start value (time up value) and continues counting after the timeout event.

Prescaler register for Timer A

In the above example, the largest time delay that we can create is:

65535 × (1 / 16MHz) = 65535 × 62.5 nsec = 4.096 msec.

One way to create a longer time delay is to use the prescaler register. TimerA in 16-bit mode has an 8-bit prescaler register whose value can go from 0x00 to 0xFF. The 8-bit prescaler extends the 16-bit timer to 24-bit. The prescaler register allows system frequency to be divided by a value between 1 and 256 before it is fed to the TimerA. Note the prescaler can yield proper division only when the timer is configured as a down counter. As shown in Figure 8.5, the clock is divided by GPTMTnPR + 1.


Tm4c123 gptm prescalar.png
Figure 8.5: Prescalar


For CPU Freq=16MHz calculate the largest delay size using

  1. 16-bit TimerA without prescaler and
  2. 16-bit TimerA with prescaler.

Solution:
1/16MHz = 62.5 nsec is period of clock pulses fed to CPU.

  1. 65,536 x 62.5 nsec = 4.096 msec for TimerA 16-bit option .
  2. 65,536 x 256 x 62.5ns = 1.0485 second for TimerA 16-bit option with the Prescaler.

Use of Timers with the I/O Pins

If the timers are only used for the timing-base or timing-up indications, one does not need to use these Capture/Compare pins (CCP) since these pins are mainly connected to the external signals to detect the number of events that have occurred or the time period events that have been experienced.

In the previous session, we showed how to use timers to generate time delay. In this lab session, we will examine the use of timers with the I/O pins. There are five modes for each timer block. They are :

  1. One-shot/Periodic mode,
  2. Real-time clock mode,
  3. Input edge-time mode,
  4. Input edge-count mode and
  5. Pulse Width Modulation (PWM).

TimerA and TimerB CCP pins

There are TimerA and TimerB for each of the Timer block 0 to 5. There are one or two designated pins for each of the TimerA and TimerB. For example, TimerA of Timer block 4 is connected internally to pin PC0 of PortC and TimerB of Timer block 4 is connected to pin PC1 of PortC. Notice, TimerA pins are also called CCP0 and TimerB pins are called CCP1. Some of the timers have option to be connected to one of the two pins. For example, TimerA of Timer1 (T1CCP0) can use PB0 or PF2 pins. Table 9.1 shows the pin designations for 16/32-bit Timer block 0 to 5.


TimerA Pins TimerB Pins
Timer0 T0CCP0 PB6 or PF0 T0CCP1 PB7 or PF1
Timer1 T1CCP0 PB4 or PF2 T1CCP1 PB5 or PF3
Timer2 T2CCP0 PB0 or PF4 T2CCP1 PB1
Timer3 T3CCP0 PB2 T3CCP1 PB3
Timer4 T4CCP0 PC0 T4CCP1 PC1
Timer5 T5CCP0 PC2 T5CCP1 PC3
Table 9.1: The Pin Designation for 16/32 bit Timer Block 0 to 5

General-Purpose Timers CCP pins distributions

Timer Pin I/O pin Pin Function
T0CCP0 PB6 16/32-Bit Timer 0 Capture/Compare/PWM 0
PF0
T0CCP1 PB7 16/32-Bit Timer 0 Capture/Compare/PWM 1
PF1
T1CCP0 PB4 16/32-Bit Timer 1 Capture/Compare/PWM 0
PF2
T1CCP1 PB5 16/32-Bit Timer 1 Capture/Compare/PWM 1
PF3
T2CCP0 PB0 16/32-Bit Timer 2 Capture/Compare/PWM 0
PF4
T2CCP1 PB1 16/32-Bit Timer 2 Capture/Compare/PWM 1
T3CCP0 PB2 16/32-Bit Timer 3 Capture/Compare/PWM 0
T3CCP1 PB3 16/32-Bit Timer 3 Capture/Compare/PWM 1
T4CCP0 PC0 16/32-Bit Timer 4 Capture/Compare/PWM 0
T4CCP1 PC1 16/32-Bit Timer 4 Capture/Compare/PWM 1
T5CCP0 PC2 16/32-Bit Timer 5 Capture/Compare/PWM 0
T5CCP1 PC3 16/32-Bit Timer 5 Capture/Compare/PWM 1
WT0CCP0 PC4 32/64-Bit Wide Timer 0 Capture/Compare/PWM 0
WT0CCP1 PC5 32/64-Bit Wide Timer 0 Capture/Compare/PWM 1
WT1CCP0 PC6 32/64-Bit Wide Timer 1 Capture/Compare/PWM 0
WT1CCP1 PC7 32/64-Bit Wide Timer 1 Capture/Compare/PWM 1
WT2CCP0 PD0 32/64-Bit Wide Timer 2 Capture/Compare/PWM 0
WT2CCP1 PD1 32/64-Bit Wide Timer 2 Capture/Compare/PWM 1
WT3CCP0 PD2 32/64-Bit Wide Timer 3 Capture/Compare/PWM 0
WT3CCP1 PD3 32/64-Bit Wide Timer 3 Capture/Compare/PWM 1
WT4CCP0 PD4 32/64-Bit Wide Timer 4 Capture/Compare/PWM 0
WT4CCP1 PD5 32/64-Bit Wide Timer 4 Capture/Compare/PWM 1
WT5CCP0 PD6 32/64-Bit Wide Timer 5 Capture/Compare/PWM 0
WT5CCP1 PD7 32/64-Bit Wide Timer 5 Capture/Compare/PWM 1
Table 9.2: General-Purpose Timers signals and GPIO pins distributions.

Selecting alternate function for Timers pin

Upon Reset, the GPIOAFSEL register has all 0s meaning the I/O pins are used as simple I/O. To use an alternate function, we first must set the bit in the AFSEL register to 1 for that pin. For example, for the PB6, we need to write 0x40 to GPIO_PORTB_AFSL_R register. After that, the GPIOPCTL register must be configured for the desired function. To do that, we need to use the information in Table 23-5 (Page No.1351) of TI Tiva TM4C123GH6PM data sheet or refer here.

Table 9.2 provides the summary for the Timers pins.

Timer Pin I/O pin How to use peripheral function on the pin
T0CCP0 PB6 GPIO_PORTB_AFSEL_R = 0x40
PF0 GPIO_PORTF_AFSEL_R = 0x01
T0CCP1 PB7 GPIO_PORTB_AFSEL_R = 0x80
PF1 GPIO_PORTF_AFSEL_R = 0x02
T1CCP0 PB4 GPIO_PORTB_AFSEL_R = 0x10
PF2 GPIO_PORTF_AFSEL_R = 0x04
T1CCP1 PB5 GPIO_PORTB_AFSEL_R = 0x20
PF3 GPIO_PORTF_AFSEL_R = 0x08
T2CCP0 PB0 GPIO_PORTB_AFSEL_R = 0x40
PF4 GPIO_PORTF_AFSEL_R = 0x10
T2CCP1 PB1 GPIO_PORTB_AFSEL_R = 0x02
T3CCP0 PB2 GPIO_PORTB_AFSEL_R = 0x04
T3CCP1 PB3 GPIO_PORTB_AFSEL_R = 0x08
T4CCP0 PC0 GPIO_PORTC_AFSEL_R = 0x01
T4CCP1 PC1 GPIO_PORTC_AFSEL_R = 0x02
T5CCP0 PC2 GPIO_PORTC_AFSEL_R = 0x04
T5CCP1 PC3 GPIO_PORTC_AFSEL_R = 0x08
WT0CCP0 PC4 GPIO_PORTC_AFSEL_R = 0x10
WT0CCP1 PC5 GPIO_PORTC_AFSEL_R = 0x20
WT1CCP0 PC6 GPIO_PORTC_AFSEL_R = 0x40
WT1CCP1 PC7 GPIO_PORTC_AFSEL_R = 0x80
WT2CCP0 PD0 GPIO_PORTD_AFSEL_R = 0x01
WT2CCP1 PD1 GPIO_PORTD_AFSEL_R = 0x02
WT3CCP0 PD2 GPIO_PORTD_AFSEL_R = 0x04
WT3CCP1 PD3 GPIO_PORTD_AFSEL_R = 0x04
WT4CCP0 PD4 GPIO_PORTD_AFSEL_R = 0x10
WT4CCP1 PD5 GPIO_PORTD_AFSEL_R = 0x20
WT5CCP0 PD6 GPIO_PORTD_AFSEL_R = 0x40
WT5CCP1 PD7 GPIO_PORTD_AFSEL_R = 0x80
Table 9.3: Timers Alternate Pin Assignments


Timer Pin I/O pin How to select the timer function on the pin
T0CCP0 PB6 GPIO_PORTB_PCTL_R = 0x0700.0000
PF0 GPIO_PORTF_PCTL_R = 0x0000.0007
T0CCP1 PB7 GPIO_PORTB_PCTL_R = 0x7000.0000
PF1 GPIO_PORTF_PCTL_R = 0x0000.0070
T1CCP0 PB4 GPIO_PORTB_PCTL_R = 0x0007.0000
PF2 GPIO_PORTF_PCTL_R = 0x0000.0700
T1CCP1 PB5 GPIO_PORTB_PCTL_R = 0x0070.0000
PF3 GPIO_PORTF_PCTL_R = 0x0000.7000
T2CCP0 PB0 GPIO_PORTB_PCTL_R = 0x0000.0007
PF4 GPIO_PORTF_PCTL_R = 0x0007.0000
T2CCP1 PB1 GPIO_PORTB_PCTL_R = 0x0000.0070
T3CCP0 PB2 GPIO_PORTB_PCTL_R = 0x0000.0700
T3CCP1 PB3 GPIO_PORTB_PCTL_R = 0x0000.7000
T4CCP0 PC0 GPIO_PORTC_PCTL_R = 0x0000.0007
T4CCP1 PC1 GPIO_PORTC_PCTL_R = 0x0000.0070
T5CCP0 PC2 GPIO_PORTC_PCTL_R = 0x0000.0700
T5CCP1 PC3 GPIO_PORTC_PCTL_R = 0x0000.7000
WT0CCP0 PC4 GPIO_PORTC_PCTL_R = 0x0007.0000
WT0CCP1 PC5 GPIO_PORTC_PCTL_R = 0x0070.0000
WT1CCP0 PC6 GPIO_PORTC_PCTL_R = 0x0700.0000
WT1CCP1 PC7 GPIO_PORTC_PCTL_R = 0x7000.0000
WT2CCP0 PD0 GPIO_PORTD_PCTL_R = 0x0000.0007
WT2CCP1 PD1 GPIO_PORTD_PCTL_R = 0x0000.0070
WT3CCP0 PD2 GPIO_PORTD_PCTL_R = 0x0000.0700
WT3CCP1 PD3 GPIO_PORTD_PCTL_R = 0x0000.7000
WT4CCP0 PD4 GPIO_PORTD_PCTL_R = 0x0007.0000
WT4CCP1 PD5 GPIO_PORTD_PCTL_R = 0x0070.0000
WT5CCP0 PD6 GPIO_PORTD_PCTL_R = 0x0700.0000
WT5CCP1 PD7 GPIO_PORTD_PCTL_R = 0x7000.0000
Table 9.4: Timers pin assignment using GPIO_PCTL


Example 9.1: Write the code to provide the T0CCP1 function on PF1.
Solution: The I/O pin is used as a peripheral function pin by setting the AFSEL register of PORTF and the desired peripheral function is selected by setting the PCTL register of PORTF:

GPIO_PORTF_AFSEL_R |= 0x02;
GPIO_PORTF_PCTL_R = 0x00000070;

Some Implementations on GPTM Modules

Timer system is a complex system with many different components and functions. We only discuss some very popular and important implementations. These include:

  • Using timer capture functions to detect the number of input edges.
  • Using timer detecting functions to measure the period for periodic signals.
  • Using timer control functions to generate PWM signals to control motors.

Using Timer for input edge-time capturing

Input edge-time capture mode

In input edge-time mode, an I/O pin is used to capture the signal transition events. When an event occurs, the content of the timer counter is captured in another register while the counter keeps counting. The program can then read the counter value when the event occurs at a slightly later time.

To configure the timer to input edge time mode the TnMR and TnCMR bits of GPTMTnMR should be set to capture edge-time mode (TnMR = 3 and TnCMR = 1). See Table 8.5. In this mode, the timer counter value is stored in the GPTMTnR register whenever the input pin is triggered by an external event. See Figure 9.1

Input Edge Time Capturing
Figure 9.1: Input Edge Time Capturing


The timer can be configured to capture on the falling edge, rising edge, or both. To determine the type of edge that is captured, the TnEVENT bits of the GPTMCTL register should be initialized. See Table 8.4

Timer counting in input edge time mode

In edge time mode GPTMTnV and the optional prescaler are combined to make a 24-bit or 48-bit timer. The timer is 24-bit when 16-bit timers are used. The timer is 48-bit when 32-bit timers are used.

In up counting mode, the GPTMTnV and GPTMTnPV registers are initialized with 0s and they count up until they reach to GPTMTnILR and GPTMTnPR, respectively. Then, they are reset to 0s again.

Tm4c counting in input edge time mode.png
Figure 9.2: Counting in Input Edge-Time Mode


In down counting mode, the GPTMTnV and GPTMTnPV registers are initialized with GPTMTnILR and GPTMTnPR, respectively and they count down until they reach 0. Then, they are reloaded with GPTMTnILR and GPTMTnPR, again. Notice that capturing has no effect on counting and the timer continues counting when the capturing event takes place.

Initialization and Configuration for Input Edge-Time Mode

Perform the following operational steps to complete the initialization and configuration process for this mode (n = A or B):

  1. Disable the selected timer by clearing the TnEN bit in the GPTMCTL register.
  2. Initialize the GPTMCFG register by writing 0x4 to setup all timers as 16-bit default timers.
  3. Configure the TnMR and TnCMR fields in the GPTMTnMR register by writing:
    • TnMR = 0x3 for capture mode.
    • TnCMR = 0x1 for edge time mode.
    • Select a count direction by programming the TnCDIR bit (0=count-down; 1=count-up).
  4. Configure the event type (positive-going, negative-going, or both) that the timer captures by writing the TnEVENT field of the GPTMCTL register.
  5. If a prescaler is to be used, write the prescale value to the GPTMTnPR register.
  6. Load the timer start value into the GPTMTnILR register.
  7. If interrupts are required, set the CnEIM bit in the GPTMIMR register.
  8. After these initializations and configurations are done, set the TnEN bit in the GPTMCTL register to enable the timer and begin waiting for edge events.
  9. If no interrupt is used, one can poll the CnERIS bit in the GPTMRIS register to wait for the edge event to occur. If interrupt is used, put appropriate codes inside the interrupt handler to process the interrupt. In both cases, the status flags are cleared by writing a 1 to the CnECIR bit on the GPTMICR register. The time at which the event happened can be obtained by reading the GPTMTnR register.

In the Input Edge Timing mode, the timer continues running after an edge event has been detected, but the timer interval can be changed at any time by writing the GPTMTnILR register and clearing the TnILD bit in the GPTMTnMR register. The change takes effect at the next cycle after the write taking placing.

Using Timer As a Counter

As shown in Table 8.4, a timer works as a counter when the TAMR bits of the GPTMTnMR are configured to capture mode and the TACMR bit is cleared. In this situation, the timer counts whenever the input pin is triggered. See Figure 9.3. The pin can be configured to count on the falling edge, rising edge, or both. To determine the type of edge that is counted, the TnEVENT bits of the GPTMCTL register should be initialized. See Table 8.3 and Table 8.4.

Tm4c counter diagram.png
Figure 9.3: Counter Diagram

Timer counting in input edge count mode

In this mode GPTMTnV and the prescaler are combined to make a 24-bit or 48-bit timer. The timer is 24-bit when TimerA and TimerB are used separately. Otherwise, they make a 48-bit timer.

In up counting mode, the GPTMTnV and GPTMTnPV registers are initialized with 0s and they count up until they reach to GPTMTnMATCHR and GPTMTnPMR, respectively. Then, they are reloaded with 0s again. See Figure 9.4.

Tm4c counting in input edge count mode.png
Figure 9.4: Counting in the Input Edge-Count Mode


Note: The value of GPTMTnPR and GPTMTnILR must be greater than the value of GPTMTnPMR and GPTMTnMATCHR.

In down counting, the GPTMTnV and GPTMTnPV registers are initialized with GPTMTnILR and GPTMTnPR, respectively and they count down until they reach to TnMATCHR and TnPMR, respectively. Then, they are reloaded with GPTMTnILR and GPTMTnPR and the CnMRIS flag of the GPTMRIS register is set. As a result, in cases that a task must be done after a specific number of events, the registers should be initialized so that (TnPR:TnILR – TnPMR:TnMATCHR = number of events to be counted); and then the CnMRIS flag is monitored to be set.

Initialization and Configuration for Input Edge-Count Mode

Perform the following operational steps to complete the initialization and configuration process for this mode (n = A or B):

  1. Disable the selected timer by clearing the TnEN bit in the GPTMCTL register.
  2. Initialize the GPTMCFG register by writing 0x4 to setup all timers as 16-bit default timers.
  3. Configure the TnMR and TnCMR fields in the GPTMTnMR register by writing:
    • TnMR = 0x3 for capture mode.
    • TnCMR = 0x0 for edge count mode.
  4. Configure the event type (positive-going, negative-going or both) that the timer captures by writing the TnEVENT field of the GPTMCTL register.
  5. Configure the following registers according to count direction:
  6. In count-down mode, the GPTMTnMATCHR and GPTMTnPMR registers are configured so that the difference between the value in the GPTMTnILR and GPTMTnPR registers and the GPTMTnMATCHR and GPTMTnPMR registers equals the number of edge events that must be counted. Make sure that the value in the GPTMTnILR and GPTMTnPR registers is greater than the value in the GPTMTnMATCHR and GPTMTnPMR registers.
  7. In count-up mode, the timer counts from 0x0 to the value in the GPTMTnMATCHR and GPTMTnPMR registers. Note that when executing a count-up, the value of the GPTMTnPR and GPTMTnILR must be greater than the value of GPTMTnPMR and GPTMTnMATCHR registers.
  8. If interrupts are required, set the CnMIM bit in the GPTMIMR register.
  9. After these initializations and configurations done, set the TnEN bit in the GPTMCTL register to enable the timer and begin waiting for edge events.
  10. If no interrupt is used, one can poll the CnMRIS bit in the GPTMRIS register to wait for the edge event to be occurred. If interrupt is used, put appropriate codes inside the interrupt handler to process the interrupt. In both cases, the status flags are cleared by writing a 1 to the CnMCIR bit on the GPTMICR register.

When counting down in the Input Edge-Count Mode, the timer stops after the programmed number of edge events has been detected. To re-enable the timer, ensure that the TnEN bit is cleared and repeat steps 4 through 8.

PWM Mode

  • When working in this mode, each timer can be configured as a 24- or 48-bit count-down counter to generate PWM output signals. At start, the timer loads the start values stored in the GPTMTAILR and GPTMTAPR registers (if prescaler is used) and begins its count-down actions. When gets 0, the timer reloads the start value and begin the next cycle.
  • The period and frequency of the PWM signal is controlled by the start values setup in the GPTMTAILR and GPTMTAPR registers, and the pulse width is controlled by the values set in the GPTMTAMATCHR and GPTMTAPMR registers (if prescaler is used). The PWM pulse is generated (outputs High) when the timer is at its start value and terminated (outputs Low) when the timer equals to the terminate values stored in the GPTMTAMATCHR and GPTMTAPMR registers.
  • The timer can generate three types of interrupt: rising edge, falling edge, and both. The event is configured by the TAEVENT field of the GPTMCTL register, and the interrupt is enabled by setting the TAPWMIE bit in the GPTMTAMR register.
  • In this mode, the GPTMTAR and GPTMTAV registers always have the same value, as do the GPTMTAPS and the GPTMTAPV registers.


The operational sequence of using the Timer A to generate a PWM signal is as follows:

  1. The start values are loaded into the GPTMTAILR and GPTMTAPR registers, and the terminate values are loaded into the GPTMTAMATCHR and GPTMTAPMR registers. The period and duty cycle of the PWM signal are determined based on these values.
  2. The PWM mode is enabled with the GPTMTAMR register by setting the TAAMS bit to 1, the TACMR bit to 0, and the TAMR field to 0x2.
  3. The timer is enabled and starts its count-down operation by setting the TAEN bit in the GPTMCTL register to 1. The counter begins counting down until it reaches the 0 state. Then it reloads the start values and continues for the next cycle until disabled by software clearing the TAEN bit in the GPTMCTL register. Alternatively, if the TAWOT bit is set in the GPTMTAMR register, once the TAEN bit is set, the timer waits for a trigger to begin counting.
  4. As the timer starts counting from its start values, the PWM pulse is generated with outputting High. During the counting-down process, when the value in the timer is equal to the terminate values set in the GPTMTAMATCHR and GPTMTAPMR registers, the pulse of the PWM signal is terminated with outputting Low.
  5. The output level of the PWM signal can be controlled by the software, it means that the software has the capability of inverting the output PWM signal by setting the TAPWML bit in the GPTMCTL register.

Timer Interrupt Programming

In the previous article, we showed how to program the timers. In those programming examples, we used polling to see if a timeout event occurred. In this section, we give interrupt-based version of those programs. Examine the earlier programs, we could run those programs only one at a time since we have to monitor the timer flag continuously. By using interrupt, we can run several of timer programs all at the same. To do that, we need to enable the timer interrupts using the GPTMIMR (GPTM Interrupt Mask) register.

Timers A and B Interrupt and Configuration Register Group

Six registers are used to control and handle interrupts of the Timers A and B:

  • GPTM Interrupt Mask Register (GPTMIMR)
  • GPTM Raw Interrupt Status Register (GPTMRIS)
  • GPTM Masked Interrupt Status Register (GPTMMIS)
  • GPTM Interrupt Clear Register (GPTMICR)
  • GPTM Synchronize Register (GPTMSYNC)
  • GPTM Peripheral Properties Register (GPTMPP)

GPTM Interrupt Mask Register (GPTMIMR)

Tm4c gptm imr.png


Bit Name Description
0 TATOIM Timer A Time-out Interrupt Mask (0: interrupt is disabled, 1: interrupt is enabled)
1 CAMIM Timer A Capture Mode Match Interrupt Mask (0: interrupt is disabled, 1: interrupt is enabled)
2 CAEIM Timer A Capture Mode Event Interrupt Mask (0: interrupt is disabled, 1: interrupt is enabled)
3 RTCIM RTC Interrupt Mask (0: interrupt is disabled, 1: interrupt is enabled)
4 TAMIM Timer A Match Interrupt Mask (0: interrupt is disabled, 1: interrupt is enabled)
8 TBTOIM Timer B Time-out Interrupt Mask (0: interrupt is disabled, 1: interrupt is enabled)
9 CBMIM Timer B Capture Mode Match Interrupt Mask (0: interrupt is disabled, 1: interrupt is enabled)
10 CBEIM Timer B Capture Mode Event Interrupt Mask (0: interrupt is disabled, 1: interrupt is enabled)
11 TBMIM Timer B Match Interrupt Mask (0: interrupt is disabled, 1: interrupt is enabled)
16 WUEIM 32/64-Bit Wide GPTM Write Update Error Interrupt Mask (0: disabled, 1: enabled)
Table 10.1: GPTM Interrupt Mask (GPTMIMR)


IRQ21 is assigned to Timer1A and IRQ23 to Timer2A. The following will enable these timers in NVIC:

NVIC_EN0_R |= 0x00200000;   /* enable IRQ21  */
NVIC_EN0_R |= 0x00800000;   /* enable IRQ23 */

GPTM Raw Interrupt Status Register (GPTMRIS)

Tm4c gptmris r.png


This 32-bit register only used the lower 10 bits to monitor and set a raw or internal interrupt if a GPTM-related raw interrupt occurred. These bits are set whether or not the interrupt is masked in the GPTMIMR register. However, whether these set raw interrupts can be sent to the interrupt controller to be further processed, it depends on whether the corresponding bits on the GPTMIMR register are set (enabled) or not (disabled). Only for those bits that have been set on the GPTMIMR register, they can be sent to the NVIC. The bit field and functions for this register are similar to those in the GPTMIMR register. If a GPTM-related raw interrupt is generated, the corresponding bit on this register is set to 1. Each bit can be cleared by writing a 1 to its corresponding bit in GPTMICR register.


Bit Name Description
0 TATORIS Timer A Time-out Raw interrupt (0: not occurred, 1: occurred)
1 CAMRIS Timer A Capture Mode Match Raw Interrupt (0: not occurred, 1: occurred)
2 CAERIS Timer A Capture Mode Event Raw Interrupt (0: not occurred, 1: occurred)
3 RTCRIS RTC Raw Interrupt(0: not occurred, 1: occurred)
4 TAMRIS Timer A Match Raw Interrupt
8 TBTORIS Timer B Time-out Raw interrupt (0: not occurred, 1: occurred)
9 CBMRIS Timer B Capture Mode Match Raw Interrupt (0: not occurred, 1: occurred)
10 CBERIS Timer B Capture Mode Event Raw Interrupt (0: not occurred, 1: occurred)
11 TBMRIS Timer B Match Raw Interrupt
16 WUERIS 32/64-Bit Wide GPTM Write Update Error Raw Interrupt Status

GPTM Masked Interrupt Status Register (GPTMMIS)

Tm4c gptmmis r.png

Similar to the GPTMIMR register, this 32-bit register only used the lower 10 bits to monitor and make a responded interrupt if a GPTM related interrupt is occurred and has been responded. The bit field and functions for this register is similar to those in the GPTMIMR register. A value of 1 on a bit in this register indicates that the corresponding interrupt has occurred and has received a response. All bits are cleared by writing a 1 to the corresponding bit in GPTMICR register.

GPTM Interrupt Clear Register (GPTMICR)

Tm4c gptmicr r.png

Similar to GPTMIMR register, this 32-bit register only used the lower 10 bits to clear related responded interrupts if the GPTM-related interrupts have received a response and have been processed. This register is used to clear the status bits in the GPTMRIS and GPTMMIS registers. Writing a 1 to a bit clears the corresponding bit in the GPTMRIS and GPTMMIS registers. All processed or responded interrupts must be cleared by using this register. Otherwise the responded interrupt cannot be generated again in the future if it is not cleared. The bit field and functions for this register is similar to those in the GPTMIMR register.

1. Build a General Purpose Timer Project

Use GPTM block 0 Timer A (Timer0A) as a 16-bit count-down counter to periodically generate a timeout interrupt to turn on three LEDs, PF3∼PF1, via GPIO Port F. The input clock to the timer is the 16 MHz system clock, and the period to be counted in the Timer0A counter is 65.536 ms.

To perform this periodic interrupt for each 65.536 ms, one needs to:

  1. Enable and clock the Timer0A for GPTM Block 0.
  2. Enable and clock the GPIO Port F.
  3. Disable the Timer0A module before any configuration can be performed.
  4. Configure the Timer0A to work as a 16-bit count-down periodic counter.
  5. Load 65535 (65536 – 1) into the GPTMTAILR register as the start value since we want to get the maximum period of time, which is 65.536 ms, for each period.
  6. Load 15 (16 – 1) into the GPTMTAPR register as a prescale value. After this 16 MHz system clock is divided by this prescaler (16), the working clock for this counter is 1 MHz with a 1-μs period.
  7. Clear any previous timeout interrupt for Timer0A by writing 1 to an appropriate bit in the GPTMICR register.
  8. Enable Timer0A timeout interrupt by writing 1 to an appropriate bit in the GPTMIMR register.
  9. Use NVIC_PRI4_R (Bit 31 - 29 ) to set the interrupt priority level as 3 for the Timer0A.
  10. Use NVIC_EN0_R (IRQ19) to enable the timeout interrupt for the Timer0A.
  11. Enable the Timer0A module after these configuration and the Timer0A begins to count.
  12. Use EnableInterrupts() function to globally enable all interrupts.
  13. Use an infinitive while() loop to wait for any interrupt coming.

In addition to the main program, one also needs to build the Timer0A interrupt handler:

  1. Clear the timeout interrupt for Timer0A by writing 1 to an appropriate bit in the GPTMICR register to enable it to be generated in the future.
  2. Turn on the related LED via GPIO Port F.

2. Use Timer1A and Timer2A timeout events to trigger interrupts

  • Configure Timer1A to timeout once every second. In the interrupt handler, toggle the red LED.
  • Configure Timer2A to timeout at 10 Hz. In the interrupt handler, toggle the green LED.

3. Measure pulse width using interrupts with a precision of 24 bits and a resolution of 12.5 ns

  • The pulse width measurement is performed from rising edge to falling edge.
  • The resolution is 12.5 ns, determined by the system bus clock.
  • The range is about 25 ns to 209ms with no overflow checking.

Hints:

  • The digital-level input signal is connected to two input capture pins, CCP0 and CCP1.
  • The bus clock is selected to be 80 MHz so the measurement resolution will be 12.5 ns.
  • The rising edge time will be measured by Timer0B without the need of an interrupt and the falling edge interrupts will be handled by Timer0A.
  • The pulse width is calculated as the difference in TIMER0_TBR_R - TIMER0_TAR_R latch values.


Tm4c measuring pulse width.png

4. Measure the period of a square wave input signal

Hint: To measure the period of a signal we must measure the time between two falling or rising edges.

Tm4c measuring square wave.png
Figure 10.5: Measuring Period and Pulse Width

5. Generate PWM

  • Generate an output PWM with a 1-ms period and a 66% duty cycle (TAPWML = 0) assuming a 50 MHz input clock. The duty cycle could be 33% if the TAPWML = 1.
    Hint:
    1. The start value is GPTMTAILR = 0xC350 and the match value in GPTMTAMATCHR is 0x411A.
    2. Use PLL
    3. Use Timer A
Task timer pwm.png

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.