摘? 要: 將嵌入式實(shí)時(shí)內(nèi)核μC/OSⅡ移植到TI公司的DSP處理器TMS320C6201上的方法。重點(diǎn)說明了內(nèi)核中與處理器相關(guān)部分的編程及其在系統(tǒng)中的作用。
關(guān)鍵詞: μC/OSⅡ內(nèi)核? 嵌入式操作系統(tǒng)? DSP? 移植
?
嵌入式系統(tǒng)設(shè)計(jì)及其應(yīng)用已對人類生活產(chǎn)生了巨大影響,并使人們未來的生活方式產(chǎn)生變化。進(jìn)行嵌入式系統(tǒng)開發(fā)的一個(gè)基礎(chǔ)工作是實(shí)現(xiàn)嵌入式操作系統(tǒng)在相關(guān)處理器平臺上的移植。本文基于目前應(yīng)用非常廣泛的DSP處理器體系結(jié)構(gòu),對μC/OS-Ⅱ嵌入式實(shí)時(shí)操作系統(tǒng)內(nèi)核的移植做了分析和介紹,并給出了相應(yīng)的移植源代碼。
1 μC/OSⅡ?qū)崟r(shí)內(nèi)核介紹
μC/OS-Ⅱ是一個(gè)簡單、高效的嵌入式實(shí)時(shí)操作系統(tǒng)內(nèi)核,已被應(yīng)用到各種嵌入式系統(tǒng)中。它支持x86、ARM、PowerPC、MIPS、DSP等眾多體系結(jié)構(gòu),并有上百個(gè)商業(yè)應(yīng)用實(shí)例,其穩(wěn)定性和可用性是經(jīng)過實(shí)踐驗(yàn)證的。同時(shí),它的源代碼公開,可以從www.ucos-ii.com網(wǎng)站上獲得全部源碼以及其在各種體系結(jié)構(gòu)平臺上的移植范例。
μC/OS-Ⅱ 2.0版以上的內(nèi)核都具有可搶占的實(shí)時(shí)多任務(wù)調(diào)度功能。另外它還提供了許多系統(tǒng)服務(wù),例如信號量、消息隊(duì)列、郵箱、內(nèi)存管理、時(shí)間函數(shù)等,這些功能可以根據(jù)不同的需求進(jìn)行裁減??梢哉f,μC/OS-Ⅱ是一個(gè)具備現(xiàn)代操作系統(tǒng)特點(diǎn)的RTOS。它結(jié)構(gòu)清晰、注解詳盡,具有良好的可擴(kuò)展性和可移植性,被廣泛地應(yīng)用于各種架構(gòu)的微處理器上。
2?TMS320C6201芯片介紹
TMS320C6201是TMS320系列產(chǎn)品中的新一代高性能的DSPs芯片。它是16位的定點(diǎn)數(shù)字信號處理器,在200MHz速率工作時(shí)可達(dá)1 600Mips;四通道DMA控制端口;最大3Mb片上存儲器;備有三種掉電模式;二個(gè)多通道緩沖串口;二枚32位定時(shí)器;超薄256/352腳BGA封裝;先進(jìn)超長指令字結(jié)構(gòu);每周期執(zhí)行八條32位指令,八個(gè)獨(dú)立通用功能單元;業(yè)內(nèi)最先進(jìn)的DSP C語言編譯器;一個(gè)新直觀性而又類似RISC的指令集,方便易用;匯編優(yōu)化程序調(diào)度任務(wù),方便匯編語言編程。
3?實(shí)時(shí)內(nèi)核的移植
移植工作包括以下內(nèi)容:修改OS_CPU.H中常量、數(shù)據(jù)類型和宏;用C語言改寫OS_CPU_C.C中六個(gè)簡單的函數(shù);用匯編語言改寫OS_CPU_A.ASM中的四個(gè)函數(shù)。
3.1 OS_CPU.H文件的修改
在OS_CPU.H頭文件中定義了與處理器相關(guān)的常量OS_STK_GRCWTH、宏OS_ENTER_CRITICAL( )、宏OS_EXIT_CRITICAL( )、宏OS_TASK_SW( )以及可移植的數(shù)據(jù)類型等。
(1)可移植的數(shù)據(jù)類型
由于C語言中的short、int、long等數(shù)據(jù)類型的數(shù)位數(shù)隨著所使用處理器的不同而變化,所以移植性不強(qiáng),μC/OSⅡ不支持。μC/OSⅡ定義了可移植的數(shù)據(jù)類型,包括8位、16位、32位的有符號數(shù)和無符號數(shù)等。此外還需要根據(jù)DSP芯片TMS320C6201的堆棧寬度定義任務(wù)堆棧數(shù)據(jù)類型OS_STK。具體定義如下:
typedef unsigned ? char BOOLEAN;布爾量
typedef unsigned?? char INT8U;8位無符號數(shù)
typedef signed???? char INT8S;8位有符號數(shù)
typedef unsigned?? short INT16U;16位無符號數(shù)
typedef signed???? short INT16S;16位有符號數(shù)
typedef unsigned ? int INT32U;32位無符號數(shù)
typedef signed???? int INT32S;32位有符號數(shù)
typedef float????? ??? FP32;32位單精度浮點(diǎn)數(shù)
typedef double????????? FP64;64位雙精度浮點(diǎn)數(shù)
typedef unsigned ? int OS_STK;TMS320C6201的堆棧入口寬度為32位
(2)宏定義
由于某些代碼在執(zhí)行時(shí)不可分割,μC/OSⅡ?qū)崟r(shí)內(nèi)核在訪問這些代碼臨界區(qū)時(shí)必須禁止中斷,因此μC/OSⅡ?qū)崟r(shí)內(nèi)核在頭文件OS_CPU.H中還定義了宏OS_ENTER_CRITICAL( )和OS_EXIT_CRITICAL( ),分別用于開中斷和關(guān)中斷。對TMS320C6201而言,可用如下代碼實(shí)現(xiàn):
extern cregister volatile unsigned int IER;
extern volatile unsigned int Always_Enabled_Interrupts;
extern volatile unsigned int Normally_Enabled_Interrupts;
static inline void OS_ENTER_CRITICAL(void)
{???? IER=Always_Enabled_Interrupts;
???? ?? asm(″NOP 4″);
} /*關(guān)全局中斷,進(jìn)入臨界區(qū)*/
??? static inline void OS_EXIT_CRITICAL(void)
{?? IER=Normally_Enabled_Interrupts;
??? asm(″NOP 5″);
} /*開全局中斷,進(jìn)入臨界區(qū)*/
#define OS_STK_GROWTH 1/*TMS320C6201的堆棧是由
?????????????????????? 低地址向高地址遞增*/
3.2 OS_CPU_C.C文件的修改
OS_CPU_C.C文件中需要用戶修改六個(gè)函數(shù):OSTaskCreateHook( )、OSTaskDelHook( )、OSTaskSwHook( )、OSTaskStatHook( )、OSTaskCreateHook( )、OSTaskStkIinit( )。而實(shí)際需要修改的只有OSTaskStkIinit( )函數(shù),其他函數(shù)是為方便用戶擴(kuò)展功能而設(shè),其定義可為空。
函數(shù)OSTaskStkIinit( )用于系統(tǒng)創(chuàng)建用戶任務(wù)時(shí),建立并初始化任務(wù)堆棧。該函數(shù)與處理器的硬件體系密切相關(guān),它將所有的寄存器壓棧,返回新的堆棧棧頂,并將它們保存在該任務(wù)的任務(wù)控制塊OS_TCB中,最終使初始化后的堆棧跟剛發(fā)生過一次中斷一樣。這樣,系統(tǒng)無需對調(diào)度程序作特殊處理即可直接對新任務(wù)進(jìn)行調(diào)度。由于在TMS320C620中堆棧是按32位數(shù)據(jù)類型進(jìn)行操作,所以堆棧數(shù)據(jù)類型OS_STK聲明為32位無符號整數(shù)。OSTaskStkIinit( )函數(shù)代碼如下:
void *OSTaskStkInit(void(*task)(void*pd),void*pdata,
void *ptos,INT16U opt)
{???? INITIAL_REGISTER_FRAME *Frame,*StackBottom
int*FirstFreeCellInStack
Frame=(INITIAL_REGISTER_FRAME*)((int)ptos &~7)
StackBottom=Frame
Frame--
Frame->A0.integer=0x0A0?? /*初始化寄存器*/
Frame->A1.integer=0x0A1
Frame->A2.integer=0x0A2
Frame->A3.integer=0x0A3
Frame->A4.integer=(int) pdata
Frame->A5.integer=0x0A5
Frame->A6.integer=0x0A6
Frame->A7.integer=0x0A7
Frame->A8.integer=0x0A8
Frame->A9.integer=0x0A9
Frame->A10.integer=0x0A10
Frame->A11.integer=0x0A11
Frame->A12.integer=0x0A12
Frame->A13.integer=0x0A13
Frame->A14.integer=0x0A14
Frame->A15.integer=0xA15
Frame->B0.integer=0x0B0
Frame->B1.integer=0x0B1
Frame->B2.integer=0x0B2
Frame->B3.integer=0x0B3
Frame->B4.integer=0x0B4
Frame->B5.integer=0x0B5
Frame->B6.integer=0x0B6
Frame->B7.integer=0x0B7
Frame->B8.integer=0x0B8
Frame->B9.integer=0x0B9
Frame->B10.integer=0x0B10
Frame->B11.integer=0x0B11
Frame->B12.integer=0x0B12
Frame->B13.integer=0x0B13
Frame->B14.integer=ReturnCurrentDP()
Frame->B15.integer=(int)StackBottom
Frame->AMR_Adressing_Mode_Register=0
Frame->CSR_Control_Status_Register=(0<<8)+3
Frame->IER_Interrupt_Enable_Register=Normally_
??????????????????????????????? Enabled_Interrupts
Frame->IRP_Interrupt_Return_Pointer=0xdeadbeef
Frame->Start_Address=task
rsFreeCellInStack=(int*) Frame
rstFreeCellInStack--
turn (FirstFreeCellInStack)
}
3.3 OS_CPU_A.ASM文件的修改
此文件包括的四個(gè)函數(shù)都涉及對寄存器的處理,與處理器有關(guān)。由于不同的處理器有不同的寄存器,所以操作系統(tǒng)在這個(gè)文件中給用戶留下四個(gè)函數(shù)接口,以便用戶根據(jù)所選處理器編寫相應(yīng)的匯編程序以完成固定的功能。四個(gè)函數(shù)分別是:多任務(wù)啟動函數(shù)中調(diào)用的OSSTartHightRdy( )、任務(wù)切換函數(shù)OSCtxSw( )、中斷任務(wù)切換函數(shù)OSIntCtxSw( )、時(shí)鐘節(jié)拍服務(wù)函數(shù)OSTickISR( )。
(1)OSSTartHightRdy( )
該函數(shù)是由啟動函數(shù)OSStart( )調(diào)用的,功能是使系統(tǒng)能及時(shí)運(yùn)行優(yōu)先級最高的就緒任務(wù)。由于系統(tǒng)中數(shù)據(jù)指針OSTCBHighRdy一直指向就緒任務(wù)中優(yōu)先級最高的任務(wù)控制塊OS_TCB,使得OSSTartHightRdy( )可以輕易地獲取最高優(yōu)先級任務(wù)的棧頂指針,再將保存在此任務(wù)堆棧的寄存器值恢復(fù)到CPU寄存器中,使該任務(wù)得以運(yùn)行,實(shí)現(xiàn)多任務(wù)的啟動。對于TMS320C6201,其代碼如下:
B??????? .S1???? _OSTaskSwHook?? /*調(diào)用用戶自
定義的_OSTaskSwHook*/
NOP??????????????????????????? 3
MVKL???? .S2???? OSStartHighRdy_1,B3
MVKH? ? .S2???? OSStartHighRdy_1,B3
OSStartHighRdy_1:
LDW???? .D2T2???? *+DP(_OSTCBHighRdy),B4
/*獲得最高優(yōu)先級任務(wù)的TCB地址*/
LDB????? .D2T2???? *+DP(_OSPrioHighRdy),B5
NOP3
STW????? .D2T2???? B4,*+DP(_OSTCBCur)
??? STB????? .D2T2???? B5,*+DP(_OSPrioCur)
????|| mvk?? 1,b1
??? STB????? .D2T2???? B1,*+DP(_OSRunning)
????LDW????? .D2T2???? *B4,SP
????NOP????? 4
??? (2)OSCtxSw( )
??? 該函數(shù)由任務(wù)切換函數(shù)OS_TASK_SW( )進(jìn)入。如果任務(wù)執(zhí)行了某個(gè)函數(shù),其結(jié)果若改變了當(dāng)前任務(wù)的狀態(tài)(如OSTaskSuspend( )、OSTimeDly( ))或是改變了別的任務(wù)的狀態(tài)(如OSTaskResume( )、OSTimeDlyResume( )),則都要引起新的任務(wù)調(diào)度函數(shù)(OSSched( ))執(zhí)行OS_TASK_SW( )。其代碼如下:
addk?????? .s2 (4 -_Framesize),SP
STW??????? .D2T2???? B3,*+SP(_StartAddress)
STW??????? .D2T2???? B0,*+SP(_B0)
|| mvc???? AMR,B0
STW??????? .D2T2???? B0,*+SP(_AMR)
|| mvc???? CSR,B0
STW??????? .D2T2???? B0,*+SP(_CSR)
|| mvc??? IER,B0
STW?????? .D2T2???? B0,*+SP(_IER)
STW?????? .D2T1???? A0,*+SP(_A0)
|| MV???? .L1X??? SP,A0
STW?????? .D2T1???? A1,*+SP(_A1)
|| addk?? .s1?????? (_IRP),A0
STW?????? .D2T1???? A0,*+SP(_B15)
STW?????? .D2T1???? A2,*+SP(_A2)
STW?????? .D2T1???? A3,*+SP(_A3)
STW?????? .D2T1???? A4,*+SP(_A4)
STW?????? .D2T1???? A5,*+SP(_A5)
STW?????? .D2T1???? A6,*+SP(_A6)
STW?????? .D2T1???? A7,*+SP(_A7)
STW?????? .D2T1???? A8,*+SP(_A8)
STW?????? .D2T1???? A9,*+SP(_A9)
STW?????? .D2T1???? A10,*+SP(_A10)
STW?????? .D2T1???? A11,*+SP(_A11)
STW?????? .D2T1???? A12,*+SP(_A12)
STW?????? .D2T1???? A13,*+SP(_A13)
STW?????? .D2T1???? A14,*+SP(_A14)
STW?????? .D2T1???? A15,*+SP(_A15)
LDW?????? .D2T2???? *+DP(_OSTCBCur),B0
??? STW?????? .D2T2???? B1,*+SP(_B1)
STW?????? .D2T2???? B2,*+SP(_B2)
STW?????? .D2T2???? B3,*+SP(_B3)
STW? ???? .D2T2???? B4,*+SP(_B4)
STW ????? .D2T2???? B5,*+SP(_B5)
STW ????? .D2T2???? B6,*+SP(_B6)
STW???????????????? SP,*B0
STW?????? .D2T2???? B7,*+SP(_B7)
STW?????? .D2T2???? B8,*+SP(_B8)
STW?????? .D2T2???? B9,*+SP(_B9)
STW?????? .D2T2???? B10,*+SP(_B10)
STW?????? .D2T2???? B11,*+SP(_B11)
STW?????? .D2T2???? B12,*+SP(_B12)
STW?????? .D2T2???? B13,*+SP(_B13)
STW?????? .D2T2???? B14,*+SP(_B14)
(3)OSIntCtxSw( )
μC/OS-Ⅱ中,中斷的產(chǎn)生可能會引起任務(wù)的切換,中斷服務(wù)程序的最后會調(diào)用OSIntExit( )檢查任務(wù)就緒狀況。如果需要進(jìn)行任務(wù)切換,將調(diào)用OSIntCtxSw( )。所以SIntCtxSw( )又稱為中斷級的任務(wù)切換函數(shù)。需要注意是,任何中斷服務(wù)程序ISR前面都要像下文介紹的時(shí)鐘節(jié)拍函數(shù)STickISR( )流程的第②步那樣保存上下文環(huán)境。SIntCtxSw( )和OSCtxSw( )的后半部分幾乎相同,不同處是對當(dāng)前任務(wù)的堆棧指針進(jìn)行了調(diào)整。其代碼如下:
LDW??????? .D2T2???? *+DP(_OSTCBCur),B0
|| mv?????? SP,B1
|| addk???? .s2????? (8),B1
STW??????? ?.D2T2???? B1,*B0
NOP????? ? 4
(4)OSTickISR( )
μC/OS-Ⅱ中,時(shí)鐘節(jié)拍中斷是一個(gè)非常重要的中斷,因?yàn)檎麄€(gè)操作系統(tǒng)的活動都受到它的激勵(lì)。OSTickISR( )的執(zhí)行流程為:①硬件進(jìn)入中斷處理;②保護(hù)上下文環(huán)境;③調(diào)用OSIntEnter( ),記錄中斷嵌套層數(shù);④調(diào)用OSTimeTick( ),檢查處理各個(gè)任務(wù)的延時(shí),并根據(jù)情況修改就緒任務(wù)表;⑤調(diào)用OSIntExit( ),檢查就緒任務(wù)表,看是否有比當(dāng)前任務(wù)優(yōu)先級更高的任務(wù)就緒。如果有,則進(jìn)行調(diào)度;如果沒有,OSIntExit( )返回并恢復(fù)②所保存的上下文環(huán)境,并執(zhí)行RETI回到被中斷的那個(gè)任務(wù)中繼續(xù)運(yùn)行。
4? 結(jié)束語
μC/OS-Ⅱ作為一個(gè)優(yōu)秀的實(shí)時(shí)操作系統(tǒng)已經(jīng)被移植到各種體系結(jié)構(gòu)的微處理器上,而DSP體系結(jié)構(gòu)在嵌入式領(lǐng)域也獲得了廣泛的應(yīng)用和支持。將μC/OS-Ⅱ移植到DSP平臺上,能夠更深入地了解實(shí)時(shí)操作系統(tǒng)的構(gòu)造,加快在DSP平臺上的應(yīng)用和開發(fā),并為更高層次上的擴(kuò)展和改進(jìn)打下基礎(chǔ)。
參考文獻(xiàn)
1?? LABROSSE J J著,邵貝貝譯.μC/OS-Ⅱ—源碼公開的實(shí)時(shí)嵌入式操作系統(tǒng).北京:中國電力出版社,2001