是只需要一次挥发还是从MMIO mmap'd地址指针派生的每个指针上都需要volatile?

问题描述

我有一个指向存储空间void *pAddr的全局基址指针。在某些方法中,我将该指针转换为很少的结构,以具有更好的访问内存的方法

class MyClass {

  private:

    struct MapMem {
      uint8_t dummy1;
      uint64_t dummy12;
    };
    void* pAddr;
    MapMem* representationPointer;
    void myMethod();
}

voidmyMethod() {
   representationPointer = static_cast<volatile MapMem*>(pAddr);
   /* Doing something with representationPointer */
}

由于pAddr是对我的驱动程序执行IO内存映射的mmap()调用的结果。

因为我只需要按8/16/32/64位访问寄存器,所以我需要使用volatile。 我需要避免使用pAddr或指向该地址的所有其他指针对所有内存访问进行优化。

  • 我应该在哪里设置volatile关键字?

在所有指向pAddr或仅指向pAddr的结构/数据类型上?

解决方法

volatile告诉编译器,而不是所生成的代码可能已更新了指向内容的其他内容。这就是为什么每当某些HW寄存器上指针的地址点(其内容可能由HW更新而不依赖于代码执行)时都需要volatile的原因。

volatile struct MapMem *representationPointer = static_cast<struct MapMem *>(pAddr);

应该足够了。

,

由于您的mmap地址指向MMIO,因此应将其存储在指向volatile的指针中。即

volatile void* pAddr;

然后,当您需要将此地址解释为指向MapMem的指针时,应进行适当的强制转换。如果您尝试执行static_cast<MapMem*>(pAddr),则会出现编译错误:例如GCC会告诉您,演员阵容会丢掉预选赛。正确的是:您的结构仍然是MMIO空间中的结构,因此它应该是易变的。因此您的演员表应该像

auto representationPointer = static_cast<volatile MapMem*>(pAddr);

现在,您可以使用representationPointer作为HW寄存器来处理结构字段了。