如何使用C / gcc从外设IO寄存器读取?

时间:2014-10-20 21:35:28

标签: gcc volatile avr isr

我在AVR32上有一个中断服务路由。我需要从中断状态寄存器中读取以取消中断。但是,我不会使用阅读结果。我宁愿不使用asm指令,但我担心gcc会将读取优化为虚拟变量。什么是正确的方法?

目前我有:

uint32_t tmp = *(volatile uint32_t *)INTERRUPT_STATUS_REG_ADDRESS;

tmp也应该波动吗?我担心如果不使用tmp,gcc会跳过读取。

1 个答案:

答案 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寄存器;