简体   繁体   中英

STM32F446xx Peripheral Register Access Difference Between Using Dereferenced Pointers and Structs

I'm trying to simply light up an external LED (wired to my STM32F446RE's Port C Pin 10). I'm using the gcc-arm-none-eabi 8-2019-q3-update for windows for my compiler and Keil uVision5 IDE for flashing/debugging the board (the Keil IDE also handles compilation with the GCC compiler).

In the following code when using structs to reference the GPIO and RCC peripheral registers (the second "section" of main) everything works perfectly. The RCC->AHB1ENR and GPIOC->MODER write lines properly update the values at the associated memory addresses and the LED does light up.

However, when using dereferenced pointers (the first "section" of main) the LED does not light. When debugging this issue, the memory locations for all of the registers are NOT being written to after executing the *GPIOC_MODER and *RCC_AHB1ENR lines.

What is the difference between these two approaches and why does one work and not the other? I've triple checked the addresses with the STM32F446xx data sheet ( https://www.st.com/content/ccc/resource/technical/document/reference_manual/4d/ed/bc/89/b5/70/40/dc/DM00135183.pdf/files/DM00135183.pdf/jcr:content/translations/en.DM00135183.pdf ) and even if the addresses were incorrect, the struct-based approach shouldn't work.

#include <stdint.h>

/* General Purpose Input Output Registers, Address Range 0x4002 0000 - 0x4002 1FFF */
typedef struct
{
    uint32_t volatile MODER;         /* Offset: 0x00 (R/W) Mode Register                                          */
    uint32_t volatile OTYPER;        /* Offset: 0x04 (R/W) Output Type Register                                   */
    uint32_t volatile OSPEEDR;       /* Offset: 0x08 (R/W) Output Speed Register                                  */
    uint32_t volatile PUPDR;         /* Offset: 0x0C (R/W) Pull-up/Pull-down Register                             */
    uint32_t volatile IDR;           /* Offset: 0x10 (R/W) Input Data Register                                    */
    uint32_t volatile ODR;           /* Offset: 0x14 (R/W) Output Data Register                                   */
    uint32_t volatile BSRR;          /* Offset: 0x18 (R/W) Bit Set/Reset Register                                 */
    uint32_t volatile LCKR;          /* Offset: 0x1C (R/W) Configuration Lock Register                            */
    uint32_t volatile AFRL;          /* Offset: 0x20 (R/W) Alternate Function Low Register                        */
    uint32_t volatile AFRH;          /* Offset: 0x24 (R/W) Alternate Function High Register                       */
} GPIO_t;
#define GPIOA ((GPIO_t *)0x40020000)
#define GPIOB ((GPIO_t *)0x40020400)
#define GPIOC ((GPIO_t *)0x40020800)
#define GPIOD ((GPIO_t *)0x40020C00)
#define GPIOE ((GPIO_t *)0x40021000)
#define GPIOF ((GPIO_t *)0x40021400)
#define GPIOG ((GPIO_t *)0x40021800)
#define GPIOH ((GPIO_t *)0x40021C00)

/* Reset and Clock Control Registers (RCC), Address Range: 0x4002 3800 - 0x4002 3BFF */
typedef struct
{
    uint32_t volatile CR;            /* Offset: 0x00 (R/W) Clock Control Register                                 */
    uint32_t volatile PLLCFGR;       /* Offset: 0x04 (R/W) PLL Configuration Register                             */
    uint32_t volatile CFGR;          /* Offset: 0x08 (R/W) Clock Configuration Register                           */
    uint32_t volatile CIR;           /* Offset: 0x0C (R/W) Clock Interrupt Register                               */
    uint32_t volatile AHB1RSTR;      /* Offset: 0x10 (R/W) AHB1 Peripheral Reset Register                         */
    uint32_t volatile AHB2RSTR;      /* Offset: 0x14 (R/W) AHB2 Peripheral Reset Register                         */
    uint32_t volatile AHB3RSTR;      /* Offset: 0x18 (R/W) AHB3 Peripheral Reset Register                         */
    uint32_t volatile reserved0;
    uint32_t volatile APB1RSTR;      /* Offset: 0x20 (R/W) APB1 Peripheral Reset Register                         */
    uint32_t volatile APB2RSTR;      /* Offset: 0x24 (R/W) APB2 Peripheral Reset Register                         */
    uint32_t reserved1[2];
    uint32_t volatile AHB1ENR;       /* Offset: 0x30 (R/W) AHB1 Peripheral Clock Enable Register                  */
    uint32_t volatile AHB2ENR;       /* Offset: 0x34 (R/W) AHB2 Peripheral Clock Enable Register                  */
    uint32_t volatile AHB3ENR;       /* Offset: 0x38 (R/W) AHB3 Peripheral Clock Enable Register                  */
    uint32_t reserved2;
    uint32_t volatile APB1ENR;       /* Offset: 0x40 (R/W) APB1 Peripheral Clock Enable Register                  */
    uint32_t volatile APB2ENR;       /* Offset: 0x44 (R/W) APB1 Peripheral Clock Enable Register                  */
    uint32_t reserved3[2];
    uint32_t volatile AHB1LPENR;     /* Offset: 0x50 (R/W) AHB1 Peripheral Clock Enable Lower Power Mode Register */
    uint32_t volatile AHB2LPENR;     /* Offset: 0x54 (R/W) AHB2 Peripheral Clock Enable Lower Power Mode Register */
    uint32_t volatile AHB3LPENR;     /* Offset: 0x58 (R/W) AHB3 Peripheral Clock Enable Lower Power Mode Register */
    uint32_t reserved4;
    uint32_t volatile APB1LPENR;     /* Offset: 0x60 (R/W) APB1 Peripheral Clock Enable Lower Power Mode Register */
    uint32_t volatile APB2LPENR;     /* Offset: 0x64 (R/W) APB2 Peripheral Clock Enable Lower Power Mode Register */
    uint32_t reserved5[2];
    uint32_t volatile BDCR;          /* Offset: 0x70 (R/W) Backup Domain Control Register                         */
    uint32_t volatile CSR;           /* Offset: 0x74 (R/W) Clock Control & Status Register                        */
    uint32_t reserved6[2];
    uint32_t volatile SSCGR;         /* Offset: 0x80 (R/W) Spread Spectrum Clock Generation Register              */
    uint32_t volatile PLLI2SCFGR;    /* Offset: 0x84 (R/W) PLLI2S Configuration Register                          */
    uint32_t volatile PLLSAICFGR;    /* Offset: 0x88 (R/W) PLLSAI Configuration Register                          */
    uint32_t volatile DCKCFGR;       /* Offset: 0x8C (R/W) Dedicated Clocks Configuration Register                */
    uint32_t volatile CKGATENR;      /* Offset: 0x90 (R/W) Clocks Gated Enabled Register                          */
    uint32_t volatile DCKCFGR2;      /* Offset: 0x94 (R/W) Dedicated Clocks Configuration Register 2              */
} RCC_t;
#define RCC ((RCC_t *)0x40023800)

void main()
{
    /* This section doesn't work */
    uint32_t volatile * const GPIOC_MODER = (uint32_t *)0x40020800;
    uint32_t volatile * const GPIOC_ODR =   (uint32_t *)0x40020814;
    uint32_t volatile * const RCC_AHB1ENR = (uint32_t *)0x40023830;

    *GPIOC_MODER &= ~(0x1 << 21); //!# Enable clock to GPIO Port C
    *GPIOC_MODER |= 0x1 << 20;    //!# Clear bit 21 to put pin 10 into general purpose output mode
    *RCC_AHB1ENR |= 0x1 << 2;     //!# Set bit 20 to put pin 10 into general purpose output mode

    while (1) {
        *GPIOC_ODR |= 0x1 << 10;  //!# Write a 1 to bit 10 (port 10) of GPIO Port C
    }




    /* This section does work */
    RCC->AHB1ENR |= 0x1 << 2;     //!# Enable clock to GPIO Port C
    GPIOC->MODER &= ~(0x1 << 21); //!# Clear bit 21 to put pin 10 into general purpose output mode
    GPIOC->MODER |= 0x1 << 20;    //!# Set bit 20 to put pin 10 into general purpose output mode

    while (1) {
        GPIOC->ODR |= 0x1 << 10;  //!# Write a 1 to bit 10 (port 10) of GPIO Port C
    }
}

Update: So turns out, it is the ORDER of the instructions that is why one "section" was working and one "section" wasn't. The working "section" enabled the clock signal to that GPIO port and then did the memory writes whereas the not-working "section" tried to do the memory writes then enable the clock signal. I'm assuming here, but it seems like that memory region is clock gated or something where trying to read/write from/to the region when the clock to that region is not enabled will result in read-as-zero/write-ignore.

您必须先启用外围设备,然后才能与之交谈。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM