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.

Problem with Blinking LED on SK-TDA4VM Board using Baremetal Programming

Part Number: SK-TDA4VM

Tool/software:

Dear TI-support team,

I am a beginner in baremetal programming and I am trying to make an LED blink using the SK-TDA4VM board. I have an LED connected to physical pin 16, which, according to the user guide of the board, corresponds to GPIO0_5.

I am having difficulties getting the LED to light up. My code runs without any issues, but the LED does not turn on. It is based on the addresses of the GPIO0_5 registers, but I am not sure if I fully understood the documentation (Technical Reference Manual), so I might be using incorrect addresses. I have tried several addresses, but nothing has worked so far.

Additionally, I thought the issue might be related to the clock, so I added the PLL configuration to my code, but still, the LED does not turn on.

Here is the code I am using:

#include <stdint.h> // For the type uint32_t

#define GPIO0_BASE_ADDR   0x00620000
#define GPIO_SETDATA_OFFSET 0x18  // Offset for the SET_DATA register of bank 0
#define GPIO_CLRDAT_OFFSET  0x1C  // Offset for the CLR_DATA register of bank 0
#define GPIO_DIR_OFFSET   0x10  // Offset for the DIR register of bank 0
#define GPIO0_5 (1 << 5)  // Pin 5 (bit 5 of the register)

#define PLLCTRL0_BASE_ADDR  0x00410100  // Address of the PLLCTRL0 register
#define PLLEN_BIT           (1 << 0)    // Bit 0: PLL Mode Enable

int main(void) {
    // 0. Enable PLL Mode
    volatile uint32_t *pllctrl0 = (uint32_t *)PLLCTRL0_BASE_ADDR;
    *pllctrl0 |= 1;  // Set bit 0 to enable PLL Mode

    // Define pointers for bank 0 registers
    volatile uint32_t *gpio0_dir = (uint32_t *)(GPIO0_BASE_ADDR + GPIO_DIR_OFFSET);
    volatile uint32_t *gpio0_setdata = (uint32_t *)(GPIO0_BASE_ADDR + GPIO_SETDATA_OFFSET);
    volatile uint32_t *gpio0_clrdata = (uint32_t *)(GPIO0_BASE_ADDR + GPIO_CLRDAT_OFFSET);

    // 1. Configure GPIO0_5 as output
    *gpio0_dir &= ~GPIO0_5;  // Set bit 5 to 0 to configure as output

    while (1) {
        // 2. Turn on the LED (GPIO0_5 = 1)
        *gpio0_setdata = GPIO0_5; // Set pin 5 (turns on the LED)

        // Delay to see the LED blink
        for (uint32_t i = 0; i < 500000; i++);

        // 3. Turn off the LED (GPIO0_5 = 0)
        *gpio0_clrdata = GPIO0_5; // Clear pin 5 (turns off the LED)

        // Delay to see the LED blink
        for (uint32_t i = 0; i < 500000; i++);
    }

    return 0;
}


I am using arm-none-eabi-gcc to compile for the R5 core of the main domain and Code Composer Studio (CCS), along with an XDS110, just to run the already compiled code and debug.

If you could assist me, I would greatly appreciate it!

Thank you in advance for your help!


  • Hi Heverton,

    My recommendation would be to use this C++ library under Linux: https://github.com/TexasInstruments/ti-gpio-cpp. If you are familiar with Raspberry Pi, the development environment would be similar to Linux/Raspbian as opposed to RTOS for MCUs.

    For reasoning, we do not support running baremetal/RTOS on the SK boards. Our RTOS/baremetal demos are primarily developed for the larger (and more expensive) EVM boards as opposed to the smaller SK boards with less peripherals pinned out to the board. Although, technically, it is possible to run RTOS/baremetal on the SK boards (support from TI will be limited).

    Now, with the large disclaimer that RTOS/baremetal programming is not officially supported on SK boards, I can give some pointers if you choose to go down this path:

    Regards,

    Takuma

  • Hi Takuma,

    Thank you for your response and the guidance regarding using the C++ library for GPIO. I understand that Texas Instruments does not officially support baremetal programming on SK boards, but it's the only board I currently have at the moment, and I want to proceed with baremetal development on it nonetheless.

    I have followed the steps in the FAQ you provided and made sure my code closely resembles the examples given. Specifically, I implemented the steps to unlock the CTRL MMR and modified the registers according to the pin I want to control. However, despite my efforts, I am still facing issues with the LED not turning on.

    I also attempted to use the OUTDATA register as outlined in the FAQ, but it did not work, so I tried using the SETDATA and CLR registers instead. Here is a snippet of my code for reference:

    #include <stdint.h>
    
    // Address and register definitions
    #define GPIO0_BASE_ADDR       0x00600000
    #define GPIO_OUTDATA_OFFSET   0x14  
    #define GPIO_SETDATA_OFFSET   0x18
    #define GPIO_CLRDATA_OFFSET   0x1C 
    #define GPIO_DIR_OFFSET       0x10 
    
    #define PADCONFIG          5            // Configuration for GPIO0_5
    #define PADCONFIG_ADDR     0x0011C014 // Base address for PADCONFIG (Offset = 1C014)
    #define PINMUX_VALUE(_rxActive, _pullType, _pull, _mux)  ((_rxActive << 18) | (_pullType << 17) | (_pull << 16) | (_mux << 0))
    
    #define RX_ACTIVE          1
    #define RX_INACTIVE        0
    #define PULL_DOWN          0
    #define PULL_UP            1
    #define PULL_ENABLED       0
    #define PULL_DISABLED      1
    #define MUX_MODE_7         0x7  // MUX MODE 7 to configure the pin as GPIO
    
    // GPIO Definitions
    #define GPIO0_5               (1 << 5)  // Pin GPIO0_5 (Bit 5)
    
    //volatile uint32_t *gpio_outdata = (uint32_t *)(GPIO0_BASE_ADDR + GPIO_OUTDATA_OFFSET);  // Out data register
    volatile uint32_t *gpio_setdata = (uint32_t *)(GPIO0_BASE_ADDR + GPIO_SETDATA_OFFSET);  // Set data register
    volatile uint32_t *gpio_clrdata = (uint32_t *)(GPIO0_BASE_ADDR + GPIO_CLRDATA_OFFSET);  // Clear data register
    
    volatile uint32_t *LOCK7_KICK0  = (uint32_t *) 0x0011D008;   // Address of LOCK7_KICK0
    
    volatile uint32_t *padconfig = (uint32_t *) PADCONFIG_ADDR;  // Pointer to PADCONFIG
    
    volatile uint32_t *gpio_dir = (uint32_t *)(GPIO0_BASE_ADDR + GPIO_DIR_OFFSET);  // Direction register
    
    // Function to unlock the MMR
    void unlock_padconfig() {
        LOCK7_KICK0[0] = 0x68EF3490;  // Unlock value 1
        LOCK7_KICK0[1] = 0xD172BC5A;  // Unlock value 2
    }
    
    // Function to configure the pin as GPIO with pull-up
    void configure_pad(void) {
        // Configure PADCONFIG for GPIO0_5 with MUXMODE = 7 and PULL-DOWN enabled
        padconfig[PADCONFIG_ADDR] = PINMUX_VALUE(RX_INACTIVE, PULL_DOWN, PULL_ENABLED, MUX_MODE_7);
    }
    
    // Function to initialize the GPIO and set the direction as output
    void gpio_init() {
        *gpio_dir &= 0xffff0000;  // Set GPIO0_5 as output
    }
    
    // Function to turn on the LED
    void led_on() {
        //*gpio_outdata |= 0x0000ffff;  // Set pin GPIO0_5 to 1 (on)
        *gpio_setdata |= 0x0000ffff; 
    }
    
    // Function to turn off the LED
    void led_off() {
        //*gpio_outdata &= 0xffff0000;  // Set pin GPIO0_5 to 0 (off)
        *gpio_clrdata &= 0xffff0000;
    }
    
    // Simple delay function
    void delay(volatile int count) {
        while (count--) {
            // Wait loop
        }
    }
    
    // Main function
    int main() {
        unlock_padconfig();  // Unlock the MMR registers
        configure_pad();  // Configure PADCONFIG for GPIO
        gpio_init();      // Initialize the GPIO
    
        while (1) {
            led_on();     // Turn on the LED
            delay(1000000); // Wait
            led_off();    // Turn off the LED
            delay(1000000); // Wait
        }
    
        return 0;
    }
    


    I would appreciate any further insights you may have to help resolve this issue. Thank you for your support!

    Best regards,
    Heverton

  • Hi Heverton,

    From a glance, everything does look to be in place. Could you read out each of the registers to confirm that the changes are made to each register? Just in case there is a different lock that is causing the writes to not happen.

    Regards,

    Takuma

  • Hi Takuma,

    Thank you for the suggestion. I'll check the register states as you advised, but unfortunately, I won’t be able to do it today. I’ll test this tomorrow and provide an update then.

    I appreciate your continued support!

    Best regards,
    Heverton

  • Hi Takuma,

    I was able to read out the register values after trying to toggle the LED. Here are the results:

    • clrdata_value:

      • Decimal: 65535
      • Hexadecimal: 0x0000FFFF
    • dir_value:

      • Decimal: 4294901760
      • Hexadecimal: 0xFFFF0000
    • lock_value0:

      • Decimal: 1760507025
      • Hexadecimal: 0x68EF3491
    • lock_value1:

      • Decimal: 3513957466
      • Hexadecimal: 0xD172BC5A
    • padconfig_value:

      • Decimal: 136396807
      • Hexadecimal: 0x081F0007
    • setdata_value:

      • Decimal: 65535
      • Hexadecimal: 0x0000FFFF

    It seems that these values are in line with what I have set in the code. Please let me know if these values help in identifying the issue or if you need any additional information.

    Thank you!

    Best regards,
    Heverton

  • Hi Heverton,

    If that is the case, then I recommend switching to the EVM board, or switching to the Linux library.

    Again, support for baremetal programming is limited with the combination of hardware/software that is currently in use. I understand EVM board is more expensive, but the cost includes the software support.

    Regards,

    Takuma