控制C中存储器映射寄存器的读写访问宽度

srk*_*ing 6 c embedded compiler-optimization memory-mapping

我正在使用基于x86的内核来操作32位内存映射寄存器.仅当CPU对该寄存器产生32位宽的读写操作时,我的硬件才能正常工作.寄存器在32位地址上对齐,并且不能以字节粒度进行寻址.

我该怎么做才能保证我的C(或C99)编译器在所有情况下都只能生成完整的32位宽读写?

例如,如果我执行这样的读 - 修改 - 写操作:

volatile uint32_t* p_reg = 0xCAFE0000;
*p_reg |= 0x01;
Run Code Online (Sandbox Code Playgroud)

我不希望编译器明智地知道只有底部字节发生变化并产生8位宽的读/写.由于机器代码在x86上的8位操作通常更密集,我害怕不必要的优化.一般情况下禁用优化不是一种选择.

-----编辑-------
一篇有趣且非常相关的论文:http://www.cs.utah.edu/~regehr/papers/emsoft08-preprint.pdf

Mic*_*urr 6

您的疑虑由volatile限定符涵盖.

6.7.3/6"类型限定词"说:

具有volatile限定类型的对象可能以实现未知的方式进行修改,或者具有其他未知的副作用.因此,任何涉及这种对象的表达都应严格按照抽象机的规则进行评估,如5.1.2.3所述.此外,在每个序列点,最后存储在对象中的值应与抽象机器规定的值一致,除非由前面提到的未知因素修改.什么构成对具有volatile限定类型的对象的访问是实现定义的.

5.1.2.3"程序执行"(除其他外)说:

在抽象机器中,所有表达式都按语义指定进行计算.

接下来是一个通常称为"as-if"规则的句子,如果最终结果相同,则允许实现不遵循抽象机器语义:

实际实现不需要评估表达式的一部分,如果它可以推断出它的值未被使用并且不产生所需的副作用(包括由调用函数或访问易失性对象引起的任何副作用).

但是,6.7.3/6基本上表示表达式中使用的volatile限定类型不能应用"as-if"规则 - 必须遵循实际的抽象机器语义.因此,如果取消引用指向易失性32位类型的指针,则必须读取或写入完整的32位值(取决于操作).