實(shí)時(shí)多任務(wù)系統µC/OS-Ⅱ在DSP上的移植
0. 引言
μC/OS-Ⅱ內核是一個(gè)強占式優(yōu)先級調度的系統,能管理63個(gè)任務(wù),支持旗語(yǔ)、信號量、互斥信號量、隊列和消息郵箱,是一個(gè)是典型的嵌入式實(shí)時(shí)操作系統。它最早由Jean J. Labrosse創(chuàng )作,源碼完全公開(kāi),已有眾多應用范例,可靠性能得到保證,內核小,移植性好。TI的C2000系列DSP處理器 TMS320LF2407A片內集成16路10位AD,4個(gè)通用定時(shí)器,8個(gè)16位PWM通道,4個(gè)CAP捕獲單元,41路I/O通道,以及SPI、 RS232、CAN等通信接口,豐富的片內資源,使得控制器不需任何擴展就能滿(mǎn)足所有的功能要求,且冗余很少。
DSP處理器在數學(xué)運算方面的優(yōu)勢也為智能化過(guò)程所需的數據處理提供了支持。TMS320LF2407A指令采用4級流水線(xiàn)操作,最高能以40M的系統時(shí)鐘工作,再加上合適的RTOS的調度,完全能保證系統的實(shí)時(shí)性。其開(kāi)發(fā)系統TMS320C2XX Code Composer Studio滿(mǎn)足μC/OS-Ⅱ的移植條件,因此,它是嵌入式計算機控制系統主控制芯片的一個(gè)較好選擇。筆者在設計基于CAN的工程機械嵌入式智能顯示儀時(shí),選用2407A做主控制芯片,軟件方面,將實(shí)時(shí)內核μC/OS-Ⅱ移植到該DSP 控制器TMS320LF2407A上,而應用程序是在μC/OS-Ⅱ內核基礎上的一系列任務(wù)。
1. μC/OS-Ⅱ的移植
由于μC/OS-Ⅱ在設計時(shí)就已經(jīng)充分考慮了可移植性,所以μC/OS-Ⅱ的移植相對來(lái)說(shuō)比較容易。移植工作包括以下幾個(gè)內容:(1)用#define設置一個(gè)常量的值(OS_CPU.H)(2)聲明10個(gè)數據類(lèi)型(OS_CPU.H)(3)用#define聲明三個(gè)宏 (OS_CPU.H)(4)用C語(yǔ)言編寫(xiě)六個(gè)簡(jiǎn)單的函數(OS_CPU_C.C)(5)編寫(xiě)四個(gè)匯編語(yǔ)言函數(OS_CPU_A.ASM);即μC/OS-Ⅱ的移植要修改3個(gè)文件OS_CPU.H、OS_CPU_C.C和OS_CPU_A.ASM。其中匯編語(yǔ)言文件OS_CPU_A.ASM是可選擇的,因為某些C編譯器允許用戶(hù)在C語(yǔ)言中插入匯編語(yǔ)言,所以用戶(hù)可以將所需的匯編語(yǔ)言代碼直接放到OS_CPU_C.C中。CCS的C編譯器允許在 C語(yǔ)言中嵌入匯編語(yǔ)言,但是由于這種方式破壞了C語(yǔ)言的完整性,因此只提倡在程序開(kāi)始系統初始化部分少量采用。而在C語(yǔ)言中嵌入實(shí)現某一完整功能的多句匯編語(yǔ)言時(shí),就不提倡采用這種方法。所以,移植中還是對OS_CPU_A.ASM做了修改。
2. 編寫(xiě)移植代碼
移植μC/OS-Ⅱ的主要工作是聲明與硬件相關(guān)的數據類(lèi)型,定義與中斷有關(guān)的宏定義,定義堆棧增長(cháng)方向宏定義,編寫(xiě)堆棧初始化函數,HOOK接口函數,任務(wù)級上下文切換函數,中斷級上下文切換函數以及系統時(shí)鐘定時(shí)服務(wù)函數等。
2.1 移植OS_CPU.H文件
(1)一個(gè)常量值。OSInit需要知道當OS_TaskIdle() 和OS_TaskStat( ) 函數建立任務(wù)時(shí),堆棧的頂端地址在哪里;其次調用OSTaskStkChk( )時(shí),μC/OS-Ⅱ需要知道堆棧的底端地址在哪里。所以需要指明堆棧的增長(cháng)方向。絕大多數微處理器和微控制器的堆棧是從上往下遞減的,但是也有某些處理器使用的是相反的方式。TMS320LF2407A的堆棧方向是從下往上增長(cháng)的,所以: #define OS_STK_GROWTH 0;// 堆棧方向是從下往上增長(cháng)
(2) 聲明數據類(lèi)型。μC/OS-Ⅱ考慮到通用性,在內核中使用了自定義數據類(lèi)型,與編譯器無(wú)關(guān),這就要求移植時(shí)必須定義微處理器的數據類(lèi)型與μC/OS-Ⅱ的數據類(lèi)型相一致,保證移植后的μC/OS-Ⅱ在微處理器平臺上運行,在移植中應將其聲明為CCS編譯器可識別的類(lèi)型。這可以由OS_CPU.h頭文件實(shí)現,程序如下所示。
typedef unsigned char BOOLEAN;/*定義ucos里的boolean為unsigned char*/
typedef unsigned char INT8U; /*定義ucos里的INT8U為unsigned char*/
typedef signed char INT8S; /*定義ucos里的INT8S為signed char*/
typedef unsigned int INT16U; /*定義ucos里的INT16U為unsigned int*/
typedef signed int INT16S; /*定義ucos里的INT16S為signed int*/
typedef unsigned long INT32U; /*定義ucos里的INT32U為unsigned long*/
typedef signed long INT32S; /*定義ucos里的INT32S為signed long */
typedef float FP; /*定義ucos里的FP為float*/
#define OS_STK INT16U /*堆棧入口寬度為16位*/
由于系統沒(méi)有用到OS_CPU_SR類(lèi)型數據,所以沒(méi)有定義此數據類(lèi)型。
(3)3個(gè)宏定義。μC/OS-Ⅱ在內核中通過(guò)禁止中斷來(lái)保護臨界區,因此,需要在C語(yǔ)言中插入禁止和允許中斷的匯編代碼,DSP里用SETC INTM來(lái)屏蔽中斷,用CLRC INTM來(lái)使能中斷。所以移植代碼定義了下面兩條宏定義:
#define OS_ENTER_CRITICAL() asm(" SETC INTM")
#define OS_EXIT_CRITICAL() asm(" CLRC INTM")
μC/OS-Ⅱ定義了三種保護臨界區的方式,此移植版本采用的是最簡(jiǎn)單的第一種方法。此種方法就要求中斷關(guān)閉的情況下不能調用μC/OS-Ⅱ的功能函數。這對于應用來(lái)說(shuō)是可以接受的,所以就選擇了此種模式。TMS320LF2407A支持多種中斷方式,包括可屏蔽硬中斷INT1~INT6,不可屏蔽硬中斷RESET和NMI_VECT,不可屏蔽軟中斷INT8~INT16和INT20~INT31以及中斷陷阱TRAP。因此使用INT31軟中斷來(lái)調用OSCtxSw()來(lái)從任務(wù)堆棧中恢復處理器所用的寄存器。用INT2的定時(shí)器1周期中斷來(lái)調用OSTickISR()。定義模仿INT31中斷的宏,來(lái)跳轉到INT31
#define OS_TASK_SW() asm(" INTR 31")
在中斷向量表里的定義
.include f2407regs.h
.global _c_int0, _OSTickISR, RESET, _OSCtxSw,_GRIS5,_adint,_nothing
.asect "vectors",0
……
INT2 B _OSTickISR ; B _c_int2
……
INT31 B _OSCtxSw ; task switching service vector.
linux操作系統文章專(zhuān)題:linux操作系統詳解(linux不再難懂)
評論