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

标签 c pointers embedded stm32

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

    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)

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

谢谢大家!这是我的第一篇文章,所以如果我可以做些什么来改进我的问题或有任何更多有用的信息,请告诉我。

最佳答案

如果偏移量是基于字节的,则它安全。

uint32_t *reg_ptr 添加类似 0x04 的内容将导致生成的地址引用比实际值大四个 uint32_t 值的偏移量在 reg_ptr 中 - 不大于四个字节

例如,将 0x04 添加到 uint32_t * 指针值 0x40020400UL 将得到实际的指针值 0x40020410UL > 并且不是预期的0x40020404UL

关于我可以/应该通过单个指针访问多个设备寄存器吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42306438/

相关文章:

c++ - Python ctypes : wraping c++ class with operators

c - 如何编写驱动程序代码?

c++ - 考虑到可能的别名,如何编写函数

c++ - 安装快板 C++

c - 为什么用太长的初始化器初始化的字符串会像这样

c - 嵌入式程序中需要说明一段代码

c - 为什么要执行跳转指令呢?

c++ - 实现 boost 函数指针时出现错误 LNK2005

c++ - 迭代器两个**的含义

assembly - 为 X86 编译时如何防止函数对齐到 16 字节边界?