在CMSIS定義爲GCC你可以找到這樣的事情:數據內存屏障(DMB)的CMSIS庫的Cortex-M3S
static __INLINE void __DMB(void) { __ASM volatile ("dmb"); }
我的問題是:內存屏障有什麼用,如果它沒有在clobber列表中聲明「內存」?
這是core_cm3.h中的錯誤,還是有一個原因,爲什麼gcc應該沒有任何額外的幫助正確行爲?
在CMSIS定義爲GCC你可以找到這樣的事情:數據內存屏障(DMB)的CMSIS庫的Cortex-M3S
static __INLINE void __DMB(void) { __ASM volatile ("dmb"); }
我的問題是:內存屏障有什麼用,如果它沒有在clobber列表中聲明「內存」?
這是core_cm3.h中的錯誤,還是有一個原因,爲什麼gcc應該沒有任何額外的幫助正確行爲?
我用gcc 4.5.2(用LTO構建)做了一些測試。如果我編譯此代碼:
static inline void __DMB(void) { asm volatile ("dmb"); }
static inline void __DMB2(void) { asm volatile ("dmb" ::: "memory"); }
char x;
char test1 (void)
{
x = 15;
return x;
}
char test2 (void)
{
x = 15;
__DMB();
return x;
}
char test3 (void)
{
x = 15;
__DMB2();
return x;
}
使用arm-none-eabi-gcc -Os -mcpu=cortex-m3 -mthumb -c dmb.c
,然後從arm-none-eabi-objdump -d dmb.o
我得到這個:
00000000 <test1>:
0: 4b01 ldr r3, [pc, #4] ; (8 <test1+0x8>)
2: 200f movs r0, #15
4: 7018 strb r0, [r3, #0]
6: 4770 bx lr
8: 00000000 .word 0x00000000
0000000c <test2>:
c: 4b02 ldr r3, [pc, #8] ; (18 <test2+0xc>)
e: 200f movs r0, #15
10: 7018 strb r0, [r3, #0]
12: f3bf 8f5f dmb sy
16: 4770 bx lr
18: 00000000 .word 0x00000000
0000001c <test3>:
1c: 4b03 ldr r3, [pc, #12] ; (2c <test3+0x10>)
1e: 220f movs r2, #15
20: 701a strb r2, [r3, #0]
22: f3bf 8f5f dmb sy
26: 7818 ldrb r0, [r3, #0]
28: 4770 bx lr
2a: bf00 nop
2c: 00000000 .word 0x00000000
顯而易見的是,__DBM()
只插入dmb
指令,它需要DMB2()
實際強制編譯器刷新緩存在寄存器中的值。
我想我發現了一個CMSIS錯誤。
恕我直言,CMSIS版本是正確的。
注射沒有撞列表中的內存屏障指令實現它到底是什麼應該做的:
如果「X」變量前面寫了緩衝則承諾。例如,如果您要將「x」地址傳遞爲DMA地址,或者您要設置MPU,這非常有用。
它對返回「x」沒有影響(即使您省略了內存障礙,您的程序也保證是正確的)。
另一方面,通過在clobber列表中插入內存,您在以前的示例(DMA,MPU ..)等情況下沒有任何效果。
後一種情況唯一的區別是,如果你有例如一個ISR在「strb」之後修改「x」的值,那麼返回的值就是由ISR修改的值,因爲clobber導致編譯器從內存中讀取以再次註冊。 但是,如果你想獲得這個東西,那麼你應該使用「易變」的變量。
換句話說:爲了保證與其他可能訪問RAM存儲器的硬件資源的一致性,屏障強制高速緩衝存儲器與存儲器提交相同,而斷開存儲器會導致編譯器停止,假定存儲器沒有改變並在本地寄存器中再次讀取,這是另一種具有不同目的的內容(無論內存更改是否仍在高速緩存中或已在RAM上提交都沒有關係,因爲最終的加載操作在兩種情況下均可保證無障礙地工作)。
但編譯器是否可以自由地對周圍的指令進行重新排序,以便在執行屏障時寫入「x」根本不會觸發緩存?我想要內存clobber,以便編譯器被迫提交變量(可能緩存)內存,然後強制高速緩存刷新。 – jpc
好問題。請注意,Linux使用'memory' clobber:http://lxr.free-electrons.com/source/arch/arm/include/asm/system.h?v=2.6.39#L135 – ninjalj
@ninjalj:感謝鏈接。 (沒有出現在Google上) – jpc