2012年1月9日 星期一

[Embedded] ARM Coretex M3 程式寫作注意事項


最近需要在 ARM Cortex M3 上開發一個安全監控系統,茲將程式寫作時需要注意的事項整理如下:

l  區域變數(Local Variable)
Ø   若使用較大的變數定義(long),會使用運算較慢的指令集,造成整體效能較慢,但不會增加çode size
Ø   但使用較小的變數定義(),則需要多餘的指令作變數轉換,會增加code size
Ø   編譯器有個最佳化選項 ”all-in-register locals”,會將local變數放在register(Cortex M3共有13 32-bit general-purpose registers),當暫存器用完的時候,local變數才會放入到stack中。如此可以加速存取local 變數的時間。
建議:使用 int, unsigned int, long,而不要使用 short


l  全域變數(Global Variable)
編譯器假設每次函數切換時,全域變數都可能會被更改,需要重新載入。
建議:盡可能使用 local variable或使用 static variable (less reloading)取代。
若需要全域變數,則可以在函數一開始,宣告一個local variable,將全域變數的值代入,以加速運行速度。
作法舉例如下:
Int x=1;
Func()
{
Int lx=x;
 x=x+1;
 x=lx;
}

l  全域常數(Global Constant)
針對不同的編譯器,對於全域常數的處理方式各不相同。例如:在SRAM配置全域常數空間,但是將初始值留在Flash中,如此則會佔據兩倍空間。並且當系統要存取此值時,需要載入記憶體,而不是簡單的執行 move 指令。
建議:使用 local constant或是enum來定義常數。

l  浮點數
因為Cortex-M3並沒有支援硬體的浮點運算器,所以盡量不要使用浮點數。若要使用,則需要使用軟體的浮點運算,根據所使用的演算法不同,效能可以差異十倍以上。最好是確認有哪些最佳化的演算法可用。

l  函數
Ø   函數所帶的參數個數
最多只用四個參數,否則會造成效能降低。Because the first four arguments are passed in registers, and the remaining arguments are passed on the stack.
Ø   遞迴 recursion
若要使用遞迴,則將遞迴函數宣告為static

l  針對周邊裝置處理,需要特別注意
Ø   變數宣告可能要使用 volatile
Ø   Back-to-back stores
Ø   與周邊裝置溝通存取變數時,最好將需要存取變數的動作分開作,以STR指令為例。
Ø   較慢的方法
MyPeriph_reg0 = x;
MyPeriph_reg1 = y;
MyPeriph_reg2 = z;
Ø   較快的方法(因為STR可以在background完成)
MyPeriph_reg0 = x;
y = some computation
MyPeriph_reg1 = y;
z = some computation
MyPeriph_reg2 = z;

l  Volatile的用法說明
由於編譯器優化的關係,若某個變數i存在於暫存器中, 存取時,CPU便可能會直接從暫存器中取值,而不會去找尋記憶體中對應的值 (因為訪問register比訪問ram)
若應用程式所定義的變數,會被編譯器未知的因素更改(例如存取周邊裝置的值),那麼就需要CPU每次都到記憶體中取值,以避免取出的值不正確,如此則需要在變數宣告之前加上volatile,避免編譯器針對此變數優化。
宣告範例:
volatile int x; // x is in volatile memory
volatile int *p; // p points to volatile memory
int   * volatile vp; // vp is a volatile pointer to non-volatile memory
volatile int* const cpv = &mem; // cpv is a const pointer to volatile memory


l 最佳化 (-O0, -O1, -O2, -O3)
    當程式運行無誤之後,可以在編譯時加上最佳化選項使得執行速度較快,程式碼較小。但若仍然在除錯階段,則要小心使用最佳化選項。此選項會使的程式碼執行步驟與程式設計師所預想的稍有不同。

l  開發ARM時可以選用各種編譯器,官方網站上建議有三種工具
Ø   ARM® RVDS  (ARM Workbench)
Ø   ARM/Keil RealView MDK tools (μVision IDE)
Ø   DS-5 (Eclipse IDE)

我現在拿到的產品附的工具是Keil,後續開發時遇到的問題,會陸續整理在此部落格中。