uCOS-II2.86 移植的一點心得

      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即可。這在習慣老版本調試方法的同學而言是很好的方法。

 

UCOS-II的移植需要提供2,3個文件分別介紹如下:
一:OS_CPU.H
1 與編譯器有關的數據類型
   只是按照不同的編譯器編寫對應的數據類型的typedef
   對應於ARM7的數據類型的編寫如下
typedef unsigned char  BOOLEAN;              /* 布爾變量                                 */
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位長度)                 */
 
   在上面定義的各種數據類型中按照ARM7的堆棧寬度選擇INT32U
typedef INT32U         OS_STK;                   /* 堆棧是32位寬度                           */
 
   接下來一部分是爲了兼容低版本UCOS的數據類型所編寫的代碼,在UCOS-II中暫不考慮
 
2 與處理器相關的代碼
    先定義中斷的實現方式,預先設定的中斷方式有三種,在ARM7中設置爲方式2
#define     OS_CRITICAL_METHOD     2            /* 選擇開、關中斷的方式 */
 
    接下來的一段是我暫時還沒有完全搞懂的一部分,只知道是設定了12個軟件中斷的函數,當調用這些函數之前都會執行對應中斷號的事情。。具體的看到後面應該能完全搞懂軟件中斷的實現方式,該段代碼在後面的文件中會有具體的解釋,這裏暫時不看
    定義堆棧的生長方式,ARM7內核支持兩種生長方式,但是ADS的C語言編譯器只支持從上往下的生長方式,因此:
#define OS_STK_GROWTH    1                      /*  堆棧是從上往下長的,0-從下往上的生長方式         */
 
    最後幾行分別定義了用戶模式01和系統模式1f以及IRQ中斷禁止的指令80三個立即數,方便調用。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章