我在AVR32上有一个中断服务路由。我需要从中断状态寄存器中读取以取消中断。但是,我不会使用阅读结果。我宁愿不使用asm指令,但我担心gcc会将读取优化为虚拟变量。什么是正确的方法?
目前我有:
uint32_t tmp = *(volatile uint32_t *)INTERRUPT_STATUS_REG_ADDRESS;
tmp也应该波动吗?我担心如果不使用tmp,gcc会跳过读取。
答案 0 :(得分:6)
通过指针转换到(volatile uint32_t *)读取中断状态寄存器告诉编译器读取此表达式(指定地址的变量)会产生副作用,因此它总是需要计算此表达式。
由于您的tmp变量不易变,编译器可以自由优化将寄存器的值存储到变量。
我认为C标准(see here)的第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寄存器;