sdcc man閱讀筆記(六)——中斷
阿新 • • 發佈:2019-02-16
一、關鍵字
1.1 interrupt&using
sdcc中,中斷程式使用的關鍵字和keil一樣:
void timer_isr (void) __interrupt (1) __using (1)
{
...
}
interrupt指定中斷號,using指定register bank。
中斷程式可以寫在任意一個原始檔裡,但在包含main程式的原始檔裡,必須要有一份中斷程式的宣告。
如果使用register bank 0,那麼系統會將當前程式用到的暫存器全都儲存進堆疊。如果用到其他register bank,那麼只會儲存類似dptr這樣的特殊暫存器。
1.2 critical
critical用於表示一個程式不能被中斷打算,sdcc會在執行__critical修飾的程式前儲存當前中斷使能狀態,並關閉所有中斷,執行完了之後再開啟。
int foo () __critical
{
...
...
}
同樣對單獨的語句也可以使用
__critical{ i++; }
二、使用中斷時的常見bug
2.1 變數沒有被定義為volatile
這是個常見的錯誤,沒有宣告為volatele的變數,會使編譯器對變數的讀取採取優化。
2.2 非原子指令
有些c語句並非對應一句彙編指令,比如在c51下16位變數讀取,可能需要2到3條指令來執行。如果在執行第一條指令時發生了中斷,很有可能會產生意想不到的後果,而且這種bug很難reproduce。
2.3 堆疊溢位
中斷程式的返回地址和保留的暫存器值全都存在堆疊裡。如果在呼叫中斷程式時,程式正好呼叫了多層的子程式裡最深的一層,很有可能會沒有足夠的堆疊給中斷使用。
2.4 使用了不可重入的函式
如果中斷程式裡對16位/32位的變數進行了乘除、取餘等操作,其實是額外呼叫了一些子函式,要使用–stack-auto將這些都編譯為可重入函式。
另外,如果在中斷程式中呼叫了其他函式(不推薦這麼做),那麼要使用#pragma nooverlay來避免子程式使用可覆蓋的變數。