Embedded C Programing w/ TM4C123G Microcontroller - 1.0 Register Addresses

The aim of the following exercises is to provide the basic understanding of Embedded System programming.

In this particular exercise you will learn how to program the Tiva TM4C123G LaunchPad to toggles the Green LED, ON & OFF, by directly accessing hardware register addresses.

To cover basic C Programing concept, the same code will be modify to include function, macros and/or header files to become conversant with Embedded System.

Objective: 


  • Provide an Assembly Language example to blink an LED in the TM4C123G microcontroller. 

  • Explain the concept of Macros

  • Explain the concept of Header Files


Reference Documents: 

  1. TM4C123G User Manual 

  2. TM4C123G Datasheet 

  3. TM4C123G LaunchPad Evaluation Board User Guide (With Schematic)


User Manual - Board Overview, p.4


Physical representation of the Red-Green-Blue (RGB) LEDs in the TM4C123G Launchpad




User Manual - Schematics, p.20


Use the schematic to identify how the Red-Green-Blue (RGB) LEDs are connected to the microcontroller:


PF1, PF2, & PF3.


The “P” stands for “port” and the letter “F” stands for the block F.

Note: Block F is one of the six blocks within the General-Purpose Input/Outputs (GPIOs) module.


The numbers 1, 2, & 3 represent the pins (or bit in register to be manipulated - explained later). 




GPIO Port F is the block in the GPIO module where the LEDs are connected to.




How to program the Tiva TM4C123G LaunchPad to toggles the red LED, ON & OFF?


The  TM4C123G datasheet  provides a series of steps to Initialize and Configure GPIO pins of a particular block. In specific the following section: 


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


The steps are summarize below:

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

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

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

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

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. 

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

STEP 7: Enable and configure the GPIO Interrupt options



I will go through each one of the 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). 




GPIOF Initialization and Configuration

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

DATA SHEET, p.656.


This section describes the steps you need to follow to access and configure the GPIO pins of a particular block. In our case the block we want to manipulate is block F: Base Address: 0x400FE000.


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


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



To begin with, take note of the following:

  • Offset 0x608 : 

    The datasheet specify an offset of
    0x608 for the (RCGCGPIO) register. This means that (RCGCGPIO) is a distance apart from a starting point. What is that starting point? - The base address (Next). 

  • Base Address 0x400FE000

    You will notice that the (RCGCGPIO) resides within the System Control module. This module is indeed a collection of registers, typically accessed through memory-mapped registers, allowing a user to configuring the microcontroller and its peripherals through these registers by using assembler or C code instructions.

    The starting point of this System Control module is
    0x400FE000. Also know as the base address. 

  • Final Address 0x400F.E608

    Therefore, to access and modify the
    (RCGCGPIO) register, you would need to calculate the final address as: 

    Final Address = Base Address + Offset =
    0x400F.E000 + 0x608 = 0x400F.E608 

    This is the memory location where you should write an [X] value to configure the (RCGCGPIO) register. 

Having said that, take a look to the Datasheet - (RCGCGPIO), p.340.

It’s telling you that to enable the clock and access to the GPIO Port F module, bit 5 in the RCGCGPIOregister must be set to 1. Go to address: 0x400FE608U (Base + Offset) and set up bit 5 to one. 


Code:


//Clock Gating Register

*((unsigned int *) 0x400FE608U) = 0x20U;


Note: Review Binary / Hex numbers & Pointers if you didn’t understand the previous sentence. 



Note: From now on, in a similar fashion, for each one of the following registers, we will use the "Base Address" and "Offset" distance to configure/modify his function.





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


Datasheet - GPIO Direction (GPIODIR), offset 0x400. Page 663





Base:
0x4002.5000 / Offset: 0x400


To blink an LED you will like to use the pins 1, 2 & 3 as outputs. Therefore, pins 1, 2 & 3 in the GPIODIR register needs to be set as 1.


Again, go to address 0x40025400U (Base + Offset) and set up bits 1, 2, & 3 to one. (e.i. from 0x0000.0000 to 0x0000.000E). 


Code: 


//GPIODIR Register

*((unsigned int *)0x40025400U) = 0x0EU;



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

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 3 - 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



GPIO Port F (APB) Base: 0x4002.5000 / Offset 0x51C.


Enable GPIODEN register pins 1, 2, & 3 as digital pins by setting pins 1, 2, & 3 from 0 to 1.


Same thing, go to address 0x4002551CU Base + Offset) and set up bits 1, 2, & 3 to one. (e.g. 0x0000.0000 to 0x0000.000E).


Code: 


//GPIODEN Register

*((unsigned int *) 0x4002551CU) = 0x0EU;





STEP 7: Enable and configure the GPIO Interrupt options

    • The GPIO bits (also it can be refer as ports) are connected to the CPU through a bunch of wires called “bus”. 
    • Each GPIO port is connected to both a dedicated “data line” (the once's in blue) and a dedicated “address line” (the once's in red). 
    • Only when the connected “address line” is one, a bit data value can be changed.
    • Otherwise the bit is unaffected regardless of the value of the attached data line.

    Basically, what we have been doing so far.



    For example:


    To isolate the three GPIO bits connected to the LEDs you could write to the address ending with an offset of: 0x038 and change their data value. 


    Or any of the 256 addresses where A5, A4 & A3 are one. If you wish to simplify things just set up all to ones ( e.i. an offset address of 0x3FC ( 1111111100). 


    With this information on hands you can now manipulate the LEDs through the GPIODATA register.


    Values written in the GPIODATA register are transferred onto the GPIO port pins if the respective pins have been configured as outputs. Wish we already did.


    So, it’s a matter of going to address 0x40025038U and set bits 1, 2 & 3 of the GPIODATA register to one if you want to turn ON the LEDs or zero to turn them OFF.


    GPIO Data (GPIODATA), offset 0x000, p.662



    Code:


    *((unsigned int *)0x400253FCU) = 0x02U;


    *((unsigned int *)0x400253FCU) = 0x02U;



    Preliminary Code
    /*
    This program toggles the Green LED ON & OFF by using register addresses.  
    The other LEDs (Red & Blue) can be configured as well. All LEDs are high active (a "1" turns ON the LED). PF1 - red LED PF2 - blue LED PF3 - green LED */ int main() { //Clock Gating Register *((unsigned int *)0x400FE608U) = 0x20U; //enable clock signal to GPIOF //GPIODIR Register *((unsigned int *)0x40025400U) = 0x0EU; //Setting bits 3-1 as outputs //GPIODEN Register *((unsigned int *)0x4002551CU) = 0x0EU; //Setting bits 3-1 as digital pins while (1) { //*((unsigned int *)0x400253FCU) = 0x02U; //Setting bit 1 to turn Red LED ON //*((unsigned int *)0x400253FCU) = 0x04U; //Setting bit 2 to turn Blue LED ON *((unsigned int *)0x400253FCU) = 0x08U; //Setting bit 3 to turn Green LED ON //Offset: 0x3FC - Bit banding int counter = 0; while (counter < 1000000) { ++counter; } *((unsigned int *)0x400253FCU) = 0x00U; //Turn OFF LED counter = 0; while (counter < 1000000) { ++counter; } } //return 0; }

     


    Connect your Tiva TM4C123G LaunchPad to your PC. 

    (Make sure the Power Select switch is to the right for Debug mode).



    Copy and Paste the code onto your development environment tool and run the program. LEDs should be blinking. 


    By now you are able to turn ON and OFF an LED by programming the Tiva TM4C123G LaunchPad using register addresses.


    What is Next? --> Link

    Functions, Macros & Header Files


    ... to simply things : )








    Comments