Search code examples
cstm32f7

GPIO Output Register Bit value not updating


I just started learning about embedded systems and I'm having a bit of trouble with correctly setting up the led pin on my stm32f746ng-discovery board. I am not sure if I am not typecasting correctly or have the wrong address for the pin however, I do believe I have addressed everything correctly and I'm not seeing a value change for the GPIO output data register in the watch window which leads me to believe there might be an issue with my code.

To define the registers and their respective addresses this is the approach I took:

//Referring to STM32F746xx Memory Map and Register Boundary Addresses:
#define PERIPH_BASE             (0x40000000UL)

#define AHB1PERIPH_OFFSET       (0x00020000UL)
#define AHB1PERIPH_BASE         (PERIPH_BASE + AHB1PERIPH_OFFSET)

#define GPIOI_OFFSET            (0x2000UL)
#define GPIOI_BASE              (AHB1PERIPH_BASE + GPIOI_OFFSET)

#define RCC_OFFSET              (0x3800UL)
#define RCC_BASE                (AHB1PERIPH_BASE + RCC_OFFSET)

#define RCC_AHB1EN_R_OFFSET     (0x30UL)
#define RCC_AHB1EN_R            (*(volatile unsigned int *)(RCC_BASE + RCC_AHB1EN_R_OFFSET)) //register

#define MODE_R_OFFSET           (0x00UL)
#define GPIOI_MODE_R            (*(volatile unsigned int *)(GPIOI_BASE + MODE_R_OFFSET)) //register

#define OD_R_OFFSET             (0x14UL)
#define GPIOI_OD_R              (*(volatile unsigned int *)(GPIOI_BASE + OD_R_OFFSET)) //register

#define GPIOIEN                 (1U << 0)

#define PIN_1                   (1U << 1)
#define LED_PIN                 PIN_1

The above hex addresses I located from the stm32f746xx datasheet's memory map/table and RM0385 reference manual for the stm32f74xxx.

The code below is the main function where I try to change the bit value of the GPIOI_OD_R register:

int main(void)
{
    /* 1. Enable clock access for GPIOI.*/
    /* 1.1 I use the OR operator to only change the first bit instead of the whole 32bit chain. */
    RCC_AHB1EN_R |= GPIOIEN;

    /* 2. Sets PIN_1 as output.*/
    GPIOI_MODE_R |= (1U << 2);
    GPIOI_MODE_R &=~(1U << 3);

    while(1)
    {
        /* 3. Sets PIN_1 high */
        GPIOI_OD_R |= LED_PIN;

    }
}

The problem that I am having is that the bit value for the GPIOI_OD_R register is not updating correctly and gets set to 00 instead of 01 which is the required value for the GPIOI Pin_1 (LED) to be set to the general-purpose output mode.

The above parameters I got from the RM0385 reference manual for the stm32f74xxx which can be seen in the image below:

GPIO mode register

However, when running the code the GPIOI_MODE_R and the GPIOI_OD_R bit values do not change which can be seen in the image below:

GPIO register no value change

I need the values of the registers to be correct to set the LED PIN high on my stm32f746ng-discovery board.

I tried combining the GPIOI_MODE_R setting operation into a single one: GPIOI_MODE_R = (GPIOI_MODE_R | (1U << 2)) & ~(1U << 3) however that causes the program to loose connection with the debugger.

I am using the STM32CubeIDE with the following MCU GCC Compiler Settings: MCU GCC Compiler Settings

Thanks in advance and if have referenced something incorrectly please excuse me im new to embedded systems.


Solution

  • I found the issue and realised that I was addressing the wrong bit value for the GPIOIEN. Instead of looking at the bit address for GPIOIEN with:#define GPIOIEN (1U << 8) I was making the mistake to look at the bit address for GPIOAEN with:#define GPIOIEN (1U << 0). enter image description here

    A super silly mistake from my side however I think it might be a mistake that many beginners like myself may make. The only advice that I can give from what I experienced and the process it took to solve the issue is to try and be extra accurate and properly focus when reading through the various board's references manuals and datasheets. When it comes to solving the issue I would say it is important to stay consistent with your code which makes it much easier during the debugging process because I followed this methodology I was able to trace each srep of my code and compare what I expected the values to be versus what I was actually getting.

    The final code solution I have attached below:

    //Referring to STM32F746xx Memory Map and Register Boundary Addresses:
    #define PERIPH_BASE             (0x40000000UL)
    
    #define AHB1PERIPH_OFFSET       (0x00020000UL)
    #define AHB1PERIPH_BASE         (PERIPH_BASE + AHB1PERIPH_OFFSET)
    
    #define GPIOI_OFFSET            (0x2000UL)
    #define GPIOI_BASE              (AHB1PERIPH_BASE + GPIOI_OFFSET)
    
    #define RCC_OFFSET              (0x3800UL)
    #define RCC_BASE                (AHB1PERIPH_BASE + RCC_OFFSET)
    
    #define RCC_AHB1EN_R_OFFSET     (0x30UL)
    #define RCC_AHB1EN_R            (*(volatile unsigned int *)(RCC_BASE + RCC_AHB1EN_R_OFFSET))
    
    #define MODE_R_OFFSET           (0x00UL)
    #define GPIOI_MODE_R            (*(volatile unsigned int *)(GPIOI_BASE + MODE_R_OFFSET))
    
    #define OD_R_OFFSET             (0x14UL)
    #define GPIOI_OD_R              (*(volatile unsigned int *)(GPIOI_BASE + OD_R_OFFSET))
    
    #define GPIOIEN                 (1U << 8) // updated from (1U << 0)
    
    #define PIN_1                   (1U << 1)
    #define LED_PIN                 PIN_1
    
    int main(void)
    {
        /* 1. Enable clock access for GPIOI.*/
        /* 1.1 I use the OR operator to only change the first bit instead of the whole 32bit chain. */
        RCC_AHB1EN_R |= GPIOIEN;
    
        /* 2. Sets PIN_1 as output.*/
        GPIOI_MODE_R |= (1U << 2);
        GPIOI_MODE_R &=~(1U << 3);
    
        while(1)
        {
            /* 3. Sets PIN_1 high */
            GPIOI_OD_R |= LED_PIN;
    
        }
    }