2012-07-05 85 views
9

我有一些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); 

的代码按预期工作与优化关闭的,但我怀疑有可能是优化问题接通。

将添加挥发性的汇编语句做的伎俩?

#define ARM_INT_UNLOCK(key_) asm volatile ("MSR cpsr_c,%0" : : "r" (key_)) 
+0

_suspect_或_found_? :) – sarnold 2012-07-05 23:22:28

+0

到目前为止只是嫌疑犯。过去我被优化的副作用咬了一口,所以我很小心 – CodePoet 2012-07-05 23:28:38

+2

@sarnold那么“永远工作”和“每个星期二都会使用这个特定的编译器工作在这个特定的代码上”是有区别的,所以需要一些保证行为的文档对于这些事情来说是个好主意。 – Voo 2012-07-06 11:50:28

回答

7

是的,asm volatile是写这个宏的正确方法。您可以通过在调试器上逐步执行此代码并查看组件级别的操作顺序来轻松检查行为。或者,您可以直观地检查功能的反汇编输出。

这里有一个关于内联汇编了一些有用的GCC文档

http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#ss5.4

0

你只需要在关键变量波动属性。