版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
嵌入式技術及應用——ARM與C/OS-Ⅱ五、C/OS-Ⅱ操作系統(tǒng)12中斷和時間管理任務之間的通信與同步中斷處理中斷:由于某種事件的發(fā)生而導致程序流程的改變。產(chǎn)生中斷的事件稱為中斷源。CPU響應中斷的條件:至少有一個中斷源向CPU發(fā)出中斷信號;系統(tǒng)允許中斷,且對此中斷信號未予屏蔽。中斷的分類
分類方式硬件中斷是否可以被屏蔽:可屏蔽中斷和不可屏蔽中斷
中斷源:硬件中斷和軟件中斷
中斷信號的產(chǎn)生:邊緣觸發(fā)中斷和電平觸發(fā)中斷
中斷服務程序的調用方式:向量中斷、直接中斷和間接中斷
可屏蔽中斷和不可屏蔽中斷由于中斷的發(fā)生是異步的,程序的正常執(zhí)行流程隨時有可能被中斷服務程序打斷。如果程序正在進行某些重要運算,中斷服務程序的插入將有可能改變某些寄存器的數(shù)據(jù),造成程序的運行發(fā)生錯誤??善帘沃袛啵耗軌虮黄帘蔚舻闹袛唷M獠吭O備的中斷請求信號一般需要先通過CPU外部的中斷控制器,再與CPU相應的引腳相連??删幊讨袛嗫刂破骺梢酝ㄟ^軟件進行控制,以禁止或是允許中斷。不可屏蔽中斷:在任何時候都不可屏蔽的。一個比較典型的例子是掉電中斷,當發(fā)生掉電時,無論程序正在進行什么樣的運算,它都肯定無法正常運行下去。這種情況下,急需進行的是一些掉電保護的操作。對這類中斷,應隨時進行響應。硬件中斷和軟件中斷硬件中斷:由于CPU外部的設備所產(chǎn)生的中斷。異步事件:可能在程序執(zhí)行的任何位置發(fā)生,發(fā)生中斷的時間通常是不確定的。軟件中斷:同步中斷或是自陷,通過處理器的軟件指令來實現(xiàn)。產(chǎn)生中斷的時機是預知的,可根據(jù)需要在程序中進行設定。軟件中斷的處理程序以同步的方式進行執(zhí)行。其處理方式同硬件中斷處理程序類似。硬件中斷和軟件中斷軟件中斷是一種非常重要的機制:系統(tǒng)可通過該機制在用戶模式執(zhí)行特權模式下的操作。是軟件調試的一個重要手段,如Intel80x86中的INT3,使指令進行單步執(zhí)行,調試器可以用它來形成觀察點,并查看隨程序執(zhí)行而動態(tài)變化的事件情況。邊緣觸發(fā)中斷和電平觸發(fā)中斷邊緣觸發(fā)中斷:中斷線從低變到高或是從高變到低時,中斷信號就被發(fā)送出去,并只有在下一次的從低變到高或是從高變到低時才會再度觸發(fā)中斷。事件發(fā)生的時間非常短,有可能出現(xiàn)中斷控制器丟失中斷的情況。如果多個設備連接到同一個中斷線,即使只有一個設備產(chǎn)生了中斷信號,也必須調用中斷線對應的所有中斷服務程序來進行匹配,否則會出現(xiàn)中斷的軟件丟失情況。邊緣觸發(fā)中斷和電平觸發(fā)中斷電平觸發(fā)中斷:在硬件中斷線的電平發(fā)生變化時產(chǎn)生中斷信號,并且中斷信號的有效性將持續(xù)保持下去,直到中斷信號被清除。能夠降低中斷信號傳送丟失的情況能通過更有效的方式來服務中斷,每個為該中斷服務后的ISR都要向外圍設備進行確認,然后取消該設備對中斷線的操作。當中斷線的最后一個設備得到中斷服務后,中斷線的電平就會發(fā)生變化,不用對連接到同一個硬件中斷線的所有中斷服務程序進行嘗試。向量中斷、直接中斷和間接中斷向量中斷:通過中斷向量來調用中斷服務程序。直接中斷:中斷對應的中斷服務程序的入口地址是一個固定值,當中斷發(fā)生的時候,程序執(zhí)行流程將直接跳轉到中斷服務程序的入口地址,執(zhí)行中斷服務程序。間接中斷:中斷服務程序的入口地址由寄存器提供。向量中斷中斷硬件設備的硬件中斷線(也稱為中斷請求IRQ)被中斷控制器匯集成中斷向量(interruptvector);每個中斷向量對應一個中斷服務程序(interruptserviceroutine,ISR),用來存放中斷服務程序的入口地址或是中斷服務程序的第一條指令。系統(tǒng)中通常包含多個中斷向量,存放這些中斷向量對應中斷服務程序入口地址的內(nèi)存區(qū)域被稱為中斷向量表。向量中斷在Intel80x86處理器中,中斷向量表包含256個入口,每個中斷向量需要四個字節(jié)(存放中斷服務程序的首址)。ARM的中斷向量表開始于內(nèi)存地址0x00000000或是0xFFFF0000處。5.1.2中斷服務程序ISR中斷一旦被識別,CPU會保存部分(或全部)運行上下文(context,即寄存器的值),然后跳轉到專門的子程序去處理此次事件,稱為中斷服務子程序(ISR)。μC/OS-Ⅱ中,中斷服務子程序要用匯編語言來編寫,然而,如果用戶使用的C語言編譯器支持在線匯編語言的話(混編),用戶可以直接將中斷服務子程序代碼放在C語言的程序文件中。(1)保存全部CPU寄存器的值;(2)調用OSIntEnter(),或直接把全局變量OSIntNesting(中斷嵌套層次)加1;(3)執(zhí)行用戶代碼做中斷服務;(4)調用OSIntExit();(5)恢復所有CPU寄存器;(6)執(zhí)行中斷返回指令。用戶ISR的框架(服務過程)5.1.3相關函數(shù)介紹OSIntEnter()/*在調用本函數(shù)之前必須先將中斷關閉*/voidOSIntEnter(void){if(OSRunning==TRUE){if(OSIntNesting<255){OSIntNesting++;}}}OSIntExit的意義OSIntExit()voidOSIntExit(void){OS_ENTER_CRITICAL();//關中斷if((--OSIntNesting|OSLockNesting)==0)//判斷嵌套是否為零{//把高優(yōu)先級任務裝入OSIntExitY=OSUnMapTbl[OSRdyGrp];OSPrioHighRdy=(INT8U)((OSIntExitY<<3)+OSUnMapTbl[OSRdyTbl[OSIntExitY]]);if(OSPrioHighRdy!=OSPrioCur){OSTCBHighRdy=
OSTCBPrioTbl[OSPrioHighRdy];OSCtxSwCtr++;
OSIntCtxSw();}}OS_EXIT_CRITICAL();//開中斷返回}OSIntCtxSw()在任務切換時,為什么使用OSIntCtxSw()而不是調度函數(shù)中的OS_TASK_SW()?原因有二點一半的任務切換工作,即CPU寄存器入棧,已經(jīng)在前面做完了;需要保證所有被掛起任務的棧結構是一樣的。OSIntExit的關鍵——OSIntCtxSw實現(xiàn)中斷級的任務切換ARM在棧指針調整過程中的優(yōu)勢為了實現(xiàn)資源共享,一個操作系統(tǒng)必須提供臨界區(qū)操作的功能;μC/OS采用關閉/打開中斷的方式來處理臨界區(qū)代碼,從而避免競爭條件,實現(xiàn)任務間的互斥;
μC/OS定義兩個宏(macros)來開關中斷,即:OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL();這兩個宏的定義取決于所用的微處理器,每種微處理器都有自己的OS_CPU.H文件。
...
OS_ENTER_CRITICAL();任務1的臨界區(qū)代碼;OS_EXIT_CRITICAL();...任務1任務2...
OS_ENTER_CRITICAL();任務2的臨界區(qū)代碼;OS_EXIT_CRITICAL();...臨界資源當處理臨界段代碼時,需要關中斷,處理完畢后,再開中斷;關中斷時間是實時內(nèi)核最重要的指標之一;在實際應用中,關中斷的時間很大程度中取決于微處理器的結構和編譯器生成的代碼質量;C/OS-II定義兩個宏開關中斷:OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL();C/OS-II中開關中斷的方法OS_CRITICAL_METHOD==1用處理器指令關中斷,執(zhí)行OS_ENTER_CRITICAL(),開中斷執(zhí)行OS_EXIT_CRITICAL();OS_CRITICAL_METHOD==2實現(xiàn)OS_ENTER_CRITICAL()時,先在堆棧中保存中斷的開/關狀態(tài),然后再關中斷;實現(xiàn)OS_EXIT_CRITICAL()時,從堆棧中彈出原來中斷的開/關狀態(tài);OS_CRITICAL_METHOD==3把當前處理器的狀態(tài)字保存在局部變量中(如OS_CPU_SR,關中斷時保存,開中斷時恢復C/OS-II中采用了3種開關中斷的方法Intel80x86實模式下中斷的打開與關閉;方法1#defineOS_ENTER_CRITICAL()asmCLI#defineOS_EXIT_CRITICAL()asmSTI方法2#defineOS_ENTER_CRITICAL()asm{PUSHF;CLI}#defineOS_EXIT_CRITICAL()asmPOPF時間管理時間管理一般具有以下功能:維持日歷時間;任務有限等待的計時;軟定時器的定時管理;維持系統(tǒng)時間片輪轉調度。
硬件時鐘設備
大多數(shù)嵌入式系統(tǒng)有兩種時鐘源:實時時鐘(realtimeclock,RTC)定時器/計數(shù)器實時時鐘:一般靠電池供電,即使系統(tǒng)斷電,也可以維持日期和時間。實時時鐘獨立于操作系統(tǒng),所以也被稱為硬件時鐘,為整個系統(tǒng)提供一個計時標準。定時器/計數(shù)器:實時內(nèi)核需要一個定時器作為系統(tǒng)時鐘(或稱OS時鐘),并由實時內(nèi)核控制系統(tǒng)時鐘工作。一般情況下,系統(tǒng)時鐘的最小刻度是由應用和操作系統(tǒng)的特點決定的。硬件時鐘設備在不同的操作系統(tǒng)中,實時時鐘和系統(tǒng)時鐘之間的關系是不同的。實時時鐘和系統(tǒng)時鐘之間的關系通常也被稱作操作系統(tǒng)的時鐘運作機制。一般來說,實時時鐘是系統(tǒng)時鐘的時間基準,實時內(nèi)核通過讀取實時時鐘來初始化系統(tǒng)時鐘,此后二者保持同步運行,共同維系系統(tǒng)時間。系統(tǒng)時鐘并不是本質意義上的時鐘,只有當系統(tǒng)運行起來以后才有效,并且由實時內(nèi)核完全控制。時鐘節(jié)拍時鐘節(jié)拍是一種特殊的中斷,相當于操作系統(tǒng)的心臟起搏器;μC/OS需要用戶提供周期性信號源,用于實現(xiàn)時間延時和確認超時。節(jié)拍率應在10到100Hz之間,時鐘節(jié)拍率越高,系統(tǒng)的額外負荷就越重;時鐘節(jié)拍的實際頻率取決于用戶應用程序的精度。時鐘節(jié)拍源可以是專門的硬件定時器,或是來自50/60Hz交流電源的信號。時間管理與時間管理相關的系統(tǒng)服務:OSTimeDLY()OSTimeDLYHMSM()OSTimeDlyResmue()OStimeGet()OSTimeSet()OSTimeDLY()OSTimeDLY():任務延時函數(shù),申請該服務的任務可以延時一段時間;調用OSTimeDLY后,任務進入等待狀態(tài);使用方法voidOSTimeDly(INT16Uticks);ticks表示需要延時的時間長度,用時鐘節(jié)拍的個數(shù)來表示。OSTimeDLY()voidOSTimeDly(INT16Uticks){if(ticks>0){OS_ENTER_CRITICAL();if((OSRdyTbl[OSTCBCur->OSTCBY]&=~OSTCBCur->OSTCBBitX)==0){OSRdyGrp&=~OSTCBCur->OSTCBBitY;}OSTCBCur->OSTCBDly=ticks;OS_EXIT_CRITICAL();OSSched();}}OSTimeDLY(1)的問題OSTimeDlyHMSM()OSTimeDlyHMSM():OSTimeDly()的另一個版本,即按時分秒延時函數(shù);使用方法INT8UOSTimeDlyHMSM(
INT8Uhours,//小時
INT8Uminutes,//分鐘
INT8Useconds,//秒
INT16Umilli//毫秒
);OSTimeDlyResume()OSTimeDlyResume():讓處在延時期的任務提前結束延時,進入就緒狀態(tài);使用方法INT8UOSTimeDlyResume(INT8U
prio);prio表示需要提前結束延時的任務的優(yōu)先級/任務ID。系統(tǒng)時間每隔一個時鐘節(jié)拍,發(fā)生一個時鐘中斷,將一個32位的計數(shù)器OSTime加1;該計數(shù)器在用戶調用OSStart()初始化多任務和4,294,967,295個節(jié)拍執(zhí)行完一遍的時候從0開始計數(shù)。若時鐘節(jié)拍的頻率等于100Hz,該計數(shù)器每隔497天就重新開始計數(shù);OSTimeGet():獲得該計數(shù)器的當前值;INT32UOSTimeGet(void);OSTimeSet():設置該計數(shù)器的值。voidOSTimeSet(INT32Uticks);watchdog軟件定時器可用于實現(xiàn)“看門狗”在應用的某個地方進行軟件定時器的停止計時操作,確保定時器在系統(tǒng)正常運行的情況下不會到期,即不會觸發(fā)定時器服務例程;如果某個時候系統(tǒng)進入了定時器服務例程,就表示使用停止計時操作的地方?jīng)]有執(zhí)行到,系統(tǒng)出現(xiàn)了錯誤。何時啟動系統(tǒng)定時器如果在OSStart之前啟動定時器,則系統(tǒng)可能無法正確執(zhí)行完OSStartHighRdyOSStart函數(shù)直接調用OSStartHighRdy去執(zhí)行最高優(yōu)先級的任務,OSStart不返回。系統(tǒng)定時器應該在系統(tǒng)的最高優(yōu)先級任務中啟動使用OSRunning變量來控制操作系統(tǒng)的運行在我們的移植版本中,使用了uCOS-II中的保留任務1作為系統(tǒng)任務。負責啟動定時器時鐘節(jié)拍的啟動用戶必須在多任務系統(tǒng)啟動以后再開啟時鐘節(jié)拍器,也就是在調用OSStart()之后;在調用OSStart()之后做的第一件事是初始化定時器中斷。voidmain(void){...OSInit();/*初始化uC/OS-II*//*應用程序初始化代碼...*//*調用OSTaskCreate()創(chuàng)建至少一個任務*/
允許時鐘節(jié)拍中斷;/*錯誤!可能crash!*/OSStart();/*開始多任務調度*/}12中斷和時間管理任務之間的通信與同步概述多任務系統(tǒng)中任務之間的關系相互獨立僅競爭CPU資源競爭除CPU外的其他資源(互斥)同步協(xié)調彼此運行的步調通信彼此間傳遞數(shù)據(jù)或信息,以協(xié)同完成某項工作任務能以以下方式與中斷處理程序或其他任務進行同步或通信:單向同步或通信:一個任務與另一個任務或一個ISR同步或通信。雙向同步或通信:兩個任務相互同步或通信。雙向同步不能在任務與ISR之間進行,因為ISR不能等待。TaskxTaskyPOSTPENDISRxTaskyPOSTPENDTaskxTaskyPOSTPENDPOSTPEND任務與任務之間的同步(單向)任務與ISR之間的同步(單向)任務與任務之間的同步(雙向)任務間通信與同步任務間通信的管理:事件控制塊ECB;同步與互斥臨界區(qū)(CriticalSections);信號量(Semaphores);任務間通信郵箱(MessageMailboxes);消息隊列(MessageQueues)。事件控制塊ECBECB數(shù)據(jù)結構typedefstruct{void*OSEventPtr;/*指向消息或消息隊列的指針*/INT8UOSEventTbl[OS_EVENT_TBL_SIZE];//等待任務列表INT16UOSEventCnt;/*計數(shù)器(當事件是信號量時)*/INT8UOSEventType;/*事件類型:信號量、郵箱等*/INT8UOSEventGrp;/*等待任務組*/}OS_EVENT;
與TCB類似的結構,使用兩個鏈表,空閑鏈表與使用鏈表所有的通信信號都被看成是事件(event),C/OS-II通過事件控制塊(ECB)來管理每一個具體事件。事件控制塊ECB數(shù)據(jù)結構2017654310891514131211181617232221201926242531302928273432333938373635424041474645444350484955545352515856576362616059·OSRdyTbl[8]·OSEventGrp·OSEventPtr·OSEventCnt·OSEventTypepreventOS_Event等待任務列表每個正在等待某個事件的任務被加入到該事件的ECB的等待任務列表中,該列表包含兩個變量OSEventGrp和OSEventTbl[]。在OSEventGrp中,任務按優(yōu)先級分組,8個任務為一組,共8組,分別對應OSEventGrp當中的8位。當某組中有任務處于等待該事件的狀態(tài)時,對應的位就被置位。同時,OSEventTbl[]中的相應位也被置位。最低優(yōu)先級任務(即空閑任務,不可能處于等待狀態(tài))565758596061626348495051525354554041424344454647323334353637383924252627282930311617181920212223891011121314150123456701234567[0][1][2][3][4][5][6][7].OSEventGrpOSEventTbl[OS_LOWEST_PRIO/8+1]XY最高優(yōu)先級任務正在等待該事件的任務的優(yōu)先級XXXYYY00任務的優(yōu)先級.OSEventTbl[]中相應位的位置.OSEventGrp中相應位的位置及.OSEventTbl[]中的數(shù)組下標空閑ECB的管理ECB的總數(shù)由用戶所需要的信號量、郵箱和消息隊列的總數(shù)決定,由OS_CFG.H中的#defineOS_MAX_EVENTS定義。在調用OSInit()初始化系統(tǒng)時,所有的ECB被鏈接成一個單向鏈表——空閑事件控制塊鏈表;每當建立一個信號量、郵箱或消息隊列時,就從該鏈表中取出一個空閑事件控制塊,并對它進行初始化。0OS_MAX_EVENTSOSEventFreeListOS_EVENTECB的基本操作OSEventWaitListInit()初始化一個事件控制塊。當創(chuàng)建一個信號量、郵箱或消息隊列時,相應的創(chuàng)建函數(shù)會調用本函數(shù)對ECB的內(nèi)容進行初始化,將OSEventGrp和OSEventTbl[]數(shù)組清零;OSEventWaitListInit(OS_EVENT*pevent);prevent:指向需要初始化的事件控制塊的指針。OSEventTaskRdy()。使一個任務進入就緒態(tài)。當一個事件發(fā)生時,需要將其等待任務列表中的最高優(yōu)先級任務置為就緒態(tài);OSEventTaskRdy(OS_EVENT*pevent,
void*msg,INT8Umsk);msg:指向消息的指針;msk:用于設置TCB的狀態(tài)。ECB的基本操作(續(xù))OSEventTaskWait()使一個任務進入等待狀態(tài)。當某個任務要等待一個事件的發(fā)生時,需要調用本函數(shù)將該任務從就緒任務表中刪除,并放到相應事件的等待任務表中;OSEventTaskWait(OS_EVENT*pevent);OSEventTO()由于等待超時而將任務置為就緒態(tài)。如果一個任務等待的事件在預先指定的時間內(nèi)沒有發(fā)生,需要調用本函數(shù)將該任務從等待列表中刪除,并把它置為就緒狀態(tài);OSEventTO(OS_EVENT*pevent);信號量信號量在多任務系統(tǒng)中的功能實現(xiàn)對共享資源的互斥訪問(包括單個共享資源或多個相同的資源);實現(xiàn)任務之間的行為同步;必須在OS_CFG.H中將OS_SEM_EN開關常量置為1,這樣μC/OS才能支持信號量。信號量的種類信號量一般分為三種:用于解決互斥問題的互斥信號量。它比較特殊,可能會引起優(yōu)先級反轉問題。用于解決同步問題的二值信號量。用于解決資源計數(shù)問題的計數(shù)信號量。將信號量進行種類細分,可以根據(jù)其用途,在具體實現(xiàn)時做專門處理,提高執(zhí)行效率和可靠性。用互斥信號量保護的代碼區(qū)稱作“臨界區(qū)”,臨界區(qū)代碼通常用于對共享資源的訪問?;コ庑盘柫康闹当怀跏蓟?,表明目前沒有任務進入“臨界區(qū)”,但最多只有一個任務可以進入“臨界區(qū)”。第一個試圖進入“臨界區(qū)”的任務將成功獲得互斥信號量,而隨后試圖進入用同一信號量保護的臨界區(qū)的所有其他任務就必須等待。當任務離開“臨界區(qū)”時,它將釋放信號量并允許正在等待該信號量的任務進入“臨界區(qū)”?;コ庑盘柫縏ask1Task2共享資源二值信號量二值信號量主要用于任務與任務之間、任務與中斷服務程序之間的同步用于同步的二值信號量初始值為0,表示同步事件尚未產(chǎn)生;任務申請信號量以等待該同步事件的發(fā)生;另一個任務或ISR到達同步點時,釋放信號量(將其值設置為1)表示同步事件已發(fā)生,以喚醒等待的任務。二值信號量availableunavailableacquire(value=0)release(value=1)Initialvalue=0二值信號量狀態(tài)圖計數(shù)信號量計數(shù)信號量用于控制系統(tǒng)中共享資源的多個實例的使用,允許多個任務同時訪問同一種資源的多個實例計數(shù)信號量被初始化為n(非負整數(shù)),n為該種共享資源的數(shù)目。Task1Task2共享資源實例nTaskm共享資源實例1…………計數(shù)信號量availableunavailableInitialcount>0acquire(count=0)release(count=1)Initialcount=0計數(shù)信號量狀態(tài)圖acquire(count=count-1)release(count=count+1)uC/OS中信號量由兩部分組成:信號量的計數(shù)值(16位無符號整數(shù))和等待該信號量的任務所組成的等待任務表;信號量系統(tǒng)服務OSSemCreate()OSSemPend(),OSSemPost()OSSemAccept(),OSSemQuery()任務、ISR和信號量的關系或任務任務ISROSSemAccept()OSSemPend()OSSemQuery()OSSemPost()OSSemPost()OSSemAccept()OSSemCreate()NN創(chuàng)建一個信號量OSSemCreate()創(chuàng)建一個信號量,并對信號量的初始計數(shù)值賦值,該初始值為0到65,535之間的一個數(shù);OS_EVENT*OSSemCreate(INT16Ucnt);cnt:信號量的初始值。執(zhí)行步驟從空閑事件控制塊鏈表中得到一個ECB;初始化ECB,包括設置信號量的初始值、把等待任務列表清零、設置ECB的事件類型等;返回一個指向該事件控制塊的指針。等待一個信號量OSSemPend()等待一個信號量,即操作系統(tǒng)中的P操作,將信號量的值減1;OSSemPend(OS_EVENT*pevent,
INT16Utimeout,INT8U*err);執(zhí)行步驟如果信號量的計數(shù)值大于0,將它減1并返回;如果信號量的值等于0,則調用本函數(shù)的任務將被阻塞起來,等待另一個任務把它喚醒;調用OSSched()函數(shù),調度下一個最高優(yōu)先級的任務運行。發(fā)送一個信號量OSSemPost()發(fā)送一個信號量,即操作系統(tǒng)中的V操作,將信號量的值加1;OSSemPost(OS_EVENT*pevent);執(zhí)行步驟檢查是否有任務在等待該信號量,如果沒有,將信號量的計數(shù)值加1并返回;如果有,將優(yōu)先級最高的任務從等待任務列表中刪除,并使它進入就緒狀態(tài);調用OSSched(),判斷是否需要進行任務切換。無等待地請求一個信號量OSSemAccept()當一個任務請求一個信號量時,如果該信號量暫時無效,則讓該任務簡單地返回,而不是進入等待狀態(tài);INT16UOSSemAccept(OS_EVENT*pevent);執(zhí)行步驟如果該信號量的計數(shù)值大于0,則將它減1,然后將信號量的原有值返回;如果該信號量的值等于0,直接返回該值(0)。查詢一個信號量的當前狀態(tài)OSSemQuery()查詢一個信號量的當前狀態(tài);INT8UOSSemQuery(OS_EVENT*pevent,
OS_SEM_DATA*pdata);將指向信號量對應事件控制塊的指針pevent所指向的ECB的內(nèi)容拷貝到指向用于記錄信號量信息的數(shù)據(jù)結構OS_SEM_DATA數(shù)據(jù)結構的指針pdata所指向的緩沖區(qū)當中。任務間通信低級通信只能傳遞狀態(tài)和整數(shù)值等控制信息,傳送的信息量?。焕纾盒盘柫扛呒壨ㄐ拍軌騻魉腿我鈹?shù)量的數(shù)據(jù);例如:共享內(nèi)存、郵箱、消息隊列共享內(nèi)存在C/OS-II中如何實現(xiàn)共享內(nèi)存?內(nèi)存地址空間只有一個,為所有的任務所共享!為了避免競爭狀態(tài),需要使用信號量來實現(xiàn)互斥訪問。消息郵箱郵箱(MailBox):一個任務或ISR可以通過郵箱向另一個任務發(fā)送一個指針型的變量,該指針指向一個包含了特定“消息”(message)的數(shù)據(jù)結構;必須在OS_CFG.H中將OS_MBOX_EN開關常量置為1,這樣μC/OS才能支持郵箱。一個郵箱可能處于兩種狀態(tài):滿的狀態(tài):郵箱包含一個非空指針型變量;空的狀態(tài):郵箱的內(nèi)容為空指針NULL;郵箱的系統(tǒng)服務OSMboxCreate()OSMboxPost()OSMboxPend()OSMboxAccept()OSMboxQuery()任務、ISR和消息郵箱的關系郵箱的系統(tǒng)服務(1)OSMboxCreate():創(chuàng)建一個郵箱在創(chuàng)建郵箱時,須分配一個ECB,并使用其中的字段OSEventPtr指針來存放消息的地址;OS_EVENT*OSMboxCreate(void*msg);msg:指針的初始值,一般情形下為NULL。OSMboxPend():等待一個郵箱中的消息若郵箱為滿,將其內(nèi)容(某消息的地址)返回;若郵箱為空,當前任務將被阻塞,直到郵箱中有了消息或等待超時;OSMboxPend(OS_EVENT*pevent,
INT16Utimeout,INT8U*err);郵箱的系統(tǒng)服務(2)OSMboxPost():發(fā)送一個消息到郵箱中如果有任務在等待該消息,將其中的最高優(yōu)先級任務從等待列表中刪除,變?yōu)榫途w狀態(tài);OSMboxPost(OS_EVENT*pevent,void*msg);OSMboxAccept():無等待地請求郵箱消息若郵箱為滿,返回它的當前內(nèi)容;若郵箱為空,返回空指針;OSMboxAccept(OS_EVENT*pevent);OSMboxQuery():查詢一個郵箱的狀態(tài)OSMboxQuery(OS_EVENT*pevent,
OS_MBOX_DATA*pdata);樣例程序(1)OSMboxCreate()函數(shù)OS_EVENT*CommMbox;voidmain(void)
{...
OSInit();
...
CommMbox=
OSMboxCreate((void*)0);
...
OSStart();}OSMboxPend()函數(shù)voidCommTask(void*pdata){INT8Uerr;
void*msg;pdata=pdata;
for(;;){
...msg=OSMboxPend(CommMbox,
10,&err);
if(err==OS_NO_ERR){/*收到消息時的代碼*/}else{/*未收到消息時的代碼*/}}樣例程序(2)OSMboxPost()函數(shù)OS_EVENT*CommMbox;INT8UCommRxBuf[100];voidCommTaskRx(void*pdata){INT8Uerr;
...for(;;){...
err=OSMboxPost(CommMbox,(void*)&CommRxbuf[0]);...}}消息隊列消息隊列(MessageQueue):消息隊列可以使一個任務或ISR向另一個任務發(fā)送多個以指針方式定義的變量;為了使μC/OS能夠支持消息隊列,必須在OS_CFG.H中將OS_Q_EN開關常量置為1,并且通過常量OS_MAX_QS來決定系統(tǒng)支持的最多消息隊列數(shù)。一個消息隊列可以容納多個不同的消息,因此可把它看作是由多個郵箱組成的數(shù)組,只是它們共用一個等待任務列表:消息隊列的系統(tǒng)服務OSQCreate()OSQPend()、OSQAccept()OSQPost()、OSQPostFront()OSQFlush()OSQQuery()消息隊列的體系結構回憶一下ECB數(shù)據(jù)結構ECB數(shù)據(jù)結構typedefstruct{void*OSEventPtr;/*指向消息或消息隊列的指針*/INT8UOSEventTbl[OS_EVENT_TBL_SIZE];//等待任務列表INT16UOSEventCnt;/*計數(shù)器(當事件是信號量時)*/INT8UOSEventType;/*事件類型:信號量、郵箱等*/INT8UOSEventGrp;/*等待任務組*/}OS_EVENT;在實現(xiàn)消息隊列時,哪些字段可以用?隊列控制塊隊列控制塊數(shù)據(jù)結構typedefstructos_q{structos_q*OSQPtr;//空閑隊列控制塊指針
void**OSQStart;//指向消息隊列的起始地址void**OSQEnd;//指向消息隊列的結束地址void**OSQIn;//指向消息隊列中下一個插入消息的位置void**OSQOut;//指向消息隊列中下一個取出消息的位置INT16UOSQSize;//消息隊列中總的單元數(shù)INT16UOSQEntries;//消息隊列中當前的消息數(shù)量}OS_EVENT;空閑隊列控制塊的管理每一個消息隊列都要用到一個隊列控制塊。在C/OS中,隊列控制塊的總數(shù)由OS_CFG.H中的常量OS_MAX_QS定義。在系統(tǒng)初始化時,所有的隊列控制塊被鏈接成一個單向鏈表——空閑隊列控制塊鏈表OSQFreeList;OSQPtrOSQStartOSQEndOSQEntriesOSQInOSQSizeOSQOutOSQPtrOSQStartOSQEndOSQEntriesOSQInOSQSizeOSQOutOSQPtrOSQStartOSQEndOSQEntriesOSQInOSQSizeOSQOutOSQFreeListOS_MAX_QSOS_Q01324C/OS-II概述任務管理中斷和時間管理任務之間的通信與同步5存儲管理概述C/OS中是實模式存儲管理不劃分內(nèi)核空間和用戶空間,整個系統(tǒng)只有一個地址空間,即物理內(nèi)存空間,應用程序和內(nèi)核程序都能直接對所有的內(nèi)存單元進行訪問;系統(tǒng)中的“任務”,實際上都是線程–––只有運行上下文和棧是獨享的,其他資源都是共享的。內(nèi)存布局代碼段(text)、數(shù)據(jù)段(data)、bss段、堆空間、??臻g;內(nèi)存管理,管的是誰?堆!malloc/free?在ANSIC中可以用malloc()和free()兩個函數(shù)動態(tài)地分配內(nèi)存和釋放內(nèi)存。在嵌入式實時操作系統(tǒng)中,容易產(chǎn)生碎片。由于內(nèi)存管理算法的原因,malloc()和free()函數(shù)執(zhí)行時間是不確定的。μC/OS-II對malloc()和free()函數(shù)進行了改進,使得它們可以分配和釋放固定大小的內(nèi)存塊。這樣一來,malloc()和free()函數(shù)的執(zhí)行時間也是固定的了
3Kb堆初始狀態(tài)A(1Kb)B(1Kb)C(1Kb)3個申請1KbB(1Kb)1Kb釋放A,CC/OS中的存儲管理C/OS采用的是固定分區(qū)的存儲管理方法μC/OS把連續(xù)的大塊內(nèi)存按分區(qū)來管理,每個分區(qū)包含有整數(shù)個大小相同的塊;在一個系統(tǒng)中可以有多個內(nèi)存分區(qū),這樣,用戶的應用程序就可以從不同的內(nèi)存分區(qū)中得到不同大小的內(nèi)存塊。但是,特定的內(nèi)存塊在釋放時必須重新放回它以前所屬于的內(nèi)存分區(qū);采用這樣的內(nèi)存管理算法,上面的內(nèi)存碎片問題就得到了解決。內(nèi)存分區(qū)示意圖分區(qū)1分區(qū)2分區(qū)3分區(qū)4內(nèi)存塊內(nèi)存控制塊為了便于管理,在μC/OS中使用內(nèi)存控制塊MCB(MemoryControlBlock)來跟蹤每一個內(nèi)存分區(qū),系統(tǒng)中的每個內(nèi)存分區(qū)都有它自己的MCB。typedefstruct{void*OSMemAddr; /*分區(qū)起始地址*/void*OSMemFreeList;//下一個空閑內(nèi)存塊INT32UOSMemBlkSize;/*內(nèi)存塊的大小*/INT32UOSMemNBlks; /*內(nèi)存塊數(shù)量*/INT32UOSMemNFree; /*空閑內(nèi)存塊數(shù)量*/}OS_MEM;內(nèi)存管理初始化如果要在μC/OS-II中使用內(nèi)存管理,需要在OS_CFG.H文件中將開關量OS_MEM_EN設置為1。這樣μC/OS-II在系統(tǒng)初始化OSInit()時就會調用OSMemInit(),對內(nèi)存管理器進行初始化,建立空閑的內(nèi)存控制塊鏈表。OSMemAddrOSMemFreeListOSMemBlkSizeOSMemNBlksOSMemNFreeOSMemAddrOSMemFreeListOSMemBlkSizeOSMemNBlksOSMemNFreeOSMemAddrOSMemFreeListOSMemBlkSizeOSMemNBlksOSMemNFreeOSMemFreeList0OS_MAX_MEM_PA
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年房產(chǎn)買賣契約(父子版)6篇
- 2025年新型私人地皮買賣協(xié)議書(含房屋拆遷補償)3篇
- 2025年房屋買賣協(xié)議(存量房)2篇
- 高級課程設計方法
- 隧道鉆爆課程設計
- 給水水質課程設計
- 語言程序設計課程設計
- 雨水 污水管網(wǎng)課程設計
- 槽型板沖壓磨具課程設計
- 音樂類app課程設計
- 2025年湖北武漢工程大學招聘6人歷年高頻重點提升(共500題)附帶答案詳解
- 【數(shù) 學】2024-2025學年北師大版數(shù)學七年級上冊期末能力提升卷
- GB/T 26846-2024電動自行車用電動機和控制器的引出線及接插件
- 遼寧省沈陽市皇姑區(qū)2024-2025學年九年級上學期期末考試語文試題(含答案)
- 妊娠咳嗽的臨床特征
- 國家公務員考試(面試)試題及解答參考(2024年)
- 《阻燃材料與技術》課件 第6講 阻燃纖維及織物
- 2024年金融理財-擔保公司考試近5年真題附答案
- 泰山產(chǎn)業(yè)領軍人才申報書
- 三創(chuàng)賽獲獎-非遺文化創(chuàng)新創(chuàng)業(yè)計劃書
- 封條模板A4直接打印版
評論
0/150
提交評論