星期三, 7月 22, 2009

GCC Inline Assembler for ARM

某些時候,即便我們寫的是 C,但是可能會需要直接去透過 assembly 去對硬體(SoC)做一些控制,而這樣混合 C 及 assembly 的寫法其實是比較直觀,更容易懂的。例如整個函式主要是用 C 實作,方便我們可以了解程式實作的邏輯,但是在 critical 或是 C 沒有支援的部份,像關閉 IRQ 或 FIQ 則是透過 assembly 完成。

以下是我在 ucosii 裡實作 critical section 保護方式,這個方式在進入 critical section 前,將 CPSR 的值存到變數 cpu_sr 裡,同時 disable IRQ 及 FIQ,而當離開 critical section 後,則將存放在 cpu_sr 的原 CPSR 值存回 CPSR裡,這是比較複雜的 inline assembly,因為我們會利用到 C 函式裡宣告的變數 cpu_sr,記住底下是一個 #define,在許多 usosii 的 C function 裡都會被使用到
#define OS_ENTER_CRITICAL()            \
/* \
* Disable both IRQ and FIQ \
*/ \
__asm__ __volatile__( \
"mrs %0, cpsr\n\t" \
"orr r8, %1, #0xC0\n\t" \
"msr cpsr_c, r8\n\t" \
: "=r" (cpu_sr) \
: "r" (cpu_sr) \
: "memory");

#define OS_EXIT_CRITICAL() \
/* \
* Restore the cpsr(IRQ and FIQ) \
*/ \
__asm__ __volatile__( \
"msr cpsr_c, %0\n\t" \
: \
: "r" (cpu_sr) \
: "memory");

分成四個部份,分別是 arm assembly instruction、output operand list、input operand list 及 clobber list,後面若不需要的話,就留空即可

所有的 assemble instructions 都放在這裡,有些很單純就跟一般的 arm instruction 沒兩樣,有些則是會稍有變化,因為利用到 C 的變數,如果宣告了變數,但在 inline assembly 中需要去存取它們,例如 line 2 及 line 3,此時,就需要 output operand 及 input operand 的搭配使用
"mov   r0, r0\n\t"
"mrs %0, cpsr\n\t"
"orr r8, %0, #0xC0\n\t"
"msr cpsr_c, r8\n\t"
output operand list
: "=r" (cpu_sr)
input operand list
: "r" (cpu_sr)
你可以把想對 compiler 說的話放在 clobber list 裡,例如 "memory" 是告訴 compiler 記憶體裡的資料是可能被改變的,所以不要去做最佳化,每次要存取該記憶體內容時,都要重新讀取到 register 裡,在 embedded 的世界裡,這是很重要的,也許在某個 ISR 裡某個變數被改變了,如果你直接讀取上次存在 register 的值而不是重新讀取到 register 裡,那,事實上,在 C 裡宣告變數時,可以使用 volatile 去做修飾,都是為了相同的目的。
: "memory");
[Download]
[ARM GCC Inline Assembler Paper]

星期一, 7月 13, 2009

第三個上班日

新的公司,還不知道能不能度過三個月的試用期,就一切隨緣囉,沒有所求,就沒有煩惱。

跟旁邊的電塔相比,好大的彩虹,就出現在雨後離公司好遠的山頭上,來去尋找彩虹吧!





偏偏現在的我還有所求,所以萬一我沒撐過,好心的親朋好友大爺們,請收留我吧 ;)