我在 AVR32 上有一个中断服务路由。我需要从中断状态寄存器中读取以取消中断。但是我不使用读取的结果。我宁愿不使用 asm 指令,但我担心 gcc 会优化对虚拟变量的读取。什么是正确的方法?
目前我有:
uint32_t tmp = *(volatile uint32_t *)INTERRUPT_STATUS_REG_ADDRESS;
tmp 也应该是易变的吗?我担心如果不使用 tmp,gcc 会跳过读取。
通过转换为 (volatile uint32_t*) 的指针读取中断状态寄存器告诉编译器读取此表达式(指定地址的变量)会产生副作用,因此它始终需要评估此表达式。
由于您的 tmp 变量不是易失性的,编译器可以自由优化将寄存器的值存储到变量中。
我认为 C 标准的第 5.1.2.3 章(见这里)足够相关。
此外,第 6.7.3 章解释了:
具有 volatile 限定类型的对象可能会以实现未知的方式被修改或具有其他未知的副作用。因此,任何引用此类对象的表达式都应严格按照抽象机的规则进行评估,如 5.1.2.3 中所述。此外,在每个序列点,最后存储在对象中的值应与抽象机规定的值一致,除非由前面提到的未知因素修改。116) 构成对具有 volatile 限定类型的对象的访问是实现定义的。
您实际上可以省略 tmp 并只写:
*(volatile uint32_t *)INTERRUPT_STATUS_REG_ADDRESS;
这将简单地读取位于 INTERRUPT_STATUS_REG_ADDRESS 的 uint32_t 寄存器;