This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TM4C123GH6PM: Address of GPIODATA register

Part Number: TM4C123GH6PM

Hy,

I have bought Tiva C Series TM4C123G LaunchPad Evaluation Kit and i am very satisfied, works very well.

I have implemented some code from the youtube tutorials, something like this : 

#include <lm4f120h5qr.h>

int main()
{
    int counter = 0;
    
    // General Purpose Input/Output Run Mode Clock Gating Control (RCGCGPIO)
    *((unsigned int*)0x400FE608) = 0x20;
    
    // The RGB leds are connected to PF1, PF2, PF3
    // GPIO Direction - GPIODIR
    *((unsigned int*)0x40025400) = 0x0E;
    
    // GPIO Digital Enable - GPIODEN
    *((unsigned int*)0x4002551C) = 0x0E;
        
    while(1)
    {
        // GPIO Data - GPIODATA - Red led ON
        *((unsigned int*)0x400253FC) = 0x02;
        counter = 0;
        while(counter < 1000000)
        {
            counter++;
        }
        // GPIO Data - GPIODATA - Blue led ON
        *((unsigned int*)0x400253FC) = 0x04;
        counter = 0;
        while(counter < 1000000)
        {
            counter++;
        }
        // GPIO Data - GPIODATA - Green led ON
        *((unsigned int*)0x400253FC) = 0x08;
        counter = 0;
        while(counter < 1000000)
        {
            counter++;
        }
    }
    return 0;
}

This code works very well, but my problem is why, when i want to access GPIODATA the address is 0x400253FC.
In the datasheet of microcontroller the address of GPIODATA is 0x40025000.
I understand that this controller has six modules (A,B,C,D,E and F) but i cant I can not figure out how to calculate the address above ?
Thank you.

  • This code works very well, but my problem is why, when i want to access GPIODATA the address is 0x400253FC.
    In the datasheet of microcontroller the address of GPIODATA is 0x40025000.
    I understand that this controller has six modules (A,B,C,D,E and F) but i cant I can not figure out how to calculate the address above ?
    Thank you.
  • first of all, that's a very poor way of coding. your asking the question here is all the evidence you need.

    2ndly, 3fc is the offset to the data register: take a look at the datasheet and figure out which port it is.
  • Danny F said:
    first of all, that's a very poor way of coding.

    It's actually less type-safe than TIVAWare, that takes some doing. And it has none of the useful abstraction.

    Robert

  • let me expand a little on this, as there was a history behind it.

    when Luminary was alive and well, this issue was brought up to their attention: this portion of the datasheet was not particularly well written and did not have full description of the port structure. i'm not sure if the same was taken to TI after their acquisition of luminary.

    anyway, the first 255 dwords of each port is the single-cycle bit-banding implementation. the datasheet has a crazy way of describing its operations.

    the next dword, at offset 0x3fc, is the data register. there is no disclosure of that in the datasheet, however. the CMSIS implementation I posted here shows that in more clear form:

    /**
      * @brief Register map for GPIOA peripheral (GPIOA)
      */
    
    typedef struct {                                    /*!< GPIOA Structure                                                       */
      __IO uint32_t  RESERVED0[255];
      __IO uint32_t  DATA;                              /*!< GPIO Data                                                             */
      __IO uint32_t  DIR;                               /*!< GPIO Direction                                                        */
      __IO uint32_t  IS;                                /*!< GPIO Interrupt Sense                                                  */
      __IO uint32_t  IBE;                               /*!< GPIO Interrupt Both Edges                                             */
      __IO uint32_t  IEV;                               /*!< GPIO Interrupt Event                                                  */
      __IO uint32_t  IM;                                /*!< GPIO Interrupt Mask                                                   */
      __IO uint32_t  RIS;                               /*!< GPIO Raw Interrupt Status                                             */
      __IO uint32_t  MIS;                               /*!< GPIO Masked Interrupt Status                                          */
      __O  uint32_t  ICR;                               /*!< GPIO Interrupt Clear                                                  */
      __IO uint32_t  AFSEL;                             /*!< GPIO Alternate Function Select                                        */
      __I  uint32_t  RESERVED1[55];
      __IO uint32_t  DR2R;                              /*!< GPIO 2-mA Drive Select                                                */
      __IO uint32_t  DR4R;                              /*!< GPIO 4-mA Drive Select                                                */
      __IO uint32_t  DR8R;                              /*!< GPIO 8-mA Drive Select                                                */
      __IO uint32_t  ODR;                               /*!< GPIO Open Drain Select                                                */
      __IO uint32_t  PUR;                               /*!< GPIO Pull-Up Select                                                   */
      __IO uint32_t  PDR;                               /*!< GPIO Pull-Down Select                                                 */
      __IO uint32_t  SLR;                               /*!< GPIO Slew Rate Control Select                                         */
      __IO uint32_t  DEN;                               /*!< GPIO Digital Enable                                                   */
    } GPIOA_Type;
    

    noticed RESERVED0[] is a 32-bit type? that's what we are talking about.

    So you have two ways to read/write to the port.

    1) via the data register:

      LED_PORT->DATA |= LED;  //set led
      LED_PORT->DATA &=~LED;  //clr led
    

    2) via the bit banding area
      LED_PORT->RESERVED0[LED] = LED; //set led
      LED_PORT->RESERVED0[LED] =~LED; //clear led
    

    the advantage of the 2nd approach is that it is inherently atomic and often faster.

    if you prefer, you can rename RESERVED0[] to something more to your liking.

    But that is much more readable than the HWREG() macro TI has in its driverlib.