版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、C/OS-II微小內核分析微小內核分析 緒論緒論 C/OS-II微小內核是為了方便初學者學習嵌入式實時操作系統(tǒng)的基本原理,分別由小到大將C/OS-II V2.52裁減為幾個只具備基本功能的微小內核。建議:初學者學習或者教師講授本章內容時,一定要盡量做到一邊閱讀源代碼一邊畫圖,事實上“過程比結論更重要” !1100行(剔除文件頭和函數(shù)頭后的數(shù)目) 只有418行(剔除文件頭和函數(shù)頭后的數(shù)目),僅包含5個最基本的服務函數(shù)的“最小內核最小內核”。 最小內核最小內核 | C/OS-II微小內核分析微小內核分析 任務級的任務調度小結任務級的任務調度小結 通過對上述內容的學習,可以看出下圖就是從Task0到
2、Task1,然后再從Task1到OS_TaskIdle的切換過程。任務級的任務調度如果ticks非0,則將當前任務Task0從就緒表中刪除,并將ticks延時節(jié)拍數(shù)保存到當前任務Task0的OS_TCB中,然后進行一次任務調度,并且執(zhí)行下一個處于就緒態(tài)優(yōu)先級最高的任務Task1。ticks非0,則將當前任務Task1從就緒表中刪除,并將ticks延時節(jié)拍數(shù)保存到當前任務Task1的OS_TCB中,然后再進行一次任務調度,并且執(zhí)行下一個處于就緒態(tài)優(yōu)先級最高的任務OS_TaskIdle 。C/OS-II微小內核分析微小內核分析臨界區(qū)與中斷管理臨界區(qū)與中斷管理123456可重入性可重入性 案例分析案
3、例分析 禁止禁止/允許中斷允許中斷 時鐘節(jié)拍時鐘節(jié)拍 中斷服務程序中斷服務程序 中斷管理中斷管理 臨界區(qū)與中斷管理臨界區(qū)與中斷管理| C/OS-II微小內核分析微小內核分析可重入性可重入性 可重入的代碼指的是一段代碼可以被多個任務同時調用,而不必擔心數(shù)據(jù)被破壞。即就是說,可重入型函數(shù)在任何時候都可以被中斷,一段時間以后又可以繼續(xù)運行,而相應數(shù)據(jù)卻不會丟失。 可重入型函數(shù)或者只使用局部變量,即變量保存在CPU寄存器或堆棧中;或者使用全局變量。當使用全局變量時,則要對全局變量予以保護。代碼的可重入性是保證完成多任務的基礎。調用調用調用臨界區(qū)與中斷管理臨界區(qū)與中斷管理| C/OS-II微小內核分析微
4、小內核分析案例分析案例分析 在RTOS中,有可能幾個任務需要訪問同一個資源。同一個資源往往不能被幾個任務同時訪問,否則可能會破壞資源。全局變量是最簡單的資源,本例用2個全局變量模擬1個共享資源,讓低優(yōu)先級任務依次改變2個全局變量的值,讓它們的值始終相等。而高優(yōu)先級的任務則定時檢查這2個變量的值是否相等,如果不相等,則讓LED2閃爍。臨界區(qū)與中斷管理臨界區(qū)與中斷管理| C/OS-II微小內核分析微小內核分析案例分析案例分析void Task0(void *pdata) while (1) OS_ENTER_CRITICAL(); if (sum1 != sum2) if (i % 2) = 0)
5、 IO2CLR = LED2; else IO2SET = LED2; i+; OS_EXIT_CRITICAL(); 初始化工作允許中斷 下面給出Task0任務的主要處理代碼。LED1閃爍關鍵代碼,禁止中斷如果sum1與sum2不相等,則根據(jù)i % 2的值點亮或熄滅LED2臨界區(qū)與中斷管理臨界區(qū)與中斷管理| C/OS-II微小內核分析微小內核分析案例分析案例分析void Task1 (void *pdata) pdata = pdata; while (1) OS_ENTER_CRITICAL(); sum1+; sum2+; OS_EXIT_CRITICAL(); 防止編譯器報警sum1和
6、sum2加1 下面給出Task1任務的主要處理代碼。允許中斷關鍵代碼,禁止中斷由于CPU在執(zhí)行關鍵代碼時,中斷被屏蔽,因此不可能執(zhí)行中斷服務程序,也就不會引起中斷切換。此時,只要Task0()運行,sum1和sum2就相等,因此,LED2不會閃爍。臨界區(qū)與中斷管理臨界區(qū)與中斷管理| C/OS-II微小內核分析微小內核分析案例分析案例分析void Task0(void *pdata) while (1) if (sum1 != sum2) 初始化工作當刪除了禁止中斷和允許中斷的語句后,任務間可能出現(xiàn)以下情況。sum1與sum2相等,不執(zhí)行括號內的代碼LED1閃爍void Task1 (void
7、*pdata) pdata = pdata; while (1) sum1+; sum2+; sum1加1防止編譯器報警執(zhí)行任務1任務調度發(fā)生中斷任務調度sum1與sum2不相等,執(zhí)行括號內的代碼LED2閃爍臨界區(qū)與中斷管理臨界區(qū)與中斷管理| C/OS-II微小內核分析微小內核分析禁止禁止/允許中斷允許中斷 和其它內核一樣,C/OS-為了處理臨界區(qū)代碼需要禁止中斷,處理完畢后再允許中斷,這使得C/OS-能夠避免同時有其它任務或中斷服務進入臨界段代碼。 為了避開不同C編譯器廠商選擇不同的方法來處理禁止中斷和允許中斷 ,C/OS-定義兩個宏來禁止中斷和允許中斷,分別是:OS_ENTER_CRITI
8、CAL()和OS_EXIT_CRITICAL()。 OS_ENTER_CRITICAL()臨界區(qū)代碼OS_EXIT_CRITICAL()需成對出現(xiàn)臨界區(qū)與中斷管理臨界區(qū)與中斷管理| C/OS-II微小內核分析微小內核分析禁止禁止/允許中斷允許中斷 在ARM7中,OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()是通過使用軟件中斷異常實現(xiàn)的,詳細請參考SWI軟件中斷異常章節(jié)。ENTER_CRITICAL LDR R1, =OsEnterSum LDRB R2, R1 ADD R2, R2, #1 STRB R2, R1 MRS R0, SPSR ORR R0, R0,
9、#NoInt MSR SPSR_c, R0 MOVS PC, LR 禁止中斷關中斷計數(shù)器OsEnterSum加1返回OS_ENTER_CRITICAL的實現(xiàn)代碼如下:臨界區(qū)與中斷管理臨界區(qū)與中斷管理| C/OS-II微小內核分析微小內核分析禁止禁止/允許中斷允許中斷OS_EXIT_CRITICAL()的實現(xiàn)代碼如下:EXIT_CRITICAL LDR R1, =OsEnterSum LDRB R2, R1 SUB R2, R2, #1 STRB R2, R1 CMP R2, #0 MRSEQ R0, SPSR BICEQ R0, R0, #NoInt MSREQ SPSR_c, R0 MOVS
10、 PC, LR OsEnterSum為0,則允許中斷關中斷計數(shù)器OsEnterSum加1返回判斷OsEnterSum是否為0在ARM處理器核中禁止中斷和禁止中斷是通過改變程序狀態(tài)寄存器CPSR中的相應控制位來實現(xiàn)的。由于使用了軟件中斷,程序狀態(tài)寄存器CPSR保存到程序狀態(tài)保存寄存器 SPSR中,軟件中斷退出時會將SPSR恢復到CPSR中,所以程序只要改變程序狀態(tài)保存寄存器SPSR中相應的控制位就可以了。 臨界區(qū)與中斷管理臨界區(qū)與中斷管理| C/OS-II微小內核分析微小內核分析時鐘節(jié)拍時鐘節(jié)拍 時鐘節(jié)拍是特定的周期性中斷時鐘節(jié)拍是特定的周期性中斷,時鐘節(jié)拍源一般是由專門的硬件定時器產生的,該定
11、時器是一個周期性定時器,該定時器產生周期性的中斷,這個中斷可以看作是系統(tǒng)心臟的脈動。一般情況下,用戶在第一個任務中開啟時鐘節(jié)拍器,以避免用戶程序崩潰。 C/OS-中的時鐘節(jié)拍服務是通過在中斷服務程序中調用OSTimeTick()實現(xiàn)的,OSTimeTick()是為系統(tǒng)提供時鐘節(jié)拍的服務程序。臨界區(qū)與中斷管理臨界區(qū)與中斷管理| C/OS-II微小內核分析微小內核分析時鐘節(jié)拍時鐘節(jié)拍使用timer0產生周期性時鐘節(jié)拍,其過程如下圖所示。VIC初始化定時器0初始化Timer0中斷服務程序產生中斷調用OSTimeTick()減少任務一個延時節(jié)拍數(shù),并判斷任務是否延時結束。如果延時結束,則任務進入就緒狀
12、態(tài)。其中,VIC初始化函數(shù)為VICInit() ,定時器0初始化函數(shù)為imer0Init() ,timer0中斷服務函數(shù)為Timer0_Exception() 。 臨界區(qū)與中斷管理臨界區(qū)與中斷管理| C/OS-II微小內核分析微小內核分析時鐘節(jié)拍時鐘節(jié)拍 VIC初始化函數(shù)VICInit()和定時器0初始化函數(shù)Timer0Init()如下。#define OS_TICKS_PER_SEC 200void VICInit (void) . 設置定時器0的中斷優(yōu)先級; 設置定時器0的中斷服務程序入口; 使能定時器0中斷; 其它中斷初始化設置中斷優(yōu)先級為0(最高)在OS_CFG.h中定義,一秒鐘200
13、個時鐘節(jié)拍設置Timer0的中斷服務地址為Timer0_Exceptionvoid Timer0Init (void) T0IR = 0 xff; T0TC = 0; T0TCR = 0 x01; T0MCR = 0 x03; T0MR0 = (Fpclk/OS_TICKS_PER_SEC) 設置TC的計數(shù)值為0使能Timer0 清除中斷TC值匹配時產生中斷,且TC值復位設定匹配值臨界區(qū)與中斷管理臨界區(qū)與中斷管理| C/OS-II微小內核分析微小內核分析時鐘節(jié)拍時鐘節(jié)拍void Timer0_Exception (void) T0IR = 0 x01; VICvectAddr = 0; OST
14、imeTick();通知中斷控制器中斷結束調用時鐘節(jié)拍函數(shù)清除Timer0中斷 當完成VIC跟Timer0的初始化后,如果此時允許中斷,則CPU跳轉到中斷異常入口處,同時CPU切換到IRQ中斷模式,“中斷返回地址+4” 保存在IRQ中斷模式下的LR寄存器中,再跳轉到中斷異常處理程序IRQ_Handler,獲取Timer0中斷服務程序地址Timer0_Exception 。C/OS-中的函數(shù)OSTimeTick()在周期性中斷的中斷服務程序Timer0_Exception()中被調用,C/OS-會在中斷退出時調用另一個為中斷編寫的調度器,讓處于就緒態(tài)優(yōu)先級最高的任務運行。 臨界區(qū)與中斷管理臨界區(qū)
15、與中斷管理| C/OS-II微小內核分析微小內核分析中斷服務程序中斷服務程序 一般來說,C/OS-II中,中斷服務程序的全部或部分用匯編語言來寫。當然,部分芯片的部分編譯器可能可以全部使用C語言編寫,但畢竟是少數(shù),中斷服務程序的圖解如下。執(zhí)行用戶代碼(中斷服務)執(zhí)行用戶代碼(中斷服務)保存全部寄存器保存全部寄存器中斷服務程序中斷服務程序 調用調用OSIntEnter或或 OSIntNesting直接加直接加1 調用調用OSIntExit() 恢復所有恢復所有CPU寄存器寄存器執(zhí)行中斷返回指令執(zhí)行中斷返回指令 告訴C/OS-此時正在執(zhí)行中斷服務 OSIntNesting減1,如果OSIntNes
16、ting減到0時,則表明所有中斷,包括嵌套的中斷都已經完成。此時C/OS-要判定有沒有優(yōu)先級更高的任務被中斷服務程序喚醒,如果有優(yōu)先級更高的任務進入了就緒態(tài),那么C/OS-就返回到那個更高優(yōu)先級的任務。 臨界區(qū)與中斷管理臨界區(qū)與中斷管理| C/OS-II微小內核分析微小內核分析中斷服務程序中斷服務程序 針對ARM7,當有IRQ中斷產生且CPU允許相應中斷時,CPU會跳轉到IRQ中斷異常入口處(異常向量表),同時CPU切換到IRQ中斷模式,處理器會自動將“IRQ中斷返回地址+4” 保存到IRQ模式下的LR寄存器中,并將用戶模式下的CPSR保存到IRQ模式下的SPSR_irq中。 “IRQ中斷返回
17、地址中斷返回地址+4”保存保存到到IRQ模式下的模式下的LR中中CPU跳到跳到IRQ中斷異常入口中斷異常入口,且且CPU切換到切換到IRQ中斷模式中斷模式IRQ中斷中斷 用戶模式下的用戶模式下的CPSR保存到保存到IRQ模式下的模式下的SPSR_irq臨界區(qū)與中斷管理臨界區(qū)與中斷管理| C/OS-II微小內核分析微小內核分析中斷服務程序中斷服務程序 在針對ARM7的C/OS-中,移植代碼提供了匯編接口代碼,它完成了大部分必要的工作。對于LPC系列ARM,進入中斷的匯編接口代碼如下。 .IRQ_Handler SUB LR, LR, #4 STMFD SP!, R0-R3, R12, LR MR
18、S R3, SPSR STMFD SP, R3, SP, LR LDR R2, =OSIntNesting LDRB R1, R2 ADD R1, R1, #1 STRB R1, R2 SUB SP, SP, #4*3 MSR CPSR_c,#(NoInt | SYS32Mode) CMP R1, #1 LDREQ SP, =StackUsr BL $IRQ_Exception_Function引入外部標號計算IRQ中斷返回地址保存用戶狀態(tài)的R3,SP,LR,注意不能回寫保存任務環(huán)境OSIntNesting+調整SP指針內容切換到系統(tǒng)模式跳轉到中斷服務程序如果當前中斷是發(fā)生在任務執(zhí)行時,則把S
19、P設置為StackUsr如果不使用這兩條指令,則實際的中斷處理函數(shù)使用的是任務本身的堆棧,這樣每個任務都需要為中斷處理程序保留足夠的堆棧,浪費了大量存儲空間。當使用了這兩條指令,那么任務就不需要為中斷處理程序保留堆棧空間。對于LPC2000系列ARM,StackUsr一般就是main()函數(shù)的堆棧,與main()函數(shù)分時復用。由于調用OSStart()之后才可能產生中斷,而OSStart()永遠不會返回main()函數(shù),此時main()函數(shù)的堆??梢匀我馐褂?。 臨界區(qū)與中斷管理臨界區(qū)與中斷管理| C/OS-II微小內核分析微小內核分析中斷服務程序中斷服務程序退出中斷的匯編接口代碼如下。 MSR
20、 CPSR_c,#(NoInt | SYS32Mode) LDR R2, =OSEnterSum MOV R1, #1 STR R1, R2 BL OSInitExit LDR R2, =OSEnterSum MOV R1, #0 STR R1, R2 MSR CPSR_c,#(NoInt | IRQ32Mode) LDMFD SP, R3, SP, LR LDR R0, =OSTCBHighRdy LDR R0, R0 LDR R1, =OSTCBCur LDR R1, R1 CMP R0, R1 ADD SP, SP, #4*3 MSR SPSR_cxsf, R3 LDMEQFD SP!,
21、 R0-R3, R12, LR LDR PC, =OSIntCtxSw 切換到系統(tǒng)模式恢復用戶狀態(tài)的R3,SP,LR,注意不能回寫調用OSInitExit調整SP指針內容恢復IRQ中的SPSR根據(jù)OSTCBHighRdy與OSTCBCur的值決定是否進行任務切換OsEnterSum為1,使OSIntExit退出時中斷關閉因為中斷服務程序要退出,所以OsEnterSum=0切換回到IRQ模式比較OSTCBHighRdy指向的內容與OSTCBCur指向的內容臨界區(qū)與中斷管理臨界區(qū)與中斷管理| C/OS-II微小內核分析微小內核分析中斷服務程序中斷服務程序SPR12LRPCCPSRSPSRSPLRR
22、0R1R3R4 R11R2SPR12LRPCCPSRSPSRSPLRR0R1R3R4 R11R2退出中斷時的出棧關系退出中斷時的出棧關系進入中斷時的壓棧關系進入中斷時的壓棧關系寄存器寄存器寄存器寄存器 用戶模式 IRQ模式用戶模式 IRQ模式0 x?0 x?0 x?0 x?0 x?0 x?0 x?0 x?0 x?存儲器存儲器0 x?123 R0 LR SPSPSR_irqLR_irq R12 R3 R2 R154堆棧指針位置說明入堆指針位置出堆指針位置進入和退出中斷時的堆棧動作圖示如下。 執(zhí)行代碼 STMFD SP!,R0-R3,R12,LR保存任務環(huán)境;執(zhí)行代碼 STMFD SP,R3,SP
23、,LR保存用戶狀態(tài)的CPSR;執(zhí)行代碼 SUB SP,SP,#4*3 調整SP指針內容;執(zhí)行代碼 LDMFD SP,R3,SP,LR恢復用戶狀態(tài)的R3、SP、LR;執(zhí)行代碼 ADD SP,SP,#4*3 調整SP指針內容;執(zhí)行代碼 LDMEQFD SP!,R0-R3,R12,PC 恢復任務環(huán)境。臨界區(qū)與中斷管理臨界區(qū)與中斷管理| C/OS-II微小內核分析微小內核分析中斷管理中斷管理 由中斷服務程序可知,C/OS-的中斷管理實際上就是2個函數(shù),OSIntEnter()和OSIntExit()。 臨界區(qū)與中斷管理臨界區(qū)與中斷管理| C/OS-II微小內核分析微小內核分析中斷管理中斷管理void
24、OSIntEnter (void) if (OSRunning = TRUE) if (OSIntNesting 0) OSIntNesting-; if (OSInterNesting = 0) OSIntExitY = OSUnMapTblOSRdyGrp; OSPrioHighRdy = (INT8U)(OSIntExitY OSTCBPrev = (OS_TCB*)0; if(OSTCBList != (OS_TCB*)0) OSTCBList-OSTCBPrev = ptcb;新增的代碼,用于建立反向鏈表,加快刪除任務TCB初始化任務的結束任務的結束| C/OS-II微小內核分析微小
25、內核分析刪除任務刪除任務 通過調用函數(shù)OSTaskDel(),可以讓處于就緒態(tài)、運行態(tài)和等待態(tài)的任務回到睡眠態(tài),也就是說任務被刪除。刪除一個任務,其實際上就是將該任務從任務控制塊鏈表中刪除,并將它歸還給空任務控制塊鏈表。 任務的結束任務的結束| C/OS-II微小內核分析微小內核分析刪除任務刪除任務函數(shù)OSTaskDel()流程圖如下所示。 OSTaskDel()先檢查刪除任務的各種條件是否成立,如果不成立,則返回相應的錯誤碼。一旦所有條件都滿足了,OS_TCB就會從所有可能的C/OS-的數(shù)據(jù)結構中移除。首先本任務從就緒表中刪除,然后本任務從索引表數(shù)組OSTCBPrioTbl中刪除,接著本任務
26、從已使用的任務控制塊鏈表中刪除,最后將任務控制塊加到空閑TCB鏈表中。這些都做完后,啟動調度器運行下一個優(yōu)先級最高的就緒任務,任務刪除就結束了。 任務的結束任務的結束| C/OS-II微小內核分析微小內核分析刪除任務刪除任務INT8U OSTaskDel (INT8U prio) OS_TCB *ptcb; if (OSIntNesting 0) return (OS_TASK_DEL_ISR); #if OS_ARG_CHK_EN 0 if (prio = OS_IDLE_PRIO) return (OS_TASK_DEL_IDLE); if (prio = OS_LOWEST_PRIO &
27、 prio != OS_PRIO_SELF) return (OS_PRIO_INVALID); #endif OS_ENTER_CRITICAL(); if (prio = OS_PRIO_SELF) prio = OSTCBCur-OSTCBPrio; ptcb = OSTCBPrioTblprio; if (ptcb != (OS_TCB *)0) if (OSRdyTblptcb-OSTCBY &= ptcb-OSTCBBitX) = 0 x00) OSRdyGrp &= ptcb-OSTCBBitY; ptcb-OSTCBDly = 0; ptcb-OSTCBStat = OS_ST
28、AT_RDY; OSTaskDel的代碼如下。不能在中斷中刪除任務 不能刪除空閑任務 任務優(yōu)先級非法 將任務從就緒表中刪除 獲得當前任務優(yōu)先級 獲得要刪除任務的TCB 任務的結束任務的結束| C/OS-II微小內核分析微小內核分析刪除任務刪除任務 OSTCBPrioTblprio = (OS_TCB *)0; if (ptcb-OSTCBPrev = (OS_TCB *)0) ptcb-OSTCBNext-OSTCBPrev = (OS_TCB *)0; OSTCBList = ptcb-OSTCBNext; else ptcb-OSTCBPrev-OSTCBNext = ptcb-OSTCB
29、Next; 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);在索引表中刪除本任務從已使用的任務控制塊鏈表中刪除對應的任務控制塊 加到空閑任務控制塊中 任務調度 C/OS-II微小內核分析微小內核分析信號量信號量12345事件與信號量事件與信號量 事件控制塊事件
30、控制塊 改進的任務控制塊及任務刪除函數(shù)改進的任務控制塊及任務刪除函數(shù) 改進的改進的OS初始化初始化 信號量管理信號量管理 6刪除信號量刪除信號量 信號量信號量| C/OS-II微小內核分析微小內核分析事件與信號量事件與信號量 在嵌入式實時多任務系統(tǒng)中,為了使系統(tǒng)達到高效處理和快速響應的目的,于是大量采用“事件驅動”的方式來編寫任務。而事件可能是外部的,比如外部設備中斷;也可能是嵌入式系統(tǒng)內部產生的,比如一個任務給另一個任務發(fā)送信號量或消息。由此可見,用于任務同步和通信的信號量、消息郵箱、消息隊列和互斥信號量都叫做“事件”。 事件信號量(Sem)消息郵箱(Mbox)消息隊列(Q)互斥信號量(Mu
31、tex)信號量信號量| C/OS-II微小內核分析微小內核分析事件與信號量事件與信號量 我們知道酒店的桌子數(shù)是固定的,因此可以這樣理解其最大桌子數(shù)就是計數(shù)器的初值,假設一人占用一張桌子,因此每進去一人,計數(shù)器就會自動減1,而只有出去一人時計數(shù)器才會自動加1。即就是說,如果計數(shù)器大于0,就可以進去吃飯,否則只好等待有人出來才能進去,這種計數(shù)信號就是信號量。酒店酒店人計數(shù)器計數(shù)器(能容納的人數(shù))(能容納的人數(shù))3 2 1 0人人人禁止其它客人進入人沒有空位,不能再容納客人有空位,能再容納1位客人信號量信號量| C/OS-II微小內核分析微小內核分析事件與信號量事件與信號量 信號量就像通行證,且通行
32、證的數(shù)目是有限的,任務要運行下去就必須先拿到通行證。如果信號量已被別的任務占用,那么該任務只能被掛起,直到信號量被當前使用者釋放為止。 信號量的值可以是0到255、0到65535或0到4294967295,取決于信號量規(guī)約機制使用的是8位、16位還是32位。到底是幾位,實際上取決于用的是哪種內核。對于C/OS-II來說,信號量使用16位,其取值范圍為065535。一般地說,對信號量只能實施3種操作:建立信號量(初始化)、等待信號量(掛起)、發(fā)送信號量。注意:信號量初始化時一定要給信號量賦初值,并將等待信號量任務列表清空。操作信號量建立信號量等待信號量發(fā)送信號量OSSemPend()OSSemC
33、reate()OSSemPost()信號量信號量| C/OS-II微小內核分析微小內核分析事件控制塊事件控制塊 C/OS-II將信號量、互斥信號量、消息郵箱、消息隊列等統(tǒng)稱為“事件事件”,然后通過一個稱為“事件控制塊(ECB)”的數(shù)據(jù)結構來管理事件,也就是說,任務和中斷服務程序可以通過ECB向另外的任務程序發(fā)送信號,任務也可以等待另一個任務或者中斷服務程序給它發(fā)送信號。事件控制塊的結構如下圖所示。信號量的計數(shù)器或互斥信號量和優(yōu)先級繼承的計數(shù)器事件類型指向郵箱或消息隊列的指針等待任務列表信號量信號量| C/OS-II微小內核分析微小內核分析事件控制塊事件控制塊事件控制塊的定義如下所示。 type
34、def struct INT8U OSEventType; INT16U OSEventCnt; void *OSEventPtr; INT8U OSEventGrp; INT8U OSEventTblOS_EVENT_TBL_SIZE; OS_EVENT;OSEventType定義了事件的具體類型。在C/OS-II 微小內核中只能為OS_EVENT_SEM(信號量)和OS_EVENT_TYPE_UNUSED(未分配)。當然,在完整版的C/OS-II還可以是OS_EVENT_TYPE_MBOX(消息郵箱)、OS_EVENT_TYPE_Q(消息隊列)和OS_EVENT_TYPE_MUTEX(互斥
35、信號量)。當事件控制塊用于信號量時,OSEventCnt用作信號量的計數(shù)器;當事件控制塊用于互斥信號量時,互斥信號量和優(yōu)先級繼承優(yōu)先級的計數(shù)器。OSEventPtr指針只有在所定義的事件是郵箱或者消息隊列時才使用。當所定義的事件是郵箱時,它指向一個消息;而當所定義的事件是消息隊列時,它指向消息隊列控制塊。當然,空閑事件控制塊鏈表也用它做鏈表指針。它們共同構成事件控制塊的等待任務列表。 信號量信號量| C/OS-II微小內核分析微小內核分析事件控制塊事件控制塊 對于等待事件任務的記錄, COS-II采用了與任務就緒表類似的方法,使用一個INT8U類型的數(shù)組OSEventTbl作為記錄等待事件任務
36、的記錄表,這個表叫等待任務表,如下圖所示。索引表,非必須的,為加快處理速度而引入根據(jù)任務的優(yōu)先級可以確定該任務在等待任務列表中的確切位置真正的等待任務列表 OSEventTbl雖然被定義為“字節(jié)數(shù)組”,但仍被看作是“位數(shù)組”,即每一位代表一個任務,其中任何一位為1表示對應的任務為事件的等待任務,否則不是等待任務。等待任務表OSEventTbl數(shù)組的大小取決于OS_LOWEST_PRIO的值確定事件的等待任務在OSEventTblOS_LOWEST_PRIO/8+1中的位置,即橫坐標X確定變量OSEventGrp具體數(shù)據(jù)位,用于確定等待任務表數(shù)組元素的下標,即縱坐標Y信號量信號量| C/OS-I
37、I微小內核分析微小內核分析事件控制塊事件控制塊 下面將給出一個任務放到事件的等待任務列表中的代碼和從等待任務列表中刪除一個任務的代碼,需要說明的是,OS_EVENT_TBL_SIZE被定義為(OS_LOWEST_PRIO) / 8 + 1)。1、將任務加入等待任務列表2、從等待任務列表中刪除任務pevent-OSEventGrp |= OSMapTblprio 3;pevent-OSEventTblprio 3 |= OSMapTblprio & 0 x07;if (pevent-OSEventTblprio 3 &= OSMapTblprio & 0 x07) = 0) pevent-OSE
38、ventGrp &= OSMapTblprio 3;信號量信號量| C/OS-II微小內核分析微小內核分析事件控制塊事件控制塊INT8U const OSUnMapTbl = /0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/*0 x00 to 0 x0F*/ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/*0 x10 to 0 x1F*/ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1,
39、 0, 2, 0, 1, 0,/*0 x20 to 0 x2F*/ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/*0 x30 to 0 x3F*/ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/*0 x40 to 0 x4F*/ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/*0 x50 to 0 x5F*/ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/*0 x60 to 0 x6F*/ 4,
40、 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/*0 x70 to 0 x7F*/ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/*0 x80 to 0 x8F*/ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/*0 x90 to 0 x9F*/ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/*0 xA0 to 0 xAF*/ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,
41、 0, 1, 0,/*0 xB0 to 0 xBF*/ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/*0 xC0 to 0 xCF*/ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/*0 xD0 to 0 xDF*/ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,/*0 xE0 to 0 xEF*/ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0/*0 xF0 to 0 xFF*/;若OSRdyGrp
42、為0 x68,以此值為偏移量查表得y值為3若OSRdyTb1y為0 x30,以此值為偏移量表得x值為2就緒任務組優(yōu)先級最高的就是26(3OSEventGrp;x = OSUnMapTblpevent-OSEventTbly;prio = (y 0) & (OS_MAX_EVENTS 0)#if (OS_MAX_EVENTS 1) INT16U i; OS_EVENT *pevent1; OS_EVENT *pevent2; pevent1 = &OSEventTbl0; pevent2 = &OSEventTbl1; for (i = 0; i OSEventType = OS_EVENT_T
43、YPE_UNUSED; pevent1-OSEventPtr = pevent2; pevent1+; pevent2+; pevent1-OSEventType = OS_EVENT_TYPE_UNUSED; pevent1-OSEventPtr = (OS_EVENT *)0; OSEventFreeList = &OSEventTbl0;#else OSEventFreeList = &OSEventTbl0; OSEventFreeList-OSEventType = OS_EVENT_TYPE_UNUSED; OSEventFreeList-OSEventPtr = (OS_EVEN
44、T *)0;#endif#endif 空閑事件控制塊鏈表初始化代碼如下。當有多個事件時,執(zhí)行下面代碼把所有空閑事件控制塊的類型設置為“未分配”鏈表尾指針指向“NULL”鏈表頭指針指向第一個空閑任務塊只有一個任務控制塊時的處理程序信號量信號量| C/OS-II微小內核分析微小內核分析事件控制塊事件控制塊使等待超時的任務進入就緒態(tài)使任務進入等待狀態(tài)初始化事件控制塊使等待事件的任務進入就緒態(tài)對于事件控制塊有一些通用的操作,如下圖所示。 為了避免代碼重復和減短程序代碼長度,C/OS-II將上面的操作用4個系統(tǒng)函數(shù)來實現(xiàn),它們分別是:OS_EventWaitListInit(),OS_EventTask
45、Rdy(),OS_EventTaskWait()和OS_EventTO(),下面將分別逐一介紹。信號量信號量| C/OS-II微小內核分析微小內核分析事件控制塊事件控制塊1、初始化事件控制塊 當建立一個信號量、互斥信號量、消息郵箱或消息隊列時,需要對事件控制塊中的等待任務列表進行初始化,這是通過調用函數(shù)OS_EventWaitListInit()來實現(xiàn)的。 由上面的分析可知,讓等待任務列表沒有任何任務就是將事件控制塊(ECB)的OSEventGrp成員和OSEventTbl的所有成員賦值為0。 信號量信號量| C/OS-II微小內核分析微小內核分析事件控制塊事件控制塊void OS_Event
46、WaitListInit (OS_EVENT *pevent) INT8U *ptbl; pevent-OSEventGrp = 0 x00; ptbl = &pevent-OSEventTbl0;#if OS_EVENT_TBL_SIZE 0 *ptbl+ = 0 x00;#endif OS_EventWaitListInit的源代碼如下。將OSEventGrp賦值為0將OSEventTbl的所有成員賦值為0信號量信號量| C/OS-II微小內核分析微小內核分析事件控制塊事件控制塊2、使任務進入等待狀態(tài) 當某個任務要等待一個事件的發(fā)生時,需要將任務從就緒任務表中刪除,并放到相應事件的事件控制
47、塊的等待任務表中,這些操作是通過調用函數(shù)OS_EventTaskWait()來實現(xiàn)的。信號量信號量| C/OS-II微小內核分析微小內核分析事件控制塊事件控制塊void OS_EventTaskWait (OS_EVENT *pevent) OSTCBCur-OSTCBEventPtr = pevent; if (OSRdyTblOSTCBCur-OSTCBY &= OSTCBCur-OSTCBBitX) = 0 x00) OSRdyGrp &= OSTCBCur-OSTCBBitY; pevent-OSEventTblOSTCBCur-OSTCBY |= OSTCBCur-OSTCBBitX
48、; pevent-OSEventGrp |= OSTCBCur-OSTCBBitY;OS_EventTaskWait的源代碼如下。指明任務等待的事件從就緒表中刪除當前任務將當前任務加入到等待任務列表中信號量信號量| C/OS-II微小內核分析微小內核分析事件控制塊事件控制塊3、使等待事件的任務進入就緒態(tài) 當發(fā)生了某個事件時,需要將等待這個事件的任務中優(yōu)先級最高的一個置于就緒態(tài),這是通過調用函數(shù)OS_EventTaskRdy()來實現(xiàn)的。在C/OS-II中,TCB的成員OSTCBStat不同的位表示等待不同的事件,則不同事件處理程序調用函數(shù)OS_EventTaskRdy()時,需要清除OSTCB
49、Stat不同位,則需要一個指示,就是參數(shù)msk。當然,C/OS-II微小內核只有一個事件,理論上不需要這個參數(shù),保留它是為了使微小內核的代碼最大限度與原版保持一致。 信號量信號量| C/OS-II微小內核分析微小內核分析事件控制塊事件控制塊INT8U OS_EventTaskRdy(OS_EVENT *pevent, void *msg, INT8U msk) y = OSUnMapTblpevent-OSEventGrp; bity = OSMapTbly; x = OSUnMapTblpevent-OSEventTbly; bitx = OSMapTblx; prio = (INT8U)(
50、y OSEventTbly &= bitx) = 0 x00) pevent-OSEventGrp &= bity; ptcb = OSTCBPrioTblprio; ptcb-OSTCBDly = 0; ptcb-OSTCBEventPtr = (OS_EVENT *)0; ptcb-OSTCBStat &= msk; if (ptcb-OSTCBStat = OS_STAT_RDY) OSRdyGrp |= bity; OSRdyTbly |= bitx; return (prio);OS_EventTaskRdy的源代代碼如下。準備公共中間變量獲得任務優(yōu)先級從等待任務列表中刪除任務獲得任
51、務TCB將任務加入就緒表中任務不再等待事件任務不再需要等待超時指針指向NULL信號量信號量| C/OS-II微小內核分析微小內核分析事件控制塊事件控制塊4、使等待超時的任務進入就緒態(tài) 在C/OS-II中,任務等待某個事件時可以指定超時時間,如果超時時間到了,指定的事件仍然沒有到來,任務也會被時鐘節(jié)拍處理函數(shù)OSTimeTick()設置為就緒態(tài)。此時,等待任務列表中仍然保存這個任務,任務控制塊中也仍然有一些變量沒有恢復,這些未完的事情由函數(shù)OS_EventTO()處理。信號量信號量| C/OS-II微小內核分析微小內核分析事件控制塊事件控制塊void OS_EventTO (OS_EVENT *
52、pevent) if (pevent-OSEventTblOSTCBCur-OSTCBY &= OSTCBCur-OSTCBBitX) = 0 x00) pevent-OSEventGrp &= OSTCBCur-OSTCBBitY; OSTCBCur-OSTCBStat = OS_STAT_RDY; OSTCBCur-OSTCBEventPtr = (OS_EVENT *)0;OS_EventTO的源代碼如下。任務狀態(tài)設置為就緒態(tài)事件控制塊指針指向NULL從等待任務列表中刪除任務信號量信號量| C/OS-II微小內核分析微小內核分析改進的任務控制塊及任務刪除函數(shù)改進的任務控制塊及任務刪除函數(shù)
53、 有了事件支持之后,刪除任務時就要特別小心了。當一個任務在等待事件時可能被別的任務刪除,此時盡管任務已經刪除,但任務還保存在事件的等待任務列表中。當對應的事件到來之時,會將這個已經不存在(或者說睡眠態(tài))的任務設置為就緒態(tài),這顯然是不可能的。如果在事件來臨之前又建立了另一個優(yōu)先級相同任務,則程序執(zhí)行的結果顯然是錯誤的。 因此,刪除任務時必須將任務從它等待事件的等待任務列表中刪除。信號量信號量| C/OS-II微小內核分析微小內核分析改進的任務控制塊及任務刪除函數(shù)改進的任務控制塊及任務刪除函數(shù) 由于在C/OS-II中,一個任務同一時間只能等待一個事件,所以在任務控制塊中增加一個指向其所等待的事件的
54、指針,實現(xiàn)這個功能就很簡單了。改進后的任務控制塊如下所示。Typedef struct os_tcb OS_EVENT *OSTCBEventPtr;OS_TCB;增加的成員,指向任務等待的事件信號量信號量| C/OS-II微小內核分析微小內核分析改進的任務控制塊及任務刪除函數(shù)改進的任務控制塊及任務刪除函數(shù) 當使用OSTCBEventPtr這個成員后,任務的刪除函數(shù)也相應地得到了改進。改進的任務刪除函數(shù)代碼如下所示。 INT8U OSTaskDel (INT8U prio)#if OS_EVENT_EN 0 OS_EVENT *pevent;#endif #if OS_EVENT_EN 0 p
55、event = ptcb-OSTCBEventPtr; if (pevent != (OS_EVENT *)0) if (pevent-OSEventTblptcb-OSTCBY &= ptcb-OSTCBBitX) = 0) pevent-OSEventGrp &= ptcb-OSTCBBitY; #endif增加的代碼,從事件的等待任務列表中刪除任務信號量信號量| C/OS-II微小內核分析微小內核分析改進的改進的OS初始化初始化 在使用事件控制塊之前,需要將所有事件控制塊鏈接成一個空閑事件控制塊鏈表,則可以通過調用函數(shù)OS_InitEventList()來實現(xiàn)。從理論上來講,只要在使用事
56、件控制塊之前調用函數(shù)OS_InitEventList()即可,但實際上在操作系統(tǒng)初始化時調用比較方便和可靠。這樣操作系統(tǒng)初始化函數(shù)OSInit()就需要添加對OS_InitEventList()的調用,改進的OS初始化代碼如下所示。void OSInit (void) OS_InitMisc(); OS_InitRdyList(); OS_InitTCBList(); OS_InitTaskIdle(); OS_InitEventList();增加的函數(shù),將所有事件控制塊鏈接成一個空閑事件控制塊鏈表信號量信號量| C/OS-II微小內核分析微小內核分析信號量管理信號量管理 只要C/OS-II支
57、持信號量,就必須有3種操作:創(chuàng)建信號量OSSemCreate()、發(fā)送信號量OSSemPost()和等待信號量OSSemPend() 。 操作信號量 建立信號量OSSemCreate() 等待信號量OSSemPend()發(fā)送信號量OSSemPost()信號量信號量| C/OS-II微小內核分析微小內核分析信號量管理信號量管理OSSemCreate函數(shù)1、創(chuàng)建信號量 在使用信號量之前,必須通過調用函數(shù)OSSemCreate()來創(chuàng)建一個信號量,函數(shù)OSSemCreate()只有唯一的參數(shù)cnt,用于初始化信號量的計數(shù)器初始值,創(chuàng)建信號量函數(shù)OSSemCreate()將返回一個指針,用于識別不同的
58、信號量 。信號量信號量| C/OS-II微小內核分析微小內核分析信號量管理信號量管理建立信號量的流程圖如下所示。信號量信號量| C/OS-II微小內核分析微小內核分析信號量管理信號量管理OSSemCreate的源代碼如下所示。OS_EVENT *OSSemCreate (INT16U cnt) OS_EVENT *pevent; if (OSIntNesting 0) return (OS_EVENT *)0); OS_ENTER_CRITICAL(); pevent = OSEventFreeList; if (OSEventFreeList != (OS_EVENT *)0) OSEven
59、tFreeList = (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);不允許在中斷服務程序中創(chuàng)建信號量 獲得空閑事件控制塊 將事件類型設置為信號量 給信號量計數(shù)器賦初值 非必須的代碼
60、初始化等待任務列表 信號量信號量| C/OS-II微小內核分析微小內核分析信號量管理信號量管理2、等待信號量 等待信號量是通過調用函數(shù)OSSemPend()來實現(xiàn)的。OSSemPend函數(shù)信號量信號量| C/OS-II微小內核分析微小內核分析信號量管理信號量管理等待信號量的流程圖如下所示。信號量信號量| C/OS-II微小內核分析微小內核分析信號量管理信號量管理OSSemPend的源代碼如下所示。void OSSemPend (OS_EVENT *pevent, INT16U timeout, INT8U *err) if (OSIntNesting 0) *err = OS_ERR_PEND
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 航空公司疫情防控服務方案
- 發(fā)行預付費電話卡行業(yè)營銷策略方案
- 水泥熟料及水泥相關行業(yè)投資方案
- 氫能開發(fā)行業(yè)營銷策略方案
- 慶祝中秋節(jié)的活動方案
- 有線電視節(jié)目播放行業(yè)營銷策略方案
- 保護環(huán)境從我做起的演講稿
- 中秋佳節(jié)致辭范文(15篇)
- 人生大事觀后感(19篇)
- 為開學典禮的致辭(25篇)
- MT99XX測試機的維修報告畢業(yè)設計
- 2022-2023學年南寧市西鄉(xiāng)塘區(qū)數(shù)學五下期末聯(lián)考試題含解析
- 土壤學教材課件
- 新聞采訪與寫作課件第十四章特寫寫作
- 漢英翻譯教程
- QC成果提高混凝土攪拌機計量合格率
- 堅持總體國家安全觀走中國特色強軍之路模板課件
- 礦井火災防治安全技術措施
- 騰訊秘書職業(yè)發(fā)展規(guī)劃書
- 線纜敷設隱蔽驗收記錄
- GB/T 36344-2018信息技術數(shù)據(jù)質量評價指標
評論
0/150
提交評論