uCOS-II是一種十分優秀實時操作系統,其在NASA的認證通過直接說明了其優秀及穩健的性能,同時由於其完全open,所以受到廣大開源愛好者的喜愛。uCOS-II簡單明瞭,同時絕大部分代碼都採用ANSI C編寫(除了與CPU相關代碼外),所以學習起來十分容易,是嵌入式學習乃至操作系統學習最好的入門OS之一。
我主要想講一下自己最近移植uCOS-II的心得,因爲最近也在學習操作系統,所以這段日子對於uCOS-II的學習的確也讓我對於操作系統有了一個實際深刻的認識。
uCOS-II移植其實十分簡單。對於一個處理器,需要做的工作只有:修改三個文件――os_cpu_c.c、os_cpu.h、os_cpu_a.asm(ASM文件根據編譯器不同而又有一些不同)。
用另一種方式說,需要做的工作就是修改五個函數:
1、os_cpu_c.c:OSTaskStkInit;
2、os_cpu_a.asm:OSStartHighRdy、OSCtxSw、OSIntCtxSw、OSTickISR;
OSTaskStkInit函數是針對CPU壓棧的函數,需要模仿出CPU初始化後的寄存器狀況。也使需要修改的唯一一個C語言函數。其他的都是彙編函數。
如果我們可以從uCOS-II官方網站上找到相同CPU或是相似的同一家族的CPU移植代碼,那麼我們的移植工作將會簡單得多。因爲至少我們可以只用瞭解這個處理器的內部結構,而不用細緻的瞭解其彙編指令等很多繁瑣而沒有意義的事情(有的處理器你可能一輩子不再用它,瞭解得太細緻只是在浪費時間)。
譬如,此次我要做的是將uCOS-II移植到瑞薩M16C/62A上,而官方網站上只有其62P的移植代碼,於是乎我就將二者的datasheet在CPU的寄存器、中斷部分仔細比對,發現二者區別很小。最大的區別恐怕就在CPU內部寄存器中的INTBL和PC寄存器二者順序相反吧,這隻要在相關部分注意就可以了,所以很容易就搞定了CPU相關代碼部分。
總結一下移植中浪費我時間的幾個小錯誤吧,這完全是個人粗心導致的失誤:
1、在os_cpu.h文件中需要用宏定義將OS_TASK_SW指向OSCtxSw函數,而我開始像以前一樣直接將OSCtxSw函數與0號軟終端鏈接起來,結果發現函數調用不成功。後來直接用宏定義將OS_TASK_SW define爲OSCtxSw函數,初步調試通過,即驗證OSCtxSw函數正確,但是到後來調用任務的時候卻發現任務切換不正常,不得不重新將函數與中斷結合起來,當然就不能還是0號中斷了,而是改爲一個比較保險的軟終端,這個問題糾結了很長時間。
2、在看書的時候不仔細直接導致我犯了一個大錯誤。起初以爲task只要是能夠達到功能的死循環即可。所以每個task函數都是while(1)或者for(;;;),但是我沒有注意到一點就是每個task裏面都應該有OSTimeDly()函數,否則將導致任務之間不能跳轉。所以最初的實驗現象是永遠只有一個任務在運行,但是任務不能切換……
3、未注意到版本之間的區別。我們知道在新版本的uCOS-II中,添加了一個文件os_tmr.c,主要是在timer上面做了很大的調整,但是我沒有注意到這一點,仍舊按照老版本的方法調試,導致函數調用讓我完全不知所措。最後注意到os的源代碼的不同,仔細閱讀源代碼之後知道了其用法,其實如果不需要timer太強大的功能,只要在os_cfg.h文件中將OS_TMR_EN設置爲0即可。這在習慣老版本調試方法的同學而言是很好的方法。
typedef unsigned char INT8U; /* 無符號8位整型變量 */
typedef signed char INT8S; /* 有符號8位整型變量 */
typedef unsigned short INT16U; /* 無符號16位整型變量 */
typedef signed short INT16S; /* 有符號16位整型變量 */
typedef unsigned int INT32U; /* 無符號32位整型變量 */
typedef signed int INT32S; /* 有符號32位整型變量 */
typedef float FP32; /* 單精度浮點數(32位長度) */
typedef double FP64; /* 雙精度浮點數(64位長度) */