版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
μCOS-II微小內(nèi)核分析2第一頁,共79頁。最小內(nèi)核
|μC/OS-II微小內(nèi)核分析
任務(wù)級的任務(wù)調(diào)度小結(jié)通過對上述內(nèi)容的學(xué)習(xí),可以看出下圖就是從Task0到Task1,然后再從Task1到OS_TaskIdle的切換過程。任務(wù)級的任務(wù)調(diào)度如果ticks非0,則將當(dāng)前任務(wù)Task0從就緒表中刪除,并將ticks延時節(jié)拍數(shù)保存到當(dāng)前任務(wù)Task0的OS_TCB中,然后進(jìn)行一次任務(wù)調(diào)度,并且執(zhí)行下一個處于就緒態(tài)優(yōu)先級最高的任務(wù)Task1。ticks非0,則將當(dāng)前任務(wù)Task1從就緒表中刪除,并將ticks延時節(jié)拍數(shù)保存到當(dāng)前任務(wù)Task1的OS_TCB中,然后再進(jìn)行一次任務(wù)調(diào)度,并且執(zhí)行下一個處于就緒態(tài)優(yōu)先級最高的任務(wù)OS_TaskIdle。第二頁,共79頁。μC/OS-II微小內(nèi)核分析臨界區(qū)與中斷管理123456可重入性案例分析禁止/允許中斷時鐘節(jié)拍中斷服務(wù)程序
中斷管理第三頁,共79頁。臨界區(qū)與中斷管理|μC/OS-II微小內(nèi)核分析可重入性可重入的代碼指的是一段代碼可以被多個任務(wù)同時調(diào)用,而不必?fù)?dān)心數(shù)據(jù)被破壞。即就是說,可重入型函數(shù)在任何時候都可以被中斷,一段時間以后又可以繼續(xù)運(yùn)行,而相應(yīng)數(shù)據(jù)卻不會丟失??芍厝胄秃瘮?shù)或者只使用局部變量,即變量保存在CPU寄存器或堆棧中;或者使用全局變量。當(dāng)使用全局變量時,則要對全局變量予以保護(hù)。可重入性代碼
任務(wù)1任務(wù)2任務(wù)3代碼的可重入性是保證完成多任務(wù)的基礎(chǔ)。調(diào)用調(diào)用調(diào)用第四頁,共79頁。臨界區(qū)與中斷管理|μC/OS-II微小內(nèi)核分析案例分析在RTOS中,有可能幾個任務(wù)需要訪問同一個資源。同一個資源往往不能被幾個任務(wù)同時訪問,否則可能會破壞資源。全局變量是最簡單的資源,本例用2個全局變量模擬1個共享資源,讓低優(yōu)先級任務(wù)依次改變2個全局變量的值,讓它們的值始終相等。而高優(yōu)先級的任務(wù)則定時檢查這2個變量的值是否相等,如果不相等,則讓LED2閃爍。第五頁,共79頁。臨界區(qū)與中斷管理|μC/OS-II微小內(nèi)核分析案例分析voidTask0(void*pdata){……while(1){OS_ENTER_CRITICAL();if(sum1!=sum2){if((i%2)==0){IO2CLR=LED2;}else{IO2SET=LED2;}i++;}OS_EXIT_CRITICAL();……}}初始化工作允許中斷下面給出Task0任務(wù)的主要處理代碼。LED1閃爍關(guān)鍵代碼,禁止中斷如果sum1與sum2不相等,則根據(jù)i%2的值點(diǎn)亮或熄滅LED2第六頁,共79頁。臨界區(qū)與中斷管理|μC/OS-II微小內(nèi)核分析案例分析voidTask1(void*pdata){pdata=pdata;
while(1){OS_ENTER_CRITICAL();sum1++;sum2++;OS_EXIT_CRITICAL();}}防止編譯器報警sum1和sum2加1下面給出Task1任務(wù)的主要處理代碼。允許中斷關(guān)鍵代碼,禁止中斷由于CPU在執(zhí)行關(guān)鍵代碼時,中斷被屏蔽,因此不可能執(zhí)行中斷服務(wù)程序,也就不會引起中斷切換。此時,只要Task0()運(yùn)行,sum1和sum2就相等,因此,LED2不會閃爍。第七頁,共79頁。臨界區(qū)與中斷管理|μC/OS-II微小內(nèi)核分析案例分析voidTask0(void*pdata){……while(1){if(sum1!=sum2){……}……}}初始化工作當(dāng)刪除了禁止中斷和允許中斷的語句后,任務(wù)間可能出現(xiàn)以下情況。sum1與sum2相等,不執(zhí)行括號內(nèi)的代碼LED1閃爍voidTask1(void*pdata){pdata=pdata;while(1){sum1++;sum2++;}}sum1加1防止編譯器報警執(zhí)行任務(wù)1任務(wù)調(diào)度發(fā)生中斷任務(wù)調(diào)度sum1與sum2不相等,執(zhí)行括號內(nèi)的代碼LED2閃爍第八頁,共79頁。臨界區(qū)與中斷管理|μC/OS-II微小內(nèi)核分析禁止/允許中斷和其它內(nèi)核一樣,μC/OS-Ⅱ?yàn)榱颂幚砼R界區(qū)代碼需要禁止中斷,處理完畢后再允許中斷,這使得μC/OS-Ⅱ能夠避免同時有其它任務(wù)或中斷服務(wù)進(jìn)入臨界段代碼。為了避開不同C編譯器廠商選擇不同的方法來處理禁止中斷和允許中斷,μC/OS-Ⅱ定義兩個宏來禁止中斷和允許中斷,分別是:OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()。OS_ENTER_CRITICAL()臨界區(qū)代碼OS_EXIT_CRITICAL()需成對出現(xiàn)第九頁,共79頁。臨界區(qū)與中斷管理|μC/OS-II微小內(nèi)核分析禁止/允許中斷在ARM7中,OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()是通過使用軟件中斷異常實(shí)現(xiàn)的,詳細(xì)請參考SWI軟件中斷異常章節(jié)。ENTER_CRITICALLDRR1,=OsEnterSumLDRBR2,[R1] ADDR2,R2,#1STRBR2,[R1] MRSR0,SPSRORRR0,R0,#NoIntMSRSPSR_c,R0MOVSPC,LR 禁止中斷關(guān)中斷計(jì)數(shù)器OsEnterSum加1返回OS_ENTER_CRITICAL的實(shí)現(xiàn)代碼如下:第十頁,共79頁。臨界區(qū)與中斷管理|μC/OS-II微小內(nèi)核分析禁止/允許中斷OS_EXIT_CRITICAL()的實(shí)現(xiàn)代碼如下:EXIT_CRITICALLDRR1,=OsEnterSumLDRBR2,[R1] SUBR2,R2,#1STRBR2,[R1]
CMPR2,#0 MRSEQR0,SPSRBICEQR0,R0,#NoIntMSREQSPSR_c,R0MOVSPC,LR OsEnterSum為0,則允許中斷關(guān)中斷計(jì)數(shù)器OsEnterSum加1返回判斷OsEnterSum是否為0在ARM處理器核中禁止中斷和禁止中斷是通過改變程序狀態(tài)寄存器CPSR中的相應(yīng)控制位來實(shí)現(xiàn)的。由于使用了軟件中斷,程序狀態(tài)寄存器CPSR保存到程序狀態(tài)保存寄存器SPSR中,軟件中斷退出時會將SPSR恢復(fù)到CPSR中,所以程序只要改變程序狀態(tài)保存寄存器SPSR中相應(yīng)的控制位就可以了。第十一頁,共79頁。臨界區(qū)與中斷管理|μC/OS-II微小內(nèi)核分析時鐘節(jié)拍時鐘節(jié)拍是特定的周期性中斷,時鐘節(jié)拍源一般是由專門的硬件定時器產(chǎn)生的,該定時器是一個周期性定時器,該定時器產(chǎn)生周期性的中斷,這個中斷可以看作是系統(tǒng)心臟的脈動。一般情況下,用戶在第一個任務(wù)中開啟時鐘節(jié)拍器,以避免用戶程序崩潰。μC/OS-Ⅱ中的時鐘節(jié)拍服務(wù)是通過在中斷服務(wù)程序中調(diào)用OSTimeTick()實(shí)現(xiàn)的,OSTimeTick()是為系統(tǒng)提供時鐘節(jié)拍的服務(wù)程序。第十二頁,共79頁。臨界區(qū)與中斷管理|μC/OS-II微小內(nèi)核分析時鐘節(jié)拍使用timer0產(chǎn)生周期性時鐘節(jié)拍,其過程如下圖所示。VIC初始化定時器0初始化Timer0中斷服務(wù)程序產(chǎn)生中斷調(diào)用OSTimeTick()減少任務(wù)一個延時節(jié)拍數(shù),并判斷任務(wù)是否延時結(jié)束。如果延時結(jié)束,則任務(wù)進(jìn)入就緒狀態(tài)。其中,VIC初始化函數(shù)為VICInit(),定時器0初始化函數(shù)為imer0Init(),timer0中斷服務(wù)函數(shù)為Timer0_Exception()。
第十三頁,共79頁。臨界區(qū)與中斷管理|μC/OS-II微小內(nèi)核分析時鐘節(jié)拍VIC初始化函數(shù)VICInit()和定時器0初始化函數(shù)Timer0Init()如下。#defineOS_TICKS_PER_SEC200voidVICInit(void){......
設(shè)置定時器0的中斷優(yōu)先級;設(shè)置定時器0的中斷服務(wù)程序入口;使能定時器0中斷;}其它中斷初始化設(shè)置中斷優(yōu)先級為0(最高)在OS_CFG.h中定義,一秒鐘200個時鐘節(jié)拍設(shè)置Timer0的中斷服務(wù)地址為Timer0_ExceptionvoidTimer0Init(void){T0IR=0xff;T0TC=0;
T0TCR=0x01;
T0MCR=0x03;
T0MR0=(Fpclk/OS_TICKS_PER_SEC)}設(shè)置TC的計(jì)數(shù)值為0使能Timer0清除中斷TC值匹配時產(chǎn)生中斷,且TC值復(fù)位設(shè)定匹配值第十四頁,共79頁。臨界區(qū)與中斷管理|μC/OS-II微小內(nèi)核分析時鐘節(jié)拍voidTimer0_Exception(void){T0IR=0x01;VICvectAddr=0;OSTimeTick();}通知中斷控制器中斷結(jié)束調(diào)用時鐘節(jié)拍函數(shù)清除Timer0中斷當(dāng)完成VIC跟Timer0的初始化后,如果此時允許中斷,則CPU跳轉(zhuǎn)到中斷異常入口處,同時CPU切換到IRQ中斷模式,“中斷返回地址+4”保存在IRQ中斷模式下的LR寄存器中,再跳轉(zhuǎn)到中斷異常處理程序IRQ_Handler,獲取Timer0中斷服務(wù)程序地址Timer0_Exception。μC/OS-Ⅱ中的函數(shù)OSTimeTick()在周期性中斷的中斷服務(wù)程序Timer0_Exception()中被調(diào)用,μC/OS-Ⅱ會在中斷退出時調(diào)用另一個為中斷編寫的調(diào)度器,讓處于就緒態(tài)優(yōu)先級最高的任務(wù)運(yùn)行。第十五頁,共79頁。臨界區(qū)與中斷管理|μC/OS-II微小內(nèi)核分析中斷服務(wù)程序一般來說,μC/OS-II中,中斷服務(wù)程序的全部或部分用匯編語言來寫。當(dāng)然,部分芯片的部分編譯器可能可以全部使用C語言編寫,但畢竟是少數(shù),中斷服務(wù)程序的圖解如下。執(zhí)行用戶代碼(中斷服務(wù))保存全部寄存器中斷服務(wù)程序調(diào)用OSIntEnter或OSIntNesting直接加1
調(diào)用OSIntExit()
恢復(fù)所有CPU寄存器執(zhí)行中斷返回指令
告訴μC/OS-Ⅱ此時正在執(zhí)行中斷服務(wù)OSIntNesting減1,如果OSIntNesting減到0時,則表明所有中斷,包括嵌套的中斷都已經(jīng)完成。此時μC/OS-Ⅱ要判定有沒有優(yōu)先級更高的任務(wù)被中斷服務(wù)程序喚醒,如果有優(yōu)先級更高的任務(wù)進(jìn)入了就緒態(tài),那么μC/OS-Ⅱ就返回到那個更高優(yōu)先級的任務(wù)。第十六頁,共79頁。臨界區(qū)與中斷管理|μC/OS-II微小內(nèi)核分析中斷服務(wù)程序針對ARM7,當(dāng)有IRQ中斷產(chǎn)生且CPU允許相應(yīng)中斷時,CPU會跳轉(zhuǎn)到IRQ中斷異常入口處(異常向量表),同時CPU切換到IRQ中斷模式,處理器會自動將“IRQ中斷返回地址+4”保存到IRQ模式下的LR寄存器中,并將用戶模式下的CPSR保存到IRQ模式下的SPSR_irq中?!癐RQ中斷返回地址+4”保存到IRQ模式下的LR中CPU跳到IRQ中斷異常入口,且CPU切換到IRQ中斷模式IRQ中斷
用戶模式下的CPSR保存到IRQ模式下的SPSR_irq第十七頁,共79頁。臨界區(qū)與中斷管理|μC/OS-II微小內(nèi)核分析中斷服務(wù)程序在針對ARM7的μC/OS-Ⅱ中,移植代碼提供了匯編接口代碼,它完成了大部分必要的工作。對于LPC系列ARM,進(jìn)入中斷的匯編接口代碼如下。......IRQ_Handler
SUBLR,LR,#4STMFDSP!,{R0-R3,R12,LR}
MRSR3,SPSRSTMFDSP,{R3,SP,LR}^LDRR2,=OSIntNestingLDRBR1,[R2]ADDR1,R1,#1STRBR1,[R2]SUBSP,SP,#4*3MSRCPSR_c,#(NoInt|SYS32Mode)CMPR1,#1LDREQSP,=StackUsrBL$IRQ_Exception_Function引入外部標(biāo)號計(jì)算IRQ中斷返回地址保存用戶狀態(tài)的R3,SP,LR,注意不能回寫保存任務(wù)環(huán)境OSIntNesting++調(diào)整SP指針內(nèi)容切換到系統(tǒng)模式跳轉(zhuǎn)到中斷服務(wù)程序如果當(dāng)前中斷是發(fā)生在任務(wù)執(zhí)行時,則把SP設(shè)置為StackUsr如果不使用這兩條指令,則實(shí)際的中斷處理函數(shù)使用的是任務(wù)本身的堆棧,這樣每個任務(wù)都需要為中斷處理程序保留足夠的堆棧,浪費(fèi)了大量存儲空間。當(dāng)使用了這兩條指令,那么任務(wù)就不需要為中斷處理程序保留堆??臻g。對于LPC2000系列ARM,StackUsr一般就是main()函數(shù)的堆棧,與main()函數(shù)分時復(fù)用。由于調(diào)用OSStart()之后才可能產(chǎn)生中斷,而OSStart()永遠(yuǎn)不會返回main()函數(shù),此時main()函數(shù)的堆??梢匀我馐褂?。第十八頁,共79頁。臨界區(qū)與中斷管理|μC/OS-II微小內(nèi)核分析中斷服務(wù)程序退出中斷的匯編接口代碼如下。MSRCPSR_c,#(NoInt|SYS32Mode)LDRR2,=OSEnterSumMOVR1,#1STRR1,[R2]BLOSInitExitLDRR2,=OSEnterSumMOVR1,#0STRR1,[R2]MSRCPSR_c,#(NoInt|IRQ32Mode)LDMFDSP,{R3,SP,LR}^LDRR0,=OSTCBHighRdyLDRR0,[R0]LDRR1,=OSTCBCurLDRR1,[R1]CMPR0,R1ADDSP,SP,#4*3MSRSPSR_cxsf,R3LDMEQFDSP!,{R0-R3,R12,LR}^LDRPC,=OSIntCtxSw
切換到系統(tǒng)模式恢復(fù)用戶狀態(tài)的R3,SP,LR,注意不能回寫調(diào)用OSInitExit調(diào)整SP指針內(nèi)容恢復(fù)IRQ中的SPSR根據(jù)OSTCBHighRdy與OSTCBCur的值決定是否進(jìn)行任務(wù)切換OsEnterSum為1,使OSIntExit退出時中斷關(guān)閉因?yàn)橹袛喾?wù)程序要退出,所以O(shè)sEnterSum=0切換回到IRQ模式比較OSTCBHighRdy指向的內(nèi)容與OSTCBCur指向的內(nèi)容第十九頁,共79頁。臨界區(qū)與中斷管理|μC/OS-II微小內(nèi)核分析中斷服務(wù)程序SPR12LRPCCPSRSPSRSPLRR0R1R3R4—R11R2SPR12LRPCCPSRSPSRSPLRR0R1R3R4—R11R2退出中斷時的出棧關(guān)系進(jìn)入中斷時的壓棧關(guān)系寄存器寄存器
用戶模式IRQ模式用戶模式IRQ模式0x??0x??0x??0x??0x??0x??0x??0x??0x??存儲器0x??123R0LRSPSPSR_irqLR_irqR12R3R2R154堆棧指針位置說明入堆指針位置出堆指針位置進(jìn)入和退出中斷時的堆棧動作圖示如下。
執(zhí)行代碼STMFDSP!,{R0-R3,R12,LR}保存任務(wù)環(huán)境;執(zhí)行代碼STMFDSP,{R3,SP,LR}^保存用戶狀態(tài)的CPSR;執(zhí)行代碼SUBSP,SP,#4*3調(diào)整SP指針內(nèi)容;執(zhí)行代碼LDMFDSP,{R3,SP,LR}^恢復(fù)用戶狀態(tài)的R3、SP、LR;執(zhí)行代碼ADDSP,SP,#4*3調(diào)整SP指針內(nèi)容;執(zhí)行代碼LDMEQFDSP!,{R0-R3,R12,PC}^恢復(fù)任務(wù)環(huán)境。第二十頁,共79頁。臨界區(qū)與中斷管理|μC/OS-II微小內(nèi)核分析中斷管理由中斷服務(wù)程序可知,μC/OS-Ⅱ的中斷管理實(shí)際上就是2個函數(shù),OSIntEnter()和OSIntExit()。
第二十一頁,共79頁。臨界區(qū)與中斷管理|μC/OS-II微小內(nèi)核分析中斷管理voidOSIntEnter(void){if(OSRunning==TRUE){if(OSIntNesting<255){OSIntNesting++;}}}判斷OSIntNesting是否小于255OSIntNesting加1判斷RTOS是否運(yùn)行進(jìn)入中斷處理的代碼如下所示。第二十二頁,共79頁。臨界區(qū)與中斷管理|μC/OS-II微小內(nèi)核分析中斷管理voidOSIntExit(void){if(OSRunning==TRUE){OS_ENTER_CRITICAL();if(OSIntNesting>0){OSIntNesting--;}if(OSInterNesting==0){OSIntExitY=OSUnMapTbl[OSRdyGrp];OSPrioHighRdy=((INT8U)(OSIntExitY<<3)+OSUnMapTbl[OSRdyTbl[OSIntExitY]]);if(OSPrioHighRdy!=OSPrioCur){OSTCBHighRdy=OSTCBPrioTbl[OSPrioHighRdy];OSIntCtxSw();}}OSIntNesting為0則查找進(jìn)入就緒態(tài)且優(yōu)先級最高的任務(wù)把就緒表中最高優(yōu)先級與當(dāng)前的優(yōu)先級進(jìn)行比較,不相等則進(jìn)行調(diào)度當(dāng)OSIntNesting大于0時,OSIntNesting減1退出中斷處理的代碼如下所示。注:上述代碼中OSIntCtxSw()僅僅是一條在INCLUDES.H中定義的函數(shù)返回語句,如下所示。而μC/OS-II要求OSIntCtxSw()直接做任務(wù)的切換工作,但此時OSIntExit()函數(shù)會將一些東西壓入堆棧中,而且壓入的數(shù)目與編譯器及編譯參數(shù)有關(guān),則加大了OSIntCtxSw()出錯的概率,從而減少了移植代碼的使用范圍。因此在LPC系列ARM中實(shí)際的中斷退出任務(wù)切換工作是在標(biāo)號為OSIntCtxSw的匯編代碼中實(shí)現(xiàn)。#defineOSIntCtxSw()return第二十三頁,共79頁。臨界區(qū)與中斷管理|μC/OS-II微小內(nèi)核分析中斷管理OSIntCtxSw;注意:當(dāng)前還是IRQ模式,下面為保存環(huán)境變量LDRR2,[SP,#20]LDRR12,[SP,#16]MRSR0,CPSRMSRCPSR_c,#(NoInt|SYS32Mode)MOVR1,LRSTMFDSP!,{R1-R2}STMFDSP!,{R4-R12}MSRCPSR_c,R0LDMFDSP!,{R4-R7}ADDSP,SP,#8MSRCPSR_c,#(NoInt|SYS32Mode)STMFDSP!,{R4-R7}……保存LR,PC,R4-R12從IRQ堆棧獲取R0-R3暫存到系統(tǒng)模式下的R4-R7獲取PC和R12退出中斷處理的代碼如下所示。保存IRQ模式下的CPSR切換到系統(tǒng)模式切換到IRQ模式出棧R12,PC切換到系統(tǒng)模式R0-R3入棧保存到任務(wù)堆棧區(qū)由于匯編接口代碼中沒有將符號OSIntCtxSw導(dǎo)出,也沒有引入符號OSIntCtxSw,也就是說匯編語言中的OSIntCtxSw和C語言中的OSIntCtxSw是不同的函數(shù),因此不會互相沖突。第二十四頁,共79頁。臨界區(qū)與中斷管理|μC/OS-II微小內(nèi)核分析中斷管理IRQ堆棧區(qū)其它棧數(shù)據(jù)LR_IRQR12R3R2R1R0空閑空間SPR12LRPCCPSRSPSRSPLRR0R1R3R4—R7R2寄存器系統(tǒng)模式IRQ模式其它棧數(shù)據(jù)PCLRR12R11…R5R4R8—R1111任務(wù)堆棧區(qū)R3R2R1R0空閑空間IRQ模式堆棧指針系統(tǒng)模式堆棧指針堆棧指針位置IRQ模式堆棧指針位置任務(wù)堆棧指針位置23645執(zhí)行代碼LDRR2,[SP,#20]和LDRR12,[SP,#16]獲取PC和R12;執(zhí)行代碼STMFDSP!,{R1-R2}保存LR,PC;執(zhí)行代碼STMFDSP!,{R4-R12}保存R4-R12;切換到IRQ模式,執(zhí)行代碼LDMFDSP!,{R4-R7}從IRQ堆棧區(qū)獲取R0-R3暫存到系統(tǒng)模式下的R4-R7中;執(zhí)行代碼ADDSP,SP,#8出棧R12,PC;切換到系統(tǒng)模式,執(zhí)行代碼STMFDSP!,{R40-R7}將R0-R3入棧保存到任務(wù)堆棧區(qū)。切換到系統(tǒng)模式,執(zhí)行代碼MOVR1,LR;保存LR到R1因?yàn)樘幱诓煌哪J剑虼薎RQ堆棧區(qū)與任務(wù)堆棧區(qū)分別處于不同的堆??臻g中。中斷退出時的堆棧處理過程如下圖所示。第二十五頁,共79頁。μC/OS-II微小內(nèi)核分析任務(wù)的結(jié)束1234案例分析改進(jìn)的任務(wù)控制塊改進(jìn)的TCB初始化刪除任務(wù)第二十六頁,共79頁。任務(wù)的結(jié)束|μC/OS-II微小內(nèi)核分析案例分析在實(shí)際的系統(tǒng)中,可能有一些任務(wù)很少運(yùn)行。例如,假設(shè)PDA有MP3的播放功能,但如果用戶不聽MP3,則此任務(wù)就不運(yùn)行。如果用戶聽完MP3后,系統(tǒng)也應(yīng)當(dāng)刪除任務(wù),以釋放其占用的資源。在μC/OS-Ⅱ中,如果有多個任務(wù)不可能同時運(yùn)行,也可以將它們設(shè)置為同一個優(yōu)先級,它們運(yùn)行完畢后刪除自身,這樣就可以極大地減少對RAM的需求(可以使用同一個堆棧),也就意味著成本的降低,這些任務(wù)一般是由人機(jī)界面(如鍵盤)啟動的。為了支持此功能,就需要μC/OS-Ⅱ微小內(nèi)核支持任務(wù)刪除功能,下面為鍵盤啟動多個同優(yōu)先級任務(wù)(這個任務(wù)會刪除自身)的程序框架。第二十七頁,共79頁。任務(wù)的結(jié)束|μC/OS-II微小內(nèi)核分析案例分析TaskKey程序代碼如下。voidTaskkey(void*pdata){unsignedintkey;pdata=pdata;while(1){key=keyin();switch(key){caseKEY1:OSTaskCreat(TaskKey1,NULL,&TaskKeyStk[494],10); break;caseKEY2:……}OSTimeDly(2);}}創(chuàng)建任務(wù)1創(chuàng)建其它任務(wù)防止編譯器報警任務(wù)延時第二十八頁,共79頁。任務(wù)的結(jié)束|μC/OS-II微小內(nèi)核分析案例分析TaskKey1的代碼如下。voidTaskKey1(void*pdata){pdata=pdata;……OSTaskDel(OS_PRIO_SELF);}任務(wù)處理刪除任務(wù)自身防止編譯器出錯第二十九頁,共79頁。任務(wù)的結(jié)束|μC/OS-II微小內(nèi)核分析改進(jìn)的任務(wù)控制塊由任務(wù)控制塊小節(jié)可知,所有任務(wù)控制塊(TCB)是由2個單向鏈表構(gòu)成的,即空閑任務(wù)控制塊鏈表和已經(jīng)使用的任務(wù)控制塊鏈表。刪除任務(wù)一個很重要的工作就是將任務(wù)對應(yīng)的任務(wù)控制塊從已經(jīng)使用的任務(wù)控制塊鏈表中刪除,放到空閑任務(wù)控制塊鏈表中。從理論上講,任務(wù)控制塊不需要修改就可以支持刪除任務(wù)操作。但是從單向鏈表中刪除一個元素是非常麻煩的,需要從鏈表頭開始搜索直到指定的元素才可以刪除。而在雙向鏈表中刪除一個元素就很簡單了,為了加快刪除任務(wù)的速度(同時使刪除任務(wù)花費(fèi)的時間固定),任務(wù)控制塊增加了一個指向鏈表前一個元素的OSTCBPrev指針,將已經(jīng)使用的任務(wù)控制塊鏈表改造成雙向鏈表。Typedefstructos_tcb{……structos_tcb*OSTCBPrev;}新增的成員,用于快速刪除任務(wù)第三十頁,共79頁。任務(wù)的結(jié)束|μC/OS-II微小內(nèi)核分析改進(jìn)的任務(wù)控制塊已改造成雙向鏈表任務(wù)控制塊鏈表如下圖所示。增加了OSTCBPrevr指針前一個控制塊頭指針第三十一頁,共79頁。任務(wù)的結(jié)束|μC/OS-II微小內(nèi)核分析改進(jìn)的TCB初始化因?yàn)橐呀?jīng)使用的任務(wù)控制塊鏈表已經(jīng)改造成了雙向鏈表,那么TCB初始化也就隨之發(fā)生了變化。由任務(wù)控制塊小節(jié)可知,給已使用任務(wù)控制塊鏈表增加元素是從鏈表頭插入的。此時,新增元素的前一個元素為空,原來的鏈表頭元素(OSTCBList)的前一個元素為新加入的元素。增加了幾行代碼后,新的TCB初始化代碼就完成了。如下所示。INT8UOS_TCBInit(INT8Uprio,OS_STK*ptos,OS_STK*pbos,INT16Uid,INT32Ustk_size,void*pext,INT16Uopt){……ptcb->OSTCBPrev=(OS_TCB*)0;if(OSTCBList!=(OS_TCB*)0){OSTCBList->OSTCBPrev=ptcb;}新增的代碼,用于建立反向鏈表,加快刪除任務(wù)TCB初始化第三十二頁,共79頁。任務(wù)的結(jié)束|μC/OS-II微小內(nèi)核分析刪除任務(wù)通過調(diào)用函數(shù)OSTaskDel(),可以讓處于就緒態(tài)、運(yùn)行態(tài)和等待態(tài)的任務(wù)回到睡眠態(tài),也就是說任務(wù)被刪除。刪除一個任務(wù),其實(shí)際上就是將該任務(wù)從任務(wù)控制塊鏈表中刪除,并將它歸還給空任務(wù)控制塊鏈表。第三十三頁,共79頁。任務(wù)的結(jié)束|μC/OS-II微小內(nèi)核分析刪除任務(wù)函數(shù)OSTaskDel()流程圖如下所示。OSTaskDel()先檢查刪除任務(wù)的各種條件是否成立,如果不成立,則返回相應(yīng)的錯誤碼。一旦所有條件都滿足了,OS_TCB就會從所有可能的μC/OS-Ⅱ的數(shù)據(jù)結(jié)構(gòu)中移除。首先本任務(wù)從就緒表中刪除,然后本任務(wù)從索引表數(shù)組OSTCBPrioTbl[]中刪除,接著本任務(wù)從已使用的任務(wù)控制塊鏈表中刪除,最后將任務(wù)控制塊加到空閑TCB鏈表中。這些都做完后,啟動調(diào)度器運(yùn)行下一個優(yōu)先級最高的就緒任務(wù),任務(wù)刪除就結(jié)束了。第三十四頁,共79頁。任務(wù)的結(jié)束|μC/OS-II微小內(nèi)核分析刪除任務(wù)INT8UOSTaskDel(INT8Uprio){OS_TCB*ptcb;if(OSIntNesting>0){return(OS_TASK_DEL_ISR);}#ifOS_ARG_CHK_EN>0if(prio==OS_IDLE_PRIO){return(OS_TASK_DEL_IDLE); }if(prio>=OS_LOWEST_PRIO&&prio!=OS_PRIO_SELF){return(OS_PRIO_INVALID);}#endifOS_ENTER_CRITICAL(); if(prio==OS_PRIO_SELF){ prio=OSTCBCur->OSTCBPrio;}ptcb=OSTCBPrioTbl[prio];if(ptcb!=(OS_TCB*)0){if((OSRdyTbl[ptcb->OSTCBY]&=~ptcb->OSTCBBitX)==0x00){OSRdyGrp&=~ptcb->OSTCBBitY;}ptcb->OSTCBDly=0;ptcb->OSTCBStat=OS_STAT_RDY;OSTaskDel的代碼如下。不能在中斷中刪除任務(wù)不能刪除空閑任務(wù)任務(wù)優(yōu)先級非法將任務(wù)從就緒表中刪除獲得當(dāng)前任務(wù)優(yōu)先級獲得要刪除任務(wù)的TCB第三十五頁,共79頁。任務(wù)的結(jié)束|μC/OS-II微小內(nèi)核分析刪除任務(wù)OSTCBPrioTbl[prio]=(OS_TCB*)0; if(ptcb->OSTCBPrev==(OS_TCB*)0){ptcb->OSTCBNext->OSTCBPrev=(OS_TCB*)0;OSTCBList=ptcb->OSTCBNext;}else{ptcb->OSTCBPrev->OSTCBNext=ptcb->OSTCBNext;ptcb->OSTCBNext->OSTCBPrev=ptcb->OSTCBPrev;}ptcb->OSTCBNext=OSTCBFreeList;OSTCBFreeList=ptcb;OS_EXIT_CRITICAL();OS_Sched();return(OS_NO_ERR);}OS_EXIT_CRITICAL();return(OS_TASK_DEL_ERR);}在索引表中刪除本任務(wù)從已使用的任務(wù)控制塊鏈表中刪除對應(yīng)的任務(wù)控制塊加到空閑任務(wù)控制塊中任務(wù)調(diào)度第三十六頁,共79頁。μC/OS-II微小內(nèi)核分析信號量12345事件與信號量事件控制塊改進(jìn)的任務(wù)控制塊及任務(wù)刪除函數(shù)改進(jìn)的OS初始化信號量管理6刪除信號量第三十七頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析事件與信號量在嵌入式實(shí)時多任務(wù)系統(tǒng)中,為了使系統(tǒng)達(dá)到高效處理和快速響應(yīng)的目的,于是大量采用“事件驅(qū)動”的方式來編寫任務(wù)。而事件可能是外部的,比如外部設(shè)備中斷;也可能是嵌入式系統(tǒng)內(nèi)部產(chǎn)生的,比如一個任務(wù)給另一個任務(wù)發(fā)送信號量或消息。由此可見,用于任務(wù)同步和通信的信號量、消息郵箱、消息隊(duì)列和互斥信號量都叫做“事件”。
事件信號量(Sem)消息郵箱(Mbox)消息隊(duì)列(Q)互斥信號量(Mutex)第三十八頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析事件與信號量我們知道酒店的桌子數(shù)是固定的,因此可以這樣理解其最大桌子數(shù)就是計(jì)數(shù)器的初值,假設(shè)一人占用一張桌子,因此每進(jìn)去一人,計(jì)數(shù)器就會自動減1,而只有出去一人時計(jì)數(shù)器才會自動加1。即就是說,如果計(jì)數(shù)器大于0,就可以進(jìn)去吃飯,否則只好等待有人出來才能進(jìn)去,這種計(jì)數(shù)信號就是信號量。酒店人計(jì)數(shù)器(能容納的人數(shù))3210人人人禁止其它客人進(jìn)入人沒有空位,不能再容納客人有空位,能再容納1位客人第三十九頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析事件與信號量信號量就像通行證,且通行證的數(shù)目是有限的,任務(wù)要運(yùn)行下去就必須先拿到通行證。如果信號量已被別的任務(wù)占用,那么該任務(wù)只能被掛起,直到信號量被當(dāng)前使用者釋放為止。信號量的值可以是0到255、0到65535或0到4294967295,取決于信號量規(guī)約機(jī)制使用的是8位、16位還是32位。到底是幾位,實(shí)際上取決于用的是哪種內(nèi)核。對于μC/OS-II來說,信號量使用16位,其取值范圍為0~65535。一般地說,對信號量只能實(shí)施3種操作:建立信號量(初始化)、等待信號量(掛起)、發(fā)送信號量。注意:信號量初始化時一定要給信號量賦初值,并將等待信號量任務(wù)列表清空。操作信號量建立信號量等待信號量發(fā)送信號量OSSemPend()OSSemCreate()OSSemPost()第四十頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析事件控制塊
μC/OS-II將信號量、互斥信號量、消息郵箱、消息隊(duì)列等統(tǒng)稱為“事件”,然后通過一個稱為“事件控制塊(ECB)”的數(shù)據(jù)結(jié)構(gòu)來管理事件,也就是說,任務(wù)和中斷服務(wù)程序可以通過ECB向另外的任務(wù)程序發(fā)送信號,任務(wù)也可以等待另一個任務(wù)或者中斷服務(wù)程序給它發(fā)送信號。事件控制塊的結(jié)構(gòu)如下圖所示。信號量的計(jì)數(shù)器或互斥信號量和優(yōu)先級繼承的計(jì)數(shù)器事件類型指向郵箱或消息隊(duì)列的指針等待任務(wù)列表第四十一頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析事件控制塊事件控制塊的定義如下所示。typedefstruct{INT8UOSEventType;INT16UOSEventCnt;void*OSEventPtr;INT8UOSEventGrp;INT8UOSEventTbl[OS_EVENT_TBL_SIZE];}OS_EVENT;OSEventType定義了事件的具體類型。在μC/OS-II微小內(nèi)核中只能為OS_EVENT_SEM(信號量)和OS_EVENT_TYPE_UNUSED(未分配)。當(dāng)然,在完整版的μC/OS-II還可以是OS_EVENT_TYPE_MBOX(消息郵箱)、OS_EVENT_TYPE_Q(消息隊(duì)列)和OS_EVENT_TYPE_MUTEX(互斥信號量)。當(dāng)事件控制塊用于信號量時,OSEventCnt用作信號量的計(jì)數(shù)器;當(dāng)事件控制塊用于互斥信號量時,互斥信號量和優(yōu)先級繼承優(yōu)先級的計(jì)數(shù)器。OSEventPtr指針只有在所定義的事件是郵箱或者消息隊(duì)列時才使用。當(dāng)所定義的事件是郵箱時,它指向一個消息;而當(dāng)所定義的事件是消息隊(duì)列時,它指向消息隊(duì)列控制塊。當(dāng)然,空閑事件控制塊鏈表也用它做鏈表指針。它們共同構(gòu)成事件控制塊的等待任務(wù)列表。第四十二頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析事件控制塊對于等待事件任務(wù)的記錄,μCOS-II采用了與任務(wù)就緒表類似的方法,使用一個INT8U類型的數(shù)組OSEventTbl[]作為記錄等待事件任務(wù)的記錄表,這個表叫等待任務(wù)表,如下圖所示。索引表,非必須的,為加快處理速度而引入根據(jù)任務(wù)的優(yōu)先級可以確定該任務(wù)在等待任務(wù)列表中的確切位置真正的等待任務(wù)列表
OSEventTbl[]雖然被定義為“字節(jié)數(shù)組”,但仍被看作是“位數(shù)組”,即每一位代表一個任務(wù),其中任何一位為1表示對應(yīng)的任務(wù)為事件的等待任務(wù),否則不是等待任務(wù)。等待任務(wù)表OSEventTbl[]數(shù)組的大小取決于OS_LOWEST_PRIO的值確定事件的等待任務(wù)在OSEventTbl[OS_LOWEST_PRIO/8+1]中的位置,即橫坐標(biāo)X確定變量OSEventGrp具體數(shù)據(jù)位,用于確定等待任務(wù)表數(shù)組元素的下標(biāo),即縱坐標(biāo)Y第四十三頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析事件控制塊下面將給出一個任務(wù)放到事件的等待任務(wù)列表中的代碼和從等待任務(wù)列表中刪除一個任務(wù)的代碼,需要說明的是,OS_EVENT_TBL_SIZE被定義為((OS_LOWEST_PRIO)/8+1)。1、將任務(wù)加入等待任務(wù)列表2、從等待任務(wù)列表中刪除任務(wù)pevent->OSEventGrp|=OSMapTbl[prio>>3];pevent->OSEventTbl[prio>>3]|=OSMapTbl[prio&0x07];if((pevent->OSEventTbl[prio>>3]&=~OSMapTbl[prio&0x07])==0){pevent->OSEventGrp&=~OSMapTbl[prio>>3];}第四十四頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析事件控制塊INT8UconstOSUnMapTbl[]={//0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f0,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0x00to0x0F*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0x10to0x1F*/5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0x20to0x2F*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0x30to0x3F*/6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0x40to0x4F*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0x50to0x5F*/5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0x60to0x6F*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0x70to0x7F*/7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0x80to0x8F*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0x90to0x9F*/5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0xA0to0xAF*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0xB0to0xBF*/6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0xC0to0xCF*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0xD0to0xDF*/5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, /*0xE0to0xEF*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 /*0xF0to0xFF*/};若OSRdyGrp為0x68,以此值為偏移量查表得y值為3若OSRdyTb1[y]為0x30,以此值為偏移量表得x值為2就緒任務(wù)組優(yōu)先級最高的就是26(3<<3+2)y=OSUnMapTbl[pevent->OSEventGrp];x=OSUnMapTbl[pevent->OSEventTbl[y]];prio=(y<<3)+x;找出最高優(yōu)先級任務(wù)的縱坐標(biāo)找出最高優(yōu)先級任務(wù)的橫坐標(biāo)算出最高優(yōu)先級從等待任務(wù)列表中查找優(yōu)先級最高的任務(wù)也很簡單,其代碼如下所示。第四十五頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析事件控制塊在μC/OS-II中,與事件控制塊相關(guān)的變量有2個,分別為OSEventFreeList和OSEventTbl[]。其中OSEventFreeList為空閑事件控制塊鏈表的頭指針,而OSEventTbl[]用于實(shí)際分配事件控制塊存儲空間。事件控制塊的總數(shù)由用戶所需要的信號量、互斥信號量、消息郵箱、消息隊(duì)列的總數(shù)決定,當(dāng)然在μC/OS-II微小內(nèi)核中只有信號量一種事件,事件控制塊的總數(shù)只由用戶所需要的信號量數(shù)目決定。OS_MAX_EVENTS由用戶在OS_CFG.H中定義。事件控制塊的定義如下所示。OS_EXTOS_EVENT*OSEventFreeList;OS_EXTOS_EVENTOSEventTbl[OS_MAX_EVENTS];第四十六頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析事件控制塊在使用事件控制塊之前,需要將所有事件控制塊鏈接成一個空閑事件控制塊鏈表(見下圖)。每當(dāng)建立一個信號量、互斥信號量、消息郵箱、消息隊(duì)列時,就從該鏈表中取出一個空閑事件控制塊,并對它進(jìn)行初始化。當(dāng)信號量、互斥信號量、消息郵箱、消息隊(duì)列被刪除時,對應(yīng)的事件控制塊也需要放回到空閑事件控制塊鏈表中。OSEventFreeList為空閑事件控制塊鏈表的“頭指針”用于實(shí)際分配事件控制塊儲存空間第四十七頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析事件控制塊staticvoidOS_InitEventList(void){#if(OS_EVENT_EN>0)&&(OS_MAX_EVENTS>0)#if(OS_MAX_EVENTS>1)INT16Ui;OS_EVENT*pevent1;OS_EVENT*pevent2;pevent1=&OSEventTbl[0];pevent2=&OSEventTbl[1];for(i=0;i<(OS_MAX_EVENTS-1);i++){pevent1->OSEventType=OS_EVENT_TYPE_UNUSED;pevent1->OSEventPtr=pevent2;pevent1++; pevent2++; }pevent1->OSEventType=OS_EVENT_TYPE_UNUSED;pevent1->OSEventPtr=(OS_EVENT*)0; OSEventFreeList=&OSEventTbl[0]; #elseOSEventFreeList=&OSEventTbl[0];OSEventFreeList->OSEventType=OS_EVENT_TYPE_UNUSED;OSEventFreeList->OSEventPtr=(OS_EVENT*)0;#endif#endif}空閑事件控制塊鏈表初始化代碼如下。當(dāng)有多個事件時,執(zhí)行下面代碼把所有空閑事件控制塊的類型設(shè)置為“未分配”鏈表尾指針指向“NULL”鏈表頭指針指向第一個空閑任務(wù)塊只有一個任務(wù)控制塊時的處理程序第四十八頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析事件控制塊使等待超時的任務(wù)進(jìn)入就緒態(tài)使任務(wù)進(jìn)入等待狀態(tài)初始化事件控制塊使等待事件的任務(wù)進(jìn)入就緒態(tài)事件控制塊1324對于事件控制塊有一些通用的操作,如下圖所示。為了避免代碼重復(fù)和減短程序代碼長度,μC/OS-II將上面的操作用4個系統(tǒng)函數(shù)來實(shí)現(xiàn),它們分別是:OS_EventWaitListInit(),OS_EventTaskRdy(),OS_EventTaskWait()和OS_EventTO(),下面將分別逐一介紹。第四十九頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析事件控制塊1、初始化事件控制塊當(dāng)建立一個信號量、互斥信號量、消息郵箱或消息隊(duì)列時,需要對事件控制塊中的等待任務(wù)列表進(jìn)行初始化,這是通過調(diào)用函數(shù)OS_EventWaitListInit()來實(shí)現(xiàn)的。由上面的分析可知,讓等待任務(wù)列表沒有任何任務(wù)就是將事件控制塊(ECB)的OSEventGrp成員和OSEventTbl[]的所有成員賦值為0。第五十頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析事件控制塊voidOS_EventWaitListInit(OS_EVENT*pevent){INT8U*ptbl;pevent->OSEventGrp=0x00;ptbl=&pevent->OSEventTbl[0];
#ifOS_EVENT_TBL_SIZE>0*ptbl++=0x00; #endif……}OS_EventWaitListInit的源代碼如下。將OSEventGrp賦值為0將OSEventTbl[]的所有成員賦值為0第五十一頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析事件控制塊2、使任務(wù)進(jìn)入等待狀態(tài)當(dāng)某個任務(wù)要等待一個事件的發(fā)生時,需要將任務(wù)從就緒任務(wù)表中刪除,并放到相應(yīng)事件的事件控制塊的等待任務(wù)表中,這些操作是通過調(diào)用函數(shù)OS_EventTaskWait()來實(shí)現(xiàn)的。第五十二頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析事件控制塊voidOS_EventTaskWait(OS_EVENT*pevent){OSTCBCur->OSTCBEventPtr=pevent;if((OSRdyTbl[OSTCBCur->OSTCBY]&=~OSTCBCur->OSTCBBitX)==0x00){ OSRdyGrp&=~OSTCBCur->OSTCBBitY;}pevent->OSEventTbl[OSTCBCur->OSTCBY]|=OSTCBCur->OSTCBBitX;pevent->OSEventGrp|=OSTCBCur->OSTCBBitY;}OS_EventTaskWait的源代碼如下。指明任務(wù)等待的事件從就緒表中刪除當(dāng)前任務(wù)將當(dāng)前任務(wù)加入到等待任務(wù)列表中第五十三頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析事件控制塊3、使等待事件的任務(wù)進(jìn)入就緒態(tài)當(dāng)發(fā)生了某個事件時,需要將等待這個事件的任務(wù)中優(yōu)先級最高的一個置于就緒態(tài),這是通過調(diào)用函數(shù)OS_EventTaskRdy()來實(shí)現(xiàn)的。在μC/OS-II中,TCB的成員OSTCBStat不同的位表示等待不同的事件,則不同事件處理程序調(diào)用函數(shù)OS_EventTaskRdy()時,需要清除OSTCBStat不同位,則需要一個指示,就是參數(shù)msk。當(dāng)然,μC/OS-II微小內(nèi)核只有一個事件,理論上不需要這個參數(shù),保留它是為了使微小內(nèi)核的代碼最大限度與原版保持一致。
第五十四頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析事件控制塊INT8UOS_EventTaskRdy(OS_EVENT*pevent,void*msg,INT8Umsk){……y=OSUnMapTbl[pevent->OSEventGrp]; bity=OSMapTbl[y]; x=OSUnMapTbl[pevent->OSEventTbl[y]];bitx=OSMapTbl[x];prio=(INT8U)((y<<3)+x);if((pevent->OSEventTbl[y]&=~bitx)==0x00){pevent->OSEventGrp&=~bity;}ptcb=OSTCBPrioTbl[prio];ptcb->OSTCBDly=0;ptcb->OSTCBEventPtr=(OS_EVENT*)0;ptcb->OSTCBStat&=~msk;if(ptcb->OSTCBStat==OS_STAT_RDY){ OSRdyGrp|=bity;OSRdyTbl[y]|=bitx;}return(prio); } OS_EventTaskRdy的源代碼如下。準(zhǔn)備公共中間變量獲得任務(wù)優(yōu)先級從等待任務(wù)列表中刪除任務(wù)獲得任務(wù)TCB將任務(wù)加入就緒表中任務(wù)不再等待事件任務(wù)不再需要等待超時指針指向NULL第五十五頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析事件控制塊4、使等待超時的任務(wù)進(jìn)入就緒態(tài)
在μC/OS-II中,任務(wù)等待某個事件時可以指定超時時間,如果超時時間到了,指定的事件仍然沒有到來,任務(wù)也會被時鐘節(jié)拍處理函數(shù)OSTimeTick()設(shè)置為就緒態(tài)。此時,等待任務(wù)列表中仍然保存這個任務(wù),任務(wù)控制塊中也仍然有一些變量沒有恢復(fù),這些未完的事情由函數(shù)OS_EventTO()處理。第五十六頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析事件控制塊voidOS_EventTO(OS_EVENT*pevent){if((pevent->OSEventTbl[OSTCBCur->OSTCBY]&=~OSTCBCur->OSTCBBitX)==0x00){pevent->OSEventGrp&=~OSTCBCur->OSTCBBitY;}OSTCBCur->OSTCBStat=OS_STAT_RDY;OSTCBCur->OSTCBEventPtr=(OS_EVENT*)0;}
OS_EventTO的源代碼如下。任務(wù)狀態(tài)設(shè)置為就緒態(tài)事件控制塊指針指向NULL從等待任務(wù)列表中刪除任務(wù)第五十七頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析改進(jìn)的任務(wù)控制塊及任務(wù)刪除函數(shù)有了事件支持之后,刪除任務(wù)時就要特別小心了。當(dāng)一個任務(wù)在等待事件時可能被別的任務(wù)刪除,此時盡管任務(wù)已經(jīng)刪除,但任務(wù)還保存在事件的等待任務(wù)列表中。當(dāng)對應(yīng)的事件到來之時,會將這個已經(jīng)不存在(或者說睡眠態(tài))的任務(wù)設(shè)置為就緒態(tài),這顯然是不可能的。如果在事件來臨之前又建立了另一個優(yōu)先級相同任務(wù),則程序執(zhí)行的結(jié)果顯然是錯誤的。因此,刪除任務(wù)時必須將任務(wù)從它等待事件的等待任務(wù)列表中刪除。第五十八頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析改進(jìn)的任務(wù)控制塊及任務(wù)刪除函數(shù)由于在μC/OS-II中,一個任務(wù)同一時間只能等待一個事件,所以在任務(wù)控制塊中增加一個指向其所等待的事件的指針,實(shí)現(xiàn)這個功能就很簡單了。改進(jìn)后的任務(wù)控制塊如下所示。Typedefstructos_tcb{……OS_EVENT*OSTCBEventPtr;}OS_TCB;增加的成員,指向任務(wù)等待的事件第五十九頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析改進(jìn)的任務(wù)控制塊及任務(wù)刪除函數(shù)當(dāng)使用OSTCBEventPtr這個成員后,任務(wù)的刪除函數(shù)也相應(yīng)地得到了改進(jìn)。改進(jìn)的任務(wù)刪除函數(shù)代碼如下所示。INT8UOSTaskDel(INT8Uprio){#ifOS_EVENT_EN>0OS_EVENT*pevent;#endif ……#ifOS_EVENT_EN>0pevent=ptcb->OSTCBEventPtr;if(pevent!=(OS_EVENT*)0){ if((pevent->OSEventTbl[ptcb->OSTCBY]&=~ptcb->OSTCBBitX)==0){pevent->OSEventGrp&=~ptcb->OSTCBBitY;}}#endif增加的代碼,從事件的等待任務(wù)列表中刪除任務(wù)第六十頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析改進(jìn)的OS初始化在使用事件控制塊之前,需要將所有事件控制塊鏈接成一個空閑事件控制塊鏈表,則可以通過調(diào)用函數(shù)OS_InitEventList()來實(shí)現(xiàn)。從理論上來講,只要在使用事件控制塊之前調(diào)用函數(shù)OS_InitEventList()即可,但實(shí)際上在操作系統(tǒng)初始化時調(diào)用比較方便和可靠。這樣操作系統(tǒng)初始化函數(shù)OSInit()就需要添加對OS_InitEventList()的調(diào)用,改進(jìn)的OS初始化代碼如下所示。voidOSInit(void){OS_InitMisc(); OS_InitRdyList();
OS_InitTCBList();
OS_InitTaskIdle();
OS_InitEventList();}增加的函數(shù),將所有事件控制塊鏈接成一個空閑事件控制塊鏈表第六十一頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析信號量管理只要μC/OS-II支持信號量,就必須有3種操作:創(chuàng)建信號量OSSemCreate()、發(fā)送信號量OSSemPost()和等待信號量OSSemPend()。操作信號量建立信號量OSSemCreate()等待信號量OSSemPend()發(fā)送信號量OSSemPost()第六十二頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析信號量管理OSSemCreate函數(shù)1、創(chuàng)建信號量在使用信號量之前,必須通過調(diào)用函數(shù)OSSemCreate()來創(chuàng)建一個信號量,函數(shù)OSSemCreate()只有唯一的參數(shù)cnt,用于初始化信號量的計(jì)數(shù)器初始值,創(chuàng)建信號量函數(shù)OSSemCreate()將返回一個指針,用于識別不同的信號量。第六十三頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析信號量管理建立信號量的流程圖如下所示。第六十四頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析信號量管理OSSemCreate的源代碼如下所示。OS_EVENT*OSSemCreate(INT16Ucnt){OS_EVENT*pevent;if(OSIntNesting>0){return((OS_EVENT*)0); }OS_ENTER_CRITICAL();pevent=OSEventFreeList;if(OSEventFreeList!=(OS_EVENT*)0){ OSEventFreeList=(OS_EVENT*)OSEventFreeList->OSEventPtr; }OS_EXIT_CRITICAL();if(pevent!=(OS_EVENT*)0){ pevent->OSEventType=OS_EVENT_TYPE_SEM;pevent->OSEventCnt=cnt; pevent->OSEventPtr=(void*)0;OS_EventWaitListInit(pevent);}return(pevent);}不允許在中斷服務(wù)程序中創(chuàng)建信號量獲得空閑事件控制塊將事件類型設(shè)置為信號量給信號量計(jì)數(shù)器賦初值非必須的代碼初始化等待任務(wù)列表第六十五頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析信號量管理2、等待信號量等待信號量是通過調(diào)用函數(shù)OSSemPend()來實(shí)現(xiàn)的。OSSemPend函數(shù)第六十六頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析信號量管理等待信號量的流程圖如下所示。第六十七頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析信號量管理OSSemPend的源代碼如下所示。voidOSSemPend(OS_EVENT*pevent,INT16Utimeout,INT8U*err){if(OSIntNesting>0){*err=OS_ERR_PEND_ISR;return;}#ifOS_ARG_CHK_EN>0if(pevent==(OS_EVENT*)0){*err=OS_ERR_PEVENT_NULL;return;}if(pevent->OSEventType!=OS_EVENT_TYPE_SEM){*err=OS_ERR_EVENT_TYPE;return;}#endifOS_ENTER_CRITICAL();if(pevent->OSEventCnt>0){pevent->OSEventCnt--;OS_EXIT_CRITICAL();*err=OS_NO_ERR;return;}不允許在中斷服務(wù)程序中等待信號量檢查指針pevent所指的任務(wù)控制塊是否是信號量,如果不是,則返回相應(yīng)的錯誤代碼檢查當(dāng)前信號量是否有效有效,信號量計(jì)數(shù)器減1err的值為OS_NO_ERR無等待返回第六十八頁,共79頁。信號量|μC/OS-II微小內(nèi)核分析信號
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五版煤炭開采權(quán)轉(zhuǎn)讓及安全生產(chǎn)保障服務(wù)合同3篇
- 二零二五年度高速公路交通安全警示標(biāo)志制作合同樣本2篇
- 二零二五版餐飲業(yè)店長任期管理與聘用合同3篇
- 二零二五版自來水廠自動化控制系統(tǒng)升級合同3篇
- 二零二五版地鐵停車場車位租賃及公共交通服務(wù)合同2篇
- 二零二五版法院判決引導(dǎo)下的債務(wù)償還與追加借款合同3篇
- 二零二五版地下室出租合同(含倉儲物流)3篇
- 二零二五版深基坑降水井施工勞務(wù)分包合同2篇
- 二零二五年果園廢棄物資源化利用合同2篇
- 設(shè)備租賃公司2025年度租賃施工塔吊合同2篇
- 人教部編版七年級語文上冊《閱讀綜合實(shí)踐》示范課教學(xué)設(shè)計(jì)
- (正式版)QC∕T 1206.1-2024 電動汽車動力蓄電池?zé)峁芾硐到y(tǒng) 第1部分:通 用要求
- 《煤礦地質(zhì)工作細(xì)則》礦安﹝2024﹞192號
- 平面向量及其應(yīng)用試題及答案
- 消防控制室值班服務(wù)人員培訓(xùn)方案
- 《貴州旅游介紹》課件2
- 2024年中職單招(護(hù)理)專業(yè)綜合知識考試題庫(含答案)
- 無人機(jī)應(yīng)用平臺實(shí)施方案
- 挪用公款還款協(xié)議書范本
- 事業(yè)單位工作人員年度考核登記表(醫(yī)生個人總結(jié))
- 盾構(gòu)隧道施工數(shù)字化與智能化系統(tǒng)集成
評論
0/150
提交評論