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