UART programing in the TI ARM Tiva TM4C123G

The following exercise show you how to make use of an UART port from the ARM Cortex-M4-based microcontroller Tiva TM4C123G LaunchPad. The ASIC character “Yes” will be send to a terminal emulator program on your PC as an example.


The  TM4C123G datasheet  provide a series of steps under the below sections that will be required for UART set-up:

  • General-Purpose Input/Outputs (GPIOs) - Initialization and Configuration. 

  • Universal Asynchronous Receivers/Transmitters (UARTs)


 

I will summarize those steps with a visual representation for better understanding of the procedure and to easily go through the datasheet. Eventually each step will  be part of an entire source code for you to use. Complete source code is at the end of this article. 


Note: For the purpose of this tutorial we are going to use IAR as our integrated development environment tool (IDE). I’m not affiliated, nor support, or receive any commission by doing so.


Note: Users should have been familiarized previously with the IAR tool.






To begin with...


You need to know that the Tiva ARM TM4C123GH6PM has up to 8 UART ports, designated as UART0 to UART7


Table 23-5. GPIO Pins and Alternate Functions, page 1351 of the datasheet, shows all of the UARTs ports and correlation with their pins.




For simplicity, and because I don’t have any other cable other than the USB included in the box at the moment, we are going to program UART0. The reason why we choose UART0 is because pins 17 & 18 allow virtual COM connection between our device and the device driver at the host PC. And will work with communication software on the PC such as a terminal emulator.  


Page 20 of the User’s Manual.



In the TI LaunchPad, the pins 17 & 18 of the TM4C123GH6PM is connected to the ICDI (In-Circuit Debug Interface), which is connected to a USB connector. Thus, only the USB cable will be needed to communicate with UART0.




From this point on the steps that you will follow represent single lines of code to be compiled later on in your source code. As mentioned before the complete source code can be found at the end.






Part I. GPIOA Initialization and Configuration

General-Purpose Input/Outputs (GPIOs) module, Port A. 

DATA SHEET, p.656.



This section describes the steps to follow to access and configure the GPIO pins of a particular block. In our case the block we want to manipulate is block A, as we just see from the previous schematic pins 17 & 18 correspond to GPIOA.


STEP 1. Enable signal clock to the appropriate GPIO module. 

Set the appropriate bits in the RCGCGPIO register to enable clock signal to the GPIOA.



Datasheet - General-Purpose Input/Output Run Mode Clock Gating Control (RCGCGPIO), offset 0x608, p.340



It’s telling you that to enable the clock and access to the GPIO Port A module, bit 0 in the RCGCGPIO register must be set to 1


SYSCTL->RCGCGPIO |= 0x01;     //STEP1: enable clock signal to GPIOA




STEP 2. Set the direction of the pins either as input or output. 


SKIP STEP 2




STEP 3A. Enable the corresponding GPIO line with an alternate function.


Each GPIO line can be configured as a GPIO or have another alternate function. 

Table 23-5 on page 1351 details which functions are muxed on each GPIO pin.


In our case, PA0 and PA1 would be enabled to act as an ALT function in the GPIOAFSEL since both can act as UART or CAN.


Datasheet - GPIO Alternate Function Select (GPIOAFSEL), offset 0x420, p.671


GPIOA->AFSEL = 0x03;    /* STEP3A. Use PA0, PA1 alternate function */


Note: We set bits 1-0 because those represent pins 17 & 18. PA0 = 17, PA1 = 18. See the schematic.





STEP 3B. Selects the specific peripheral signal for the corresponding selected GPIO line.


Datasheet - GPIO Port Control (GPIOPCTL), offset 0x52C, p.688


Each PMCn field in the GPIOPCTL register represents a GPIO line. 8 lines in total -> from bit 0 to 31.



For each line you could select a specific peripheral signal to be used on those lines. The specific signal is represented by a value between 1 to 15 in Table 23-5 on page 1351.


Digital  Function 1 is the value that should be placed in the PMC1 and PMC1 fields of the  GPIOPCTL register to assign the UART ALT function to the GPIO Port A line 0 (Rx) and 1 (Tx) .


GPIOA->PCTL = 0x11;    /* STEP3B. Configure PA0 and PA1 for UART */




STEP 4. Set the drive strength for each of the pins through the GPIODR2R, GPIODR4R, and GPIODR8R registers.



STEP 5. Configure SW1 & SW0 by enabling the pull up resistor.

Note:  STEPs 4 - 5 would be skipped since those are features not needed at the moment.



STEP 6. Set up GPIO pins as digital I/Os.

To enable GPIO pins as digital I/Os, set the appropriate DEN bit in the GPIODEN register.

Datasheet - GPIO Digital Enable (GPIODEN), offset 0x51C. Page 682

Enable GPIODEN register bits 1:0 as digital by setting bits from 0 to 1. 


GPIOA->DEN = 0x03;    /* STEP6. Enable PORTF2-0 DIGITAL pins */


STEP 7: Enable and configure the GPIO Interrupt options


SKIP STEP 7





Part II. UART Initialization and Configuration

This section goes through the initialization and configuration for the Universal Asynchronous Receivers/Transmitters (UARTs), datasheet p. 902.



STEP 1. Enable clock signal to the UART Module.

For us to be able to use the UART0 we must first enable the clock signal to the UART Modules by setting the appropriate R0 bit in the RCGCUART register to 1.

Datasheet - Universal Asynchronous Receiver/Transmitter Run Mode Clock

Gating Control (RCGCUART), offset 0x618, p.344



SYSCTL->RCGCUART |= 1; /* STEP1. Enable clock signal to UART0. */



STEP 2. Disable UART0 before making any changes.


Disable the UART by clearing the UARTEN bit in the UARTCTL register.


Datasheet - UART Control (UARTCTL), offset 0x030, p.918


UART0->CTL = 0x00; /* STEP2. Disable UART0 before any changes */




STEP3. The Baud-Rate Divisor (BRD)

3A. Write the integer portion of the BRD to the UARTIBRD register.


Datasheet - UART Integer Baud-Rate Divisor (UARTIBRD), offset 0x024, p.914


UART0->IBRD = 104; /* STEP3A. 16Mhz/16 = 1MHz, 1Mhz/104 = 9600 baud rate */




3B. Write the fractional portion of the BRD to the UARTFBRD register.


Datasheet - UART Fractional Baud-Rate Divisor (UARTFBRD), offset 0x028, p.915



UART0->FBRD = 11; /* STEP3A. fraction part, see Example 4-4 */





STEP4. Write the desired serial parameters to the UARTLCRH register (in this case, a value of 0x0000.0060).


Desired UART Serial configuration:

¦ 9600 baud rate

¦ Data length of 8 bits

¦ One stop bit

¦ No parity

¦ FIFOs disabled

¦ No interrupts


Datasheet - UART Line Control (UARTLCRH), offset 0x02C, p.916


UART->LCRH = 0x60; /* 8-bit, no parity, 1-stop bit, no FIFO */




STEP5. Configure the UART clock source by writing to the UARTCC register.

Datasheet - UART Line Control (UARTLCRH), offset 0xFC8, p.939

    UART->CC = 0; /* STEP5. use system clock */

STEP6. Optional


STEP7. Enable the UART by setting the UARTEN bit in the UARTCTL register

Datasheet - UART Control (UARTCTL), offset 0x030, p.918


    UART0->CTL = 0x301; /* STEP7. Enable UART0, TXE, RXE */





Part III. UART Flag Register (Status)


Monitor the TXFF flag bit in the UART Flag register (UARTFR) and when it goes LOW (buffer not full), write a byte into the Data register to be transmitted.

The following function “UART0Tx(char c)” was created for this purpose:

void UART0Tx(char c)

{

  /* -------------------------- PART III -------------------------- */

  while ((UART0->FR & 0x20) != 0);/* wait until Tx buffer not full */  

  UART0->DR = c; /* before giving it another byte */

  /* ----------------------- PART III (END) ----------------------- */

}



You have reached the end of the Initialization and Configuration for the GPIO Port A and the UART module, plus monitoring the status flag to know when to send the character “Yes” to the terminal emulator program at your PC.

Now:

  • Press the Download & Debug at the top of the IAR tool bar to upload the code to your Tiva LaunchPad.

  • Then, open your terminal emulator program (PuTTY for example). Serial configuration is as follows: Note: Go to Device Manager and validate which COMX is your Tiva LaunchPad connected to.

  • Open a section. You should be able to see the word “Yes” in the terminal emulator screen.


Congratulations! You have configured an UART module from the Tiva TM4C123GH6PM to transmit the word “Yes” serially through an terminal emulator.

CODE:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/*
UART 

Sending "Yes" to UART0 on TI ARM Launchpad (TM4C123GH6PM)
UART0 is on USB/Debug
Use PuTTY to see the message "YES" on a PC

Desired UART configuration:
¦ 9600 baud rate
¦ Data length of 8 bits
¦ One stop bit
¦ No parity
¦ FIFOs disabled
¦ No interrupts

*/

#include <stdint.h>
#include <TM4C123GH6PM.h>       //Tiva C Series TM4C123G “Header File”.

void GPIO_init(void);
void UART0_init(void);

void UART0Tx(char c);
void delayMs(int n);

int main(void)
{
  GPIO_init();
  UART0_init();
  
  delayMs(1);			/* wait for output line to stabilize */
  
  for (;;)
  {
    UART0Tx('Y');
    UART0Tx('E');
    UART0Tx('S');
    UART0Tx(' ');
  }
}

void GPIO_init(void)
{
  /* ---------------------------- PART I ---------------------------- */
  /* ------------ GPIOA Initialization and Configuration ------------ */
  SYSCTL->RCGCGPIO |= 0x01;     /* STEP1. Enable clock signal to the GPIOA */     
  /*SKIP STEP2*/
  GPIOA->AFSEL = 0x03;	        /* STEP3A. Use PA0, PA1 alternate function */
  GPIOA->PCTL = 0x11;           /* STEP3B. Configure PA0 and PA1 for UART */
  /*SKIP STEP4 - 5*/
  GPIOA->DEN = 0x03;            /* STEP6. Enable PORTF2-0 DIGITAL pins */  
  /* ------------------------ PART I (END) -------------------------- */  
}

void UART0_init(void)
{
  /* --------------------------- PART II -------------------------- */
  /* ----------- UART Initialization and Configuration ---------- */
  SYSCTL->RCGCUART |= 1;        /* STEP1. Enable clock signal to UART0. */  
  UART0->CTL = 0x00;	        /* STEP2. Disable UART0 before any changes */ 
  
  /* desire configuration */
  UART0->IBRD = 104;	/* STEP3A. 16Mhz/16 = 1MHz, 1Mhz/104 = 9600 baud rate */
  UART0->FBRD = 11; 	/* STEP3B. Fraction part, see Example 4-4 */
  UART0->LCRH = 0x60;	/* STEP4. 8-bit, no parity, 1-stop bit, no FIFO */
  UART0->CC = 0;		/* STEP5. Use system clock */
  /*SKIP STEP6*/
  UART0->CTL = 0x301;	/* STEP7. Enable UART0, TXE, RXE */ 
  /* ------------------------ PART II (END) ------------------------ */
}

void UART0Tx(char c)
{
  /* --------------------------- PART III -------------------------- */
  /* ----------------- UART Flag Register (Status) ----------------- */
  while ((UART0->FR & 0x20) != 0);				/* wait until Tx buffer not full */  
  UART0->DR = c;						/* before giving it another byte */
  /* ------------------------ PART III (END) ----------------------- */
}

void delayMs(int n)
{
	int i, j;
	for(i = 0; i < n; i++)
          for(j=0; j < 3180; j++)
            {}	// do nothing for 1 ms 
}



Comments