可以/应该通过单个指针访问多个设备寄存器吗?

时间:2017-02-17 20:02:49

标签: c pointers embedded stm32

我目前正在用C语言编写STM32F446RE(ARM编译器),因为我想获得嵌入式编程的经验,所以我没有使用任何库。对于我的初始化,我想知道通过将一个指针从外设基址的偏移量递增一个指针来访问寄存器是否是个好主意。

    void I2C_Init(void)
    {
        volatile uint32_t *reg_ptr = (uint32_t *) GPIOB_LOC;
        *(reg_ptr + GPIOB_MODE_OFFSET) &= ~((0xFU<<16) | (0xFU<<20));   //clear before updating
        *(reg_ptr + GPIOB_MODE_OFFSET) |= ((0xAU<<16) | (0xAU<<20));        //set pins 8, 9, 10, 11 to alt func
        *(reg_ptr + GPIOB_OTYPE_OFFSET) &= ~(0xFU<<8);  //no types
        *(reg_ptr + GPIOB_OSPEED_OFFSET) &= ~((0xFU<<16) | (0xFU<<20)); //clear before updating
        *(reg_ptr + GPIOB_OSPEED_OFFSET) |= ((0x5U<<16) | (0x5U<<20));      //set to normal speed (will get overriden by alt func)
        *(reg_ptr + GPIOB_PUPD_OFFSET) &= ~((0xFU<<16) | (0xFU<<20));       //no pull up or pull down
        *(reg_ptr + GPIOB_AFH_OFFSET) &= ~0xFFFFU;  //clear before updating
        *(reg_ptr + GPIOB_AFH_OFFSET) |= 0x4444U;       //set pins 8, 9, 10, 11 to alt func 4 (i2c1 & i2c2 SCL and SDA respectively)
    }

在我的标题文件中:

    #define GPIOB_LOC       0x40020400UL    //base
    #define GPIOB_MODE_OFFSET (0x00)
    #define GPIOB_OTYPE_OFFSET (0x04)
    #define GPIOB_OSPEED_OFFSET (0x08)
    #define GPIOB_PUPD_OFFSET (0x0C)
    #define GPIOB_AFH_OFFSET (0x24)

这种做法不安全吗?有没有更好的,更普遍接受的访问多个设备寄存器的方法,而没有为每个特定寄存器创建指针的开销?

谢谢你们!这是我的第一篇文章,所以如果有任何我可以采取的措施来改进我的问题或任何更有用的信息,请告诉我。

1 个答案:

答案 0 :(得分:1)

如果偏移量是基于 byte 的,那么它的不是安全的。

0x04添加uint32_t *reg_ptr之类的内容会导致生成的地址引用的偏移值大于uint32_t中的reg_ptr个值0x04 1}} - 不是四个字节更大。

例如,将uint32_t *添加到0x40020400UL指针值0x40020410UL将导致实际指针值0x40020404UL NOT 预期{ {1}}。