Posted
by: 邱小新
at 下午2:14
in
SDCC
- 變數沒有宣告成 volatile (variable not declared volatile)
在中斷副程式裏改變一個全域變數,且這個全域變數也會被其它函數使用,則這個全域變數必須宣告成 volatile。
- 非原子型態變數的存取 (non-atomic access)
非原子型態變數即 MCU 需要一個以上的指令去存取變數。當存取非原子型態變數時發生中斷,且在中斷函數中也會去存取此變數,則會發生不可預期的問題,而且很難被複制重現。所以當函數中存取到在中斷函數中用到的非原子型態變數時,需關閉所有中斷。例如:
- 16/32 bit 變數在 8bit MCU 是屬於非原子型態變數。
- 8bit 變數 flags 使用 "flags |= 0x80;" 這個指令,當 flags 位於 xdata 是需要一個以上指令來完成。
- 8bit 變數 counter 使用 "counter += 8;" 這個指令,不管 counter 位於那個記憶體,都需要一個以上指令來完成。
- 堆疊溢位 (stack overflow)
返回位址 (return address) 及在中斷函數會用到的 register 都會被中斷函數先放進堆疊,離開時再從堆疊裏取出恢復。但是當堆疊空間不足時,又發生中斷,就會造成不可預期的問題。這種問題常常發生在遞迴函數的運行。
- 非可再進入函數的使用 (use of non-reentrant functions)
在中斷函數中呼叫其它函數是不建議的,最好避免如此做。因為當執行此函數時,又發生中斷時,中斷函數又去呼叫此函數,造成重復進入的問題。所以如果要在中斷函數中呼叫函數,必須是呼叫可再進入的函數。
- int/long/float 的四則運算使用
當你在中斷函數中使用 int/long 變數的乘法、除法、餘數運算,及 float 變數的四則運算時,需要注意非可再進入函數的使用。因為這些運算都是另外依靠函式庫來提供運算,並非 MCU 所提供的,而預設都是非可再進入函數。如果需要在中斷函數內使用,需要加上 --stack-auto 重新編譯,而且函數庫需要加上 --int-long-reent 及 --float-reent 再重新編譯一次。
張貼留言