我有一些C宏可以禁用和启用中断,以便我可以定义代码的关键部分。我想确保优化器符合操作,不移动它们或删除它们。
#define ARM_INT_KEY_TYPE unsigned int
#define ARM_INT_LOCK(key_) ({ \
asm("MRS %0,cpsr" : "=r" (key_)); \
asm("MSR cpsr_c,#(0x1F | 0x80 | 0x40)"); \
})
#define ARM_INT_UNLOCK(key_) asm("MSR cpsr_c,%0" : : "r" (key_))
用法如下:
int init_i2c(p_device_i2c dev){
// Interrupts are enabled
doSomething();
ARM_INT_KEY_TYPE key;
ARM_INT_LOCK(key);
// Interrupts are disabled
pMX27_GPIO i2c_clk = (pMX27_GPIO)(GPIO_BASE_ADDR | I2C_CLK_PORT);
pMX27_GPIO i2c_sda = (pMX27_GPIO)(GPIO_BASE_ADDR | I2C_DATA_PORT);
i2c_clk->GIUS &= ~(1 << I2C_CLK_PIN); // I2C Signals
i2c_sda->GIUS &= ~(1 << I2C_DATA_PIN); // I2C Signals
ARM_INT_UNLOCK(key);
// Interrupts ON again
// Wait for stable
ARM_delay_clocks(5000);
i2c_stop(dev);
代码按预期工作,优化已关闭,但我怀疑优化开启时可能存在问题。
在asm语句中添加volatile是否可以解决问题?
#define ARM_INT_UNLOCK(key_) asm volatile ("MSR cpsr_c,%0" : : "r" (key_))
答案 0 :(得分:7)
是的,asm volatile
是编写此宏的正确方法。您可以通过在调试器上单步执行此代码并在程序集级别查看操作顺序来轻松检查行为。或者,您可以直观地检查功能的反汇编输出。
这是关于内联asm的一些有用的gcc文档
http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#ss5.4
答案 1 :(得分:0)
你只需要关键变量的volatile属性。