代码之家  ›  专栏  ›  技术社区  ›  Sam Hammamy

将包含多个成员的结构强制转换为内存地址

  •  0
  • Sam Hammamy  · 技术社区  · 6 年前

    我正在通过一些微控制器代码阅读(自学习),并想验证我是否正确理解了这一点。

    #define PERIPH_BASE           ((u32)0x40000000)
    #define AHBPERIPH_BASE        (PERIPH_BASE + 0x20000)
    #define RCC_BASE              (AHBPERIPH_BASE + 0x1000)
    
    /*------------------------ Reset and Clock Control ---------------------------*/
    typedef struct
    {
      vu32 CR;
      vu32 CFGR;
      vu32 CIR;
      vu32 APB2RSTR;
      vu32 APB1RSTR;
      vu32 AHBENR;
      vu32 APB2ENR;
      vu32 APB1ENR;
      vu32 BDCR;
      vu32 CSR;
    } RCC_TypeDef;
    
    #define RCC                 ((RCC_TypeDef *) RCC_BASE)
    

    上面的第3行是分配地址 0x40000000 + 0x20000 + 0x1000 to RCC_BASE .

    那就是芯片设计者定义的地址,我可以在这里找到 datasheet 它告诉CPU在哪里可以找到为休息和控制时钟设置的寄存器的开始。

    显然 u32 vu32 是典型的, VU32 成为 volatile 告诉编译器不要对其进行任何优化。我拉了它,它是:

    typedef volatile unsigned long  vu32;
    

    那么最后一行设置变量 RCC RCC_BASE 从而分配其第一个成员 CR 价值 碾压混凝土基层 ,因此 CFGR 变成 RCC_BASE + 0x04 ( 4 bytes i.e 32 bits) CIR = RCC_BASE + 0x08 (64 bits) . 这是因为 不稳定的 .

    这些都是准确的吗?有点准确吗?完全错误?

    1 回复  |  直到 6 年前
        1
  •  4
  •   andy mango    6 年前

    代码段看起来非常ARMISH和CMSISISH,所以我将在这些方面尽我所能。

    这些类型的声明在定义内存映射的外围寄存器时很常见。最后一行定义 RCC 不是变量声明。它是预处理器宏定义。其目的是让您拥有如下陈述:

    vu32 cr = RCC->CR ;
    

    在您的代码中,它为您提供 CR 在中注册 碾压混凝土 外围设备转换成一个局部变量,我用类似的方法命名。编译器计算到 构造成员并生成从该地址的内存中获取值所需的指令。显然,编译器不知道地址中驻留了什么。由于它是由前置处理器宏扩展的,意味着直接的文本替换,最终您将有一个硬物理地址转换来指向一个特定的硬件外围寄存器布局,您将其“巧妙地”排列成一个“C”结构。波动性与此没有太多关系,除了编译器不会假设仅仅因为它不对结构成员执行没有更改的写入操作,也就是说,值可以在不执行写入操作的情况下更改。