在MOTOROLAA68K系列MCU上移植μC/OS-II
問題出現在使用OSSemPend()函數時,一旦調用這個函數,CPU就會出現地址錯誤而進入異常處理,內核被終止。這個問題相當奇怪,因為,OSSemPend()函數完全是一個C語言寫成的子函數,函數本身不應出現地址錯誤。通過閱讀編譯器編譯出來的目標碼發現了問題。EmPend()函數,發現這個函數沒有任何局部變量。在進入OSSemPend()函數時,編譯器不需要產生LINK指令來提供局部變量空間。所有的參數都是使用帶偏移量的地址寄存器間接尋址方式直接從堆棧中取得,而且使用的地址寄存器就是A7寄存器。問題可能就在這里,OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()對堆棧的操作都會調整A7寄存器,這就會導致下面的語句在利用A7作寄存器間接尋址時發生錯亂,出現地址錯誤。
這需要詳細研究編譯器的特性。我們使用的HIWARE的編譯器實際上已經考慮到了這一點,當調用OS_ENTER_CRITICAL()或OS_EXIT_CRITICAL()函數更加了A7寄存器后,使用A7的地址寄存器間接尋址也會做出相應的調整,保證仍然能夠得到函數調用時傳遞的變量。每出現一個OS_ENTER_CRITICAL(),接下來的A7寄存器間接尋址的偏移量就會加2;每出現一個OS_EXIT_CRITICAL(),接下來的A7寄存器間接尋址的偏移量就會減2。但是問題卻依然存在,對OSSemPend()的調用會導致地址錯誤,這應該是一個更深層次的錯誤。
這個問題的解決方法是:定義一個局部變量,迫使編譯器生成LINK指令,構造內部參數尋址指針A6,這樣調用OS_ENTER_CRITICAL()或OS_EXIT_CRITICAL()時,更動的只是A7,而對參數尋址用的是A6,不受影響。
如果強迫編譯器在調用函數時都加上LINK和UNLINK指令也可以解決這個問題,但是又會面臨最先提到的編譯器的優化選項問題??梢钥闯?,編譯器的特性對移植μC/OS-II是非常重要的,并且往往這些特性是相互制約的。
在移植和運行μC/OS-II的過程中,也許還會有新的問題出現,遇到問題時只要仔細分析,分析堆棧的使用、中斷的影響,分析編譯生成的代碼,就可以實現μC/OS-II的穩定可靠運行。
評論