volatile 只需要一次还是在每个从 MMIO mmap 地址指针派生的指针上需要?

Is volatile needed only once or on each derived pointers from a MMIO mmap'd address pointer?

我有一个指向内存的全局基指针 space 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/64bits的寄存器,所以需要用到volatile。 我需要避免使用 pAddr 或指向该地址的所有其他指针对所有内存访问进行优化。

在所有指向 pAddr 或仅指向 pAddr 的 structures/data 类型上?

volatile 告诉编译器除生成的代码之外的其他内容可能已经更新了指向的内容。这就是为什么每当指针的地址指向某些硬件寄存器(其内容可能由硬件独立于代码执行而更新)时需要 volatile 的原因。

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

应该够了。

由于您的 mmapped 地址指向 MMIO,因此它应该存储在 pointer-to-volatile 变量中。即,

volatile void* pAddr;

然后,当您需要将此地址解释为指向 MapMem 的指针时,您应该进行适当的转换。如果你尝试做 static_cast<MapMem*>(pAddr),你会得到编译错误:例如GCC 会告诉你,演员表抛弃了限定词。确实如此:您的结构仍然是 MMIO space 中的结构,因此它应该是易变的。所以你的演员应该看起来像

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

现在您可以使用 representationPointer 将结构字段用作硬件寄存器。