ucos-ii中文書 第3章_第1頁
ucos-ii中文書 第3章_第2頁
ucos-ii中文書 第3章_第3頁
ucos-ii中文書 第3章_第4頁
ucos-ii中文書 第3章_第5頁
已閱讀5頁,還剩24頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

I 第第 3 章章內(nèi)核結(jié)構(gòu)內(nèi)核結(jié)構(gòu) 1 3 0臨界段 Critical Sections 1 3 1任務(wù) 1 3 2任務(wù)狀態(tài) 3 3 3任務(wù)控制塊 Task Control Blocks OS TCBs 3 3 4就緒表 Ready List 6 3 5任務(wù)調(diào)度 Task Scheduling 8 3 6給調(diào)度器上鎖和開鎖 Locking and UnLocking the Scheduler 9 3 7空閑任務(wù) Idle Task 11 3 8統(tǒng)計任務(wù) 11 3 9 C OS 中的中斷處理 14 3 10時鐘節(jié)拍 17 3 11 C OS 初始化 20 3 12 C OS 的啟動 20 3 13獲取當(dāng)前 C OS 的版本號 21 3 14OSEvent 函數(shù) 22 3 1 第 3 章內(nèi)核結(jié)構(gòu)內(nèi)核結(jié)構(gòu) 本章給出 C OS 的主要結(jié)構(gòu)概貌 讀者將學(xué)習(xí)以下一些內(nèi)容 C OS 是怎樣處理臨界段代碼的 什么是任務(wù) 怎樣把用戶的任務(wù)交給 C OS 任務(wù)是怎樣調(diào)度的 應(yīng)用程序 CPU 的利用率是多少 C OS 是怎樣知道的 怎樣寫中斷服務(wù)子程序 什么是時鐘節(jié)拍 C OS 是怎樣處理時鐘節(jié)拍的 C OS 是怎樣初始化的 以及 怎樣啟動多任務(wù) 本章還描述以下函數(shù) 這些服務(wù)于應(yīng)用程序 OS ENTER CRITICAL 和 OS EXIT CRITICAL OSInit OSStart OSIntEnter 和 OSIntExit OSSchedLock 和 OSSchedUnlock 以及 OSVersion 3 0臨界段臨界段 Critical Critical Sections Sections 和其它內(nèi)核一樣 C OS 為了處理臨界段代碼需要關(guān)中斷 處理完畢后再開中斷 這使得 C OS 能夠避免同時有其它任務(wù)或中斷服務(wù)進(jìn)入臨界段代碼 關(guān)中斷的時間是 實(shí)時內(nèi)核開發(fā)商應(yīng)提供的最重要的指標(biāo)之一 因?yàn)檫@個指標(biāo)影響用戶系統(tǒng)對實(shí)時事件的響 應(yīng)性 C OS 努力使關(guān)中斷時間降至最短 但就使用 C OS 而言 關(guān)中斷的時間很 大程度上取決于微處理器的架構(gòu)以及編譯器所生成的代碼質(zhì)量 微處理器一般都有關(guān)中斷 開中斷指令 用戶使用的 C 語言編譯器必須有某種機(jī)制能夠 在 C 中直接實(shí)現(xiàn)關(guān)中斷 開中斷地操作 某些 C 編譯器允許在用戶的 C 源代碼中插入?yún)R編語 言的語句 這使得插入微處理器指令來關(guān)中斷 開中斷很容易實(shí)現(xiàn) 而有的編譯器把從 C 語 言中關(guān)中斷 開中斷放在語言的擴(kuò)展部分 C OS 定義兩個宏 macros 來關(guān)中斷和開中 斷 以便避開不同 C 編譯器廠商選擇不同的方法來處理關(guān)中斷和開中斷 C OS 中的這 兩個宏調(diào)用分別是 OS ENTER CRITICAL 和 OS EXIT CRITICAL 因?yàn)檫@兩個宏的定義 取決于所用的微處理器 故在文件 OS CPU H 中可以找到相應(yīng)宏定義 每種微處理器都有自 己的 OS CPU H 文件 3 1任務(wù)任務(wù) 一個任務(wù)通常是一個無限的循環(huán) L3 1 2 如程序清單 3 1 所示 一個任務(wù)看起來像 其它 C 的函數(shù)一樣 有函數(shù)返回類型 有形式參數(shù)變量 但是任務(wù)是絕不會返回的 故返 回參數(shù)必須定義成 void L3 1 1 3 2 程序清單程序清單 L3 1L3 1 任務(wù)是一個無限循環(huán)任務(wù)是一個無限循環(huán) void YourTask void pdata 1 for 2 用戶代碼 調(diào)用uC OS II的某種系統(tǒng)服務(wù) OSMboxPend OSQPend OSSemPend OSTaskDel OS PRIO SELF OSTaskSuspend OS PRIO SELF OSTimeDly OSTimeDlyHMSM 用戶代碼 不同的是 當(dāng)任務(wù)完成以后 任務(wù)可以自我刪除 如清單 L3 2 所示 注意任務(wù)代碼并 非真的刪除了 C OS 只是簡單地不再理會這個任務(wù)了 這個任務(wù)的代碼也不會再運(yùn)行 如果任務(wù)調(diào)用了 OSTaskDel 這個任務(wù)絕不會返回什么 程序清單程序清單 L 3 2 任務(wù)完成后自我刪除任務(wù)完成后自我刪除 void YourTask void pdata 用戶代碼 OSTaskDel OS PRIO SELF 形式參數(shù)變量 L3 1 1 是由用戶代碼在第一次執(zhí)行的時候帶入的 請注意 該變量的 類型是一個指向 void 的指針 這是為了允許用戶應(yīng)用程序傳遞任何類型的數(shù)據(jù)給任務(wù) 這 個指針好比一輛萬能的車子 如果需要的話 可以運(yùn)載一個變量的地址 或一個結(jié)構(gòu) 甚 至是一個函數(shù)的地址 也可以建立許多相同的任務(wù) 所有任務(wù)都使用同一個函數(shù) 或者說 是同一個任務(wù)代碼程序 見第一章的例 1 例如 用戶可以將四個串行口安排成每個串 行口都是一個單獨(dú)的任務(wù) 而每個任務(wù)的代碼實(shí)際上是相同的 并不需要將代碼復(fù)制四次 用戶可以建立一個任務(wù) 向這個任務(wù)傳入一個指向某數(shù)據(jù)結(jié)構(gòu)的指針變量 這個數(shù)據(jù)結(jié)構(gòu) 定義串行口的參數(shù) 波特率 I O 口地址 中斷向量號等 C OS 可以管理多達(dá) 64 個任務(wù) 但目前版本的 C OS 有兩個任務(wù)已經(jīng)被系統(tǒng) 占用了 作者保留了優(yōu)先級為 0 1 2 3 OS LOWEST PRIO 3 OS LOWEST PRI0 2 OS LOWEST PRI0 1 以及 OS LOWEST PRI0 這 8 個任務(wù)以被將來使用 OS LOWEST PRI0 是 作為定義的常數(shù)在 OS CFG H 文件中用定義常數(shù)語句 define constant 定義的 因此用戶 可以有多達(dá) 56 個應(yīng)用任務(wù) 必須給每個任務(wù)賦以不同的優(yōu)先級 優(yōu)先級可以從 0 到 OS LOWEST PR10 2 優(yōu)先級號越低 任務(wù)的優(yōu)先級越高 C OS 總是運(yùn)行進(jìn)入就緒態(tài)的 3 3 優(yōu)先級最高的任務(wù) 目前版本的 C OS 中 任務(wù)的優(yōu)先級號就是任務(wù)編號 ID 優(yōu)先 級號 或任務(wù)的 ID 號 也被一些內(nèi)核服務(wù)函數(shù)調(diào)用 如改變優(yōu)先級函數(shù) OSTaskChangePrio 以及任務(wù)刪除函數(shù) OSTaskDel 為了使 C OS 能管理用戶任務(wù) 用戶必須在建立一個任務(wù)的時候 將任務(wù)的起始 地址與其它參數(shù)一起傳給下面兩個函數(shù)中的一個 OSTastCreat 或 OSTaskCreatExt OSTaskCreateExt 是 OSTaskCreate 的擴(kuò)展 擴(kuò)展了一些附加的功能 這兩個函數(shù)的解 釋見第四章 任務(wù)管理 3 2任務(wù)狀態(tài)任務(wù)狀態(tài) 圖 3 1 是 C OS 控制下的任務(wù)狀態(tài)轉(zhuǎn)換圖 在任一給定的時刻 任務(wù)的狀態(tài)一定 是在這五種狀態(tài)之一 睡眠態(tài) DORMANT 指任務(wù)駐留在程序空間之中 還沒有交給 C OS 管理 見程 序清單 L3 1 或 L3 2 把任務(wù)交給 C OS 是通過調(diào)用下述兩個函數(shù)之一 OSTaskCreate 或 OSTaskCreateExt 當(dāng)任務(wù)一旦建立 這個任務(wù)就進(jìn)入就緒態(tài)準(zhǔn)備運(yùn) 行 任務(wù)的建立可以是在多任務(wù)運(yùn)行開始之前 也可以是動態(tài)地被一個運(yùn)行著的任務(wù)建立 如果一個任務(wù)是被另一個任務(wù)建立的 而這個任務(wù)的優(yōu)先級高于建立它的那個任務(wù) 則這 個剛剛建立的任務(wù)將立即得到 CPU 的控制權(quán) 一個任務(wù)可以通過調(diào)用 OSTaskDel 返回到 睡眠態(tài) 或通過調(diào)用該函數(shù)讓另一個任務(wù)進(jìn)入睡眠態(tài) 調(diào)用 OSStart 可以啟動多任務(wù) OSStart 函數(shù)運(yùn)行進(jìn)入就緒態(tài)的優(yōu)先級最高的任務(wù) 就緒的任務(wù)只有當(dāng)所有優(yōu)先級高于這個任務(wù)的任務(wù)轉(zhuǎn)為等待狀態(tài) 或者是被刪除了 才能 進(jìn)入運(yùn)行態(tài) 圖 3 1 任務(wù)的狀態(tài) 正在運(yùn)行的任務(wù)可以通過調(diào)用兩個函數(shù)之一將自身延遲一段時間 這兩個函數(shù)是 OSTimeDly 或 OSTimeDlyHMSM 這個任務(wù)于是進(jìn)入等待狀態(tài) 等待這段時間過去 下一 個優(yōu)先級最高的 并進(jìn)入了就緒態(tài)的任務(wù)立刻被賦予了 CPU 的控制權(quán) 等待的時間過去以 后 系統(tǒng)服務(wù)函數(shù) OSTimeTick 使延遲了的任務(wù)進(jìn)入就緒態(tài) 見 3 10 節(jié) 時鐘節(jié)拍 正在運(yùn)行的任務(wù)期待某一事件的發(fā)生時也要等待 手段是調(diào)用以下 3 個函數(shù)之一 3 4 OSSemPend OSMboxPend 或 OSQPend 調(diào)用后任務(wù)進(jìn)入了等待狀態(tài) WAITING 當(dāng) 任務(wù)因等待事件被掛起 Pend 下一個優(yōu)先級最高的任務(wù)立即得到了 CPU 的控制權(quán) 當(dāng)事 件發(fā)生了 被掛起的任務(wù)進(jìn)入就緒態(tài) 事件發(fā)生的報告可能來自另一個任務(wù) 也可能來自 中斷服務(wù)子程序 正在運(yùn)行的任務(wù)是可以被中斷的 除非該任務(wù)將中斷關(guān)了 或者 C OS 將中斷關(guān) 了 被中斷了的任務(wù)就進(jìn)入了中斷服務(wù)態(tài) ISR 響應(yīng)中斷時 正在執(zhí)行的任務(wù)被掛起 中斷服務(wù)子程序控制了 CPU 的使用權(quán) 中斷服務(wù)子程序可能會報告一個或多個事件的發(fā)生 而使一個或多個任務(wù)進(jìn)入就緒態(tài) 在這種情況下 從中斷服務(wù)子程序返回之前 C OS 要判定 被中斷的任務(wù)是否還是就緒態(tài)任務(wù)中優(yōu)先級最高的 如果中斷服務(wù)子程序使一個 優(yōu)先級更高的任務(wù)進(jìn)入了就緒態(tài) 則新進(jìn)入就緒態(tài)的這個優(yōu)先級更高的任務(wù)將得以運(yùn)行 否則原來被中斷了的任務(wù)才能繼續(xù)運(yùn)行 當(dāng)所有的任務(wù)都在等待事件發(fā)生或等待延遲時間結(jié)束 C OS 執(zhí)行空閑任務(wù) idle task 執(zhí)行 OSTaskIdle 函數(shù) 3 3任務(wù)控制塊 任務(wù)控制塊 TaskTask ControlControl Blocks Blocks OSOS TCBs TCBs 一旦任務(wù)建立了 任務(wù)控制塊 OS TCBs 將被賦值 程序清單 3 3 任務(wù)控制塊是一個 數(shù)據(jù)結(jié)構(gòu) 當(dāng)任務(wù)的 CPU 使用權(quán)被剝奪時 C OS 用它來保存該任務(wù)的狀態(tài) 當(dāng)任務(wù)重 新得到 CPU 使用權(quán)時 任務(wù)控制塊能確保任務(wù)從當(dāng)時被中斷的那一點(diǎn)絲毫不差地繼續(xù)執(zhí)行 OS TCBs 全部駐留在 RAM 中 讀者將會注意到筆者在組織這個數(shù)據(jù)結(jié)構(gòu)時 考慮到了各成 員的邏輯分組 任務(wù)建立的時候 OS TCBs 就被初始化了 見第四章 任務(wù)管理 程序清單程序清單 L 3 3 C OS II任務(wù)控制塊任務(wù)控制塊 typedef struct os tcb OS STK OSTCBStkPtr if OS TASK CREATE EXT EN void OSTCBExtPtr OS STK OSTCBStkBottom INT32U OSTCBStkSize INT16U OSTCBOpt INT16U OSTCBId endif struct os tcb OSTCBNext struct os tcb OSTCBPrev if OS Q EN endif if OS Q EN endif 3 5 INT16U OSTCBDly INT8U OSTCBStat INT8U OSTCBPrio INT8U OSTCBX INT8U OSTCBY INT8U OSTCBBitX INT8U OSTCBBitY if OS TASK DEL EN BOOLEAN OSTCBDelReq endif OS TCB OSTCBStkPtr OSTCBStkPtr 是指向當(dāng)前任務(wù)棧頂?shù)闹羔?C OS 允許每個任務(wù)有自己的棧 尤為重 要的是 每個任務(wù)的棧的容量可以是任意的 有些商業(yè)內(nèi)核要求所有任務(wù)棧的容量都一樣 除非用戶寫一個復(fù)雜的接口函數(shù)來改變之 這種限制浪費(fèi)了 RAM 當(dāng)各任務(wù)需要的??臻g 不同時 也得按任務(wù)中預(yù)期棧容量需求最多的來分配??臻g OSTCBStkPtr 是 OS TCB 數(shù)據(jù) 結(jié)構(gòu)中唯一的一個能用匯編語言來處置的變量 在任務(wù)切換段的代碼 Context switching code 之中 把 OSTCBStkPtr 放在數(shù)據(jù)結(jié)構(gòu)的最前面 使得從匯編語言中處理這個變量時 較為容易 OSTCBExtPtr OSTCBExtPtr 指向用戶定義的任務(wù)控制塊擴(kuò)展 用戶可以擴(kuò)展任務(wù)控制塊而不必修改 C OS 的源代碼 OSTCBExtPtr 只在函數(shù) OstaskCreateExt 中使用 故使用時要將 OS TASK CREAT EN 設(shè)為 1 以允許建立任務(wù)函數(shù)的擴(kuò)展 例如用戶可以建立一個數(shù)據(jù)結(jié)構(gòu) 這個數(shù)據(jù)結(jié)構(gòu)包含每個任務(wù)的名字 或跟蹤某個任務(wù)的執(zhí)行時間 或者跟蹤切換到某個任 務(wù)的次數(shù) 見例 3 注意 筆者將這個擴(kuò)展指針變量放在緊跟著堆棧指針的位置 為的是 當(dāng)用戶需要在匯編語言中處理這個變量時 從數(shù)據(jù)結(jié)構(gòu)的頭上算偏移量比較方便 OSTCBStkBottom OSTCBStkBottom 是指向任務(wù)棧底的指針 如果微處理器的棧指針是遞減的 即棧存儲器 從高地址向低地址方向分配 則 OSTCBStkBottom 指向任務(wù)使用的??臻g的最低地址 類似 地 如果微處理器的棧是從低地址向高地址遞增型的 則 OSTCBStkBottom 指向任務(wù)可以使 用的??臻g的最高地址 函數(shù) OSTaskStkChk 要用到變量 OSTCBStkBottom 在運(yùn)行中檢驗(yàn) ??臻g的使用情況 用戶可以用它來確定任務(wù)實(shí)際需要的棧空間 這個功能只有當(dāng)用戶在 任務(wù)建立時允許使用 OSTaskCreateExt 函數(shù)時才能實(shí)現(xiàn) 這就要求用戶將 OS TASK CREATE EXT EN 設(shè)為 1 以便允許該功能 OSTCBStkSize OSTCBStkSize 存有棧中可容納的指針元數(shù)目而不是用字節(jié) Byte 表示的棧容量總數(shù) 也就是說 如果棧中可以保存 1 000 個入口地址 每個地址寬度是 32 位的 則實(shí)際棧容量 是 4 000 字節(jié) 同樣是 1 000 個入口地址 如果每個地址寬度是 16 位的 則總棧容量只有 2 000 字節(jié) 在函數(shù) OSStakChk 中要調(diào)用 OSTCBStkSize 同理 若使用該函數(shù)的話 要 將 OS TASK CREAT EXT EN 設(shè)為 1 OSTCBOpt OSTCBOpt 把 選擇項(xiàng) 傳給 OSTaskCreateExt 只有在用戶將 OS TASK CREATE EXT EN 設(shè)為 1 時 這個變量才有效 C OS 目前只支持 3 個選擇項(xiàng) 見 uCOS II H OS TASK OTP STK CHK OS TASK OPT STK CLR 和 OS TASK OPT SAVE FP OS TASK OTP STK CHK 用于告知 TaskCreateExt 在任務(wù)建立的時候任務(wù)棧檢驗(yàn)功能得 3 6 到了允許 OS TASK OPT STK CLR 表示任務(wù)建立的時候任務(wù)棧要清零 只有在用戶需要有 棧檢驗(yàn)功能時 才需要將棧清零 如果不定義 OS TASK OPT STK CLR 而后又建立 刪除 了任務(wù) 棧檢驗(yàn)功能報告的棧使用情況將是錯誤的 如果任務(wù)一旦建立就決不會被刪除 而用戶初始化時 已將 RAM 清過零 則 OS TASK OPT STK CLR 不需要再定義 這可以節(jié)約 程序執(zhí)行時間 傳遞了 OS TASK OPT STK CLR 將增加 TaskCreateExt 函數(shù)的執(zhí)行時間 因?yàn)橐獙?臻g清零 棧容量越大 清零花的時間越長 最后一個選擇項(xiàng) OS TASK OPT SAVE FP 通知 TaskCreateExt 任務(wù)要做浮點(diǎn)運(yùn)算 如果微處理器有硬件的 浮點(diǎn)協(xié)處理器 則所建立的任務(wù)在做任務(wù)調(diào)度切換時 浮點(diǎn)寄存器的內(nèi)容要保存 OSTCBId OSTCBId 用于存儲任務(wù)的識別碼 這個變量現(xiàn)在沒有使用 留給將來擴(kuò)展用 OSTCBNext OSTCBNext 和 OSTCBPrevOSTCBPrev 用于任務(wù)控制塊 OS TCBs 的雙重鏈接 該鏈表在時鐘節(jié)拍函數(shù) OSTimeTick 中使用 用于刷新各個任務(wù)的任務(wù)延遲變量 OSTCBDly 每個任務(wù)的任務(wù)控制 塊 OS TCB 在任務(wù)建立的時候被鏈接到鏈表中 在任務(wù)刪除的時候從鏈表中被刪除 雙重連 接的鏈表使得任一成員都能被快速插入或刪除 OSTCBEventPtr OSTCBEventPtr 是指向事件控制塊的指針 后面的章節(jié)中會有所描述 見第 6 章 任務(wù)間 通訊與同步 OSTCBMsg OSTCBMsg 是指向傳給任務(wù)的消息的指針 用法將在后面的章節(jié)中提到 見第 6 章任務(wù)間 通訊與同步 OSTCBDly OSTCBDly 當(dāng)需要把任務(wù)延時若干時鐘節(jié)拍時要用到這個變量 或者需要把任務(wù)掛起一段 時間以等待某事件的發(fā)生 這種等待是有超時限制的 在這種情況下 這個變量保存的是 任務(wù)允許等待事件發(fā)生的最多時鐘節(jié)拍數(shù) 如果這個變量為 0 表示任務(wù)不延時 或者表 示等待事件發(fā)生的時間沒有限制 OSTCBStat OSTCBStat 是任務(wù)的狀態(tài)字 當(dāng) OSTCBStat 為 0 任務(wù)進(jìn)入就緒態(tài) 可以給 OSTCBStat 賦 其它的值 在文件 uCOS II H 中有關(guān)于這個值的描述 OSTCBPrio OSTCBPrio 是任務(wù)優(yōu)先級 高優(yōu)先級任務(wù)的 OSTCBPrio 值小 也就是說 這個值越小 任 務(wù)的優(yōu)先級越高 OSTCBX OSTCBX OSTCBY OSTCBY OSTCBBitX OSTCBBitX 和和 OSTCBBitY OSTCBBitY 用于加速任務(wù)進(jìn)入就緒態(tài)的過程或進(jìn)入等 待事件發(fā)生狀態(tài)的過程 避免在運(yùn)行中去計算這些值 這些值是在任務(wù)建立時算好的 或 者是在改變?nèi)蝿?wù)優(yōu)先級時算出的 這些值的算法見程序清單 L3 4 程序清單程序清單 L 3 4任務(wù)控制塊任務(wù)控制塊OS TCBOS TCB中幾個成員的算法中幾個成員的算法 OSTCBY priority 3 OSTCBBitY OSMapTbl priority 3 OSTCBX priority OSTCBBitX OSMapTbl priority OSTCBDelReq OSTCBDelReq 是一個布爾量 用于表示該任務(wù)是否需要刪除 用法將在后面的章節(jié)中描述 見第 4 章 任務(wù)管理 應(yīng)用程序中可以有的最多任務(wù)數(shù) OS MAX TASKS 是在文件 OS CFG H 中定義的 這個 最多任務(wù)數(shù)也是 C OS 分配給用戶程序的最多任務(wù)控制塊 OS TCBs 的數(shù)目 將 OS MAX TASKS 的數(shù)目設(shè)置為用戶應(yīng)用程序?qū)嶋H需要的任務(wù)數(shù)可以減小 RAM 的需求量 所有 的任務(wù)控制塊 OS TCBs 都是放在任務(wù)控制塊列表數(shù)組 OSTCBTbl 中的 請注意 C OS 分配給系統(tǒng)任務(wù) OS N SYS TASKS 若干個任務(wù)控制塊 見文件 C OS H 供其內(nèi)部使 3 7 用 目前 一個用于空閑任務(wù) 另一個用于任務(wù)統(tǒng)計 如果 OS TASK STAT EN 是設(shè)為 1 的 在 C OS 初始化的時候 如圖 3 2 所示 所有任務(wù)控制塊 OS TCBs 被鏈接成單向空任 務(wù)鏈表 當(dāng)任務(wù)一旦建立 空任務(wù)控制塊指針 OSTCBFreeList 指向的任務(wù)控制塊便賦給了 該任務(wù) 然后 OSTCBFreeList 的值調(diào)整為指向下鏈表中下一個空的任務(wù)控制塊 一旦任務(wù) 被刪除 任務(wù)控制塊就還給空任務(wù)鏈表 圖 3 2 空任務(wù)列表 3 4 就緒表 就緒表 ReadyReady ListList 每個任務(wù)被賦予不同的優(yōu)先級等級 從 0 級到最低優(yōu)先級 OS LOWEST PR1O 包括 0 和 OS LOWEST PR1O 在內(nèi) 見文件 OS CFG H 當(dāng) C OS 初始化的時候 最低優(yōu)先級 OS LOWEST PR1O 總是被賦給空閑任務(wù) idle task 注意 最多任務(wù)數(shù)目 OS MAX TASKS 和最 低優(yōu)先級數(shù)是沒有關(guān)系的 用戶應(yīng)用程序可以只有 10 個任務(wù) 而仍然可以有 32 個優(yōu)先級 的級別 如果用戶將最低優(yōu)先級數(shù)設(shè)為 31 的話 每個任務(wù)的就緒態(tài)標(biāo)志都放入就緒表中的 就緒表中有兩個變量 OSRedyGrp 和 OSRdyTbl 在 OSRdyGrp 中 任務(wù)按優(yōu)先級分組 8 個任務(wù)為一組 OSRdyGrp 中的每一位 表示 8 組任務(wù)中每一組中是否有進(jìn)入就緒態(tài)的任務(wù) 任務(wù)進(jìn)入就緒態(tài)時 就緒表 OSRdyTbl 中的相應(yīng)元素的相應(yīng)位也置位 就緒表 OSRdyTbl 數(shù)組的大小取決于 OS LOWEST PR1O 見文件 OS CFG H 當(dāng)用戶的應(yīng)用程序中任務(wù)數(shù)目比較少時 減少 OS LOWEST PR1O 的值可以降低 C OS 對 RAM 數(shù)據(jù)空間 的需求量 為確定下次該哪個優(yōu)先級的任務(wù)運(yùn)行了 內(nèi)核調(diào)度器總是將 OS LOWEST PR1O 在就緒表 中相應(yīng)字節(jié)的相應(yīng)位置 1 OSRdyGrp 和 OSRdyTbl 之間的關(guān)系見圖 3 3 是按以下規(guī)則給 出的 當(dāng) OSRdyTbl 0 中的任何一位是 1 時 OSRdyGrp 的第 0 位置 1 當(dāng) OSRdyTbl 1 中的任何一位是 1 時 OSRdyGrp 的第 1 位置 1 當(dāng) OSRdyTbl 2 中的任何一位是 1 時 OSRdyGrp 的第 2 位置 1 當(dāng) OSRdyTbl 3 中的任何一位是 1 時 OSRdyGrp 的第 3 位置 1 當(dāng) OSRdyTbl 4 中的任何一位是 1 時 OSRdyGrp 的第 4 位置 1 當(dāng) OSRdyTbl 5 中的任何一位是 1 時 OSRdyGrp 的第 5 位置 1 當(dāng) OSRdyTbl 6 中的任何一位是 1 時 OSRdyGrp 的第 6 位置 1 當(dāng) OSRdyTbl 7 中的任何一位是 1 時 OSRdyGrp 的第 7 位置 1 程序清單 3 5 中的代碼用于將任務(wù)放入就緒表 Prio 是任務(wù)的優(yōu)先級 3 8 程序清單程序清單 L3 5L3 5 使任務(wù)進(jìn)入就緒態(tài)使任務(wù)進(jìn)入就緒態(tài) OSRdyGrp OSMapTbl prio 3 OSRdyTbl prio 3 OSMapTbl prio 表表 T3 1T3 1 OSMapTbl OSMapTbl 的值的值 IndexBit Mask Binary 0 00000001 1 00000010 2 00000100 3 00001000 4 00010000 5 00100000 6 01000000 7 10000000 讀者可以看出 任務(wù)優(yōu)先級的低三位用于確定任務(wù)在總就緒表 OSRdyTbl 中的所在位 接下去的三位用于確定是在 OSRdyTbl 數(shù)組的第幾個元素 OSMapTbl 是在 ROM 中的 見 文件 OS CORE C 屏蔽字 用于限制 OSRdyTbl 數(shù)組的元素下標(biāo)在 0 到 7 之間 見表 3 1 3 9 圖 3 3 C OS 就緒表 如果一個任務(wù)被刪除了 則用程序清單 3 6 中的代碼做求反處理 程序清單程序清單 L3 6L3 6 從就緒表中刪除一個任務(wù)從就緒表中刪除一個任務(wù) if OSRdyTbl prio 3 以上代碼將就緒任務(wù)表數(shù)組 OSRdyTbl 中相應(yīng)元素的相應(yīng)位清零 而對于 OSRdyGrp 只有當(dāng)被刪除任務(wù)所在任務(wù)組中全組任務(wù)一個都沒有進(jìn)入就緒態(tài)時 才將相應(yīng)位清零 也 就是說 OSRdyTbl prio 3 所有的位都是零時 OSRdyGrp 的相應(yīng)位才清零 為了找到那個 進(jìn)入就緒態(tài)的優(yōu)先級最高的任務(wù) 并不需要從 OSRdyTbl 0 開始掃描整個就緒任務(wù)表 只 需要查另外一張表 即優(yōu)先級判定表 OSUnMapTbl 256 見文件 OS CORE C OSRdyTbl 中每個字節(jié)的 8 位代表這一組的 8 個任務(wù)哪些進(jìn)入就緒態(tài)了 低位的優(yōu)先級高于高位 利 用這個字節(jié)為下標(biāo)來查 OSUnMapTbl 這張表 返回的字節(jié)就是該組任務(wù)中就緒態(tài)任務(wù)中優(yōu)先 級最高的那個任務(wù)所在的位置 這個返回值在 0 到 7 之間 確定進(jìn)入就緒態(tài)的優(yōu)先級最高 的任務(wù)是用以下代碼完成的 如程序清單 L3 7 所示 程序清單程序清單 L3 7 找出進(jìn)入就緒態(tài)的優(yōu)先級最高的任務(wù)找出進(jìn)入就緒態(tài)的優(yōu)先級最高的任務(wù) y OSUnMapTbl OSRdyGrp x OSUnMapTbl OSRdyTbl y 3 10 prio y 3 x 例如 如果 OSRdyGrp 的值為二進(jìn)制 01101000 查 OSUnMapTbl OSRdyGrp 得到的值是 3 它相應(yīng)于 OSRdyGrp 中的第 3 位 bit3 這里假設(shè)最右邊的一位是第 0 位 bit0 類似地 如果 OSRdyTbl 3 的值是二進(jìn)制 11100100 則 OSUnMapTbl OSRdyTbc 3 的值是 2 即第 2 位 于是任務(wù)的優(yōu)先級 Prio 就等于 26 3 8 2 利用這個優(yōu)先級的值 查任務(wù)控制塊優(yōu) 先級表 OSTCBPrioTbl 得到指向相應(yīng)任務(wù)的任務(wù)控制塊 OS TCB 的工作就完成了 3 5任務(wù)調(diào)度 任務(wù)調(diào)度 TaskTask SchedulingScheduling C OS 總是運(yùn)行進(jìn)入就緒態(tài)任務(wù)中優(yōu)先級最高的那一個 確定哪個任務(wù)優(yōu)先級最高 下面該哪個任務(wù)運(yùn)行了的工作是由調(diào)度器 Scheduler 完成的 任務(wù)級的調(diào)度是由函數(shù) OSSched 完成的 中斷級的調(diào)度是由另一個函數(shù) OSIntExt 完成的 這個函數(shù)將在以后 描述 OSSched 的代碼如程序清單 L3 8 所示 程序清單程序清單 L3 8L3 8 任務(wù)調(diào)度器 任務(wù)調(diào)度器 thethe TaskTask SchedulerScheduler void OSSched void INT8U y OS ENTER CRITICAL if OSLockNesting OSIntNesting 0 1 y OSUnMapTbl OSRdyGrp 2 OSPrioHighRdy INT8U y 0 或者由于用戶至少調(diào)用了一次給任務(wù)調(diào)度上鎖函數(shù) OSSchedLock 使 OSLockNesting 0 如果不是在中斷服務(wù)子程序調(diào)用 OSSched 并且任務(wù)調(diào)度是允許的 即沒有上鎖 則任務(wù)調(diào)度函數(shù)將找出那個進(jìn)入就緒態(tài)且優(yōu)先級最高的任務(wù) L3 8 2 進(jìn)入 就緒態(tài)的任務(wù)在就緒任務(wù)表中有相應(yīng)的位置位 一旦找到那個優(yōu)先級最高的任務(wù) OSSched 檢驗(yàn)這個優(yōu)先級最高的任務(wù)是不是當(dāng)前正在運(yùn)行的任務(wù) 以此來避免不必要的任 務(wù)調(diào)度 L3 8 3 注意 在 C OS 中曾經(jīng)是先得到 OSTCBHighRdy 然后和 OSTCBCur 做比 較 因?yàn)檫@個比較是兩個指針型變量的比較 在 8 位和一些 16 位微處理器中這種比較相對 較慢 而在 C OS 中是兩個整數(shù)的比較 并且 除非用戶實(shí)際需要做任務(wù)切換 在查 3 11 任務(wù)控制塊優(yōu)先級表 OSTCBPrioTbl 時 不需要用指針變量來查 OSTCBHighRdy 綜合這兩 項(xiàng)改進(jìn) 即用整數(shù)比較代替指針的比較和當(dāng)需要任務(wù)切換時再查表 使得 C OS 比 C OS 在 8 位和一些 16 位微處理器上要更快一些 為實(shí)現(xiàn)任務(wù)切換 OSTCBHighRdy 必須指向優(yōu)先級最高的那個任務(wù)控制塊 OS TCB 這是 通過將以 OSPrioHighRdy 為下標(biāo)的 OSTCBPrioTbl 數(shù)組中的那個元素賦給 OSTCBHighRdy 來實(shí)現(xiàn)的 L3 8 4 接著 統(tǒng)計計數(shù)器 OSCtxSwCtr 加 1 以跟蹤任務(wù)切換次數(shù) L3 8 5 最后宏調(diào)用 OS TASK SW 來完成實(shí)際上的任務(wù)切換 L3 8 6 任務(wù)切換很簡單 由以下兩步完成 將被掛起任務(wù)的微處理器寄存器推入堆棧 然后 將較高優(yōu)先級的任務(wù)的寄存器值從棧中恢復(fù)到寄存器中 在 C OS 中 就緒任務(wù)的棧 結(jié)構(gòu)總是看起來跟剛剛發(fā)生過中斷一樣 所有微處理器的寄存器都保存在棧中 換句話說 C OS 運(yùn)行就緒態(tài)的任務(wù)所要做的一切 只是恢復(fù)所有的 CPU 寄存器并運(yùn)行中斷返回指 令 為了做任務(wù)切換 運(yùn)行 OS TASK SW 人為模仿了一次中斷 多數(shù)微處理器有軟中斷 指令或者陷阱指令 TRAP 來實(shí)現(xiàn)上述操作 中斷服務(wù)子程序或陷阱處理 Trap hardler 也稱作事故處理 exception handler 必須提供中斷向量給匯編語言函數(shù) OSCtxSw OSCtxSw 除了需要 OS TCBHighRdy 指向即將被掛起的任務(wù) 還需要讓當(dāng)前任務(wù)控制塊 OSTCBCur 指向即將被掛起的任務(wù) 參見第 8 章 移植 C OS 有關(guān)于 OSCtxSw 的更 詳盡的解釋 OSSched 的所有代碼都屬臨界段代碼 在尋找進(jìn)入就緒態(tài)的優(yōu)先級最高的任務(wù)過程中 為防止中斷服務(wù)子程序把一個或幾個任務(wù)的就緒位置位 中斷是被關(guān)掉的 為縮短切換時 間 OSSched 全部代碼都可以用匯編語言寫 為增加可讀性 可移植性和將匯編語言代碼 最少化 OSSched 是用 C 寫的 3 6給調(diào)度器上鎖和開鎖給調(diào)度器上鎖和開鎖 Locking Locking andand UnLockingUnLocking thethe Scheduler Scheduler 給調(diào)度器上鎖函數(shù) OSSchedlock 程序清單 L3 9 用于禁止任務(wù)調(diào)度 直到任務(wù)完 成后調(diào)用給調(diào)度器開鎖函數(shù) OSSchedUnlock 為止 程序清單 L3 10 調(diào)用 OSSchedlock 的任務(wù)保持對 CPU 的控制權(quán) 盡管有個優(yōu)先級更高的任務(wù)進(jìn)入了就緒態(tài) 然 而 此時中斷是可以被識別的 中斷服務(wù)也能得到 假設(shè)中斷是開著的 OSSchedlock 和 OSSchedUnlock 必須成對使用 變量 OSLockNesting 跟蹤 OSSchedLock 函數(shù)被調(diào)用的 次數(shù) 以允許嵌套的函數(shù)包含臨界段代碼 這段代碼其它任務(wù)不得干預(yù) C OS 允許嵌 套深度達(dá) 255 層 當(dāng) OSLockNesting 等于零時 調(diào)度重新得到允許 函數(shù) OSSchedLock 和 OSSchedUnlock 的使用要非常謹(jǐn)慎 因?yàn)樗鼈冇绊?C OS 對任務(wù)的正常管理 當(dāng) OSLockNesting 減到零的時候 OSSchedUnlock 調(diào)用 OSSched L3 10 2 OSSchedUnlock 是被某任務(wù)調(diào)用的 在調(diào)度器上鎖的期間 可能有什么事件發(fā)生了并使一 個更高優(yōu)先級的任務(wù)進(jìn)入就緒態(tài) 調(diào)用 OSSchedLock 以后 用戶的應(yīng)用程序不得使用任何能將現(xiàn)行任務(wù)掛起的系統(tǒng)調(diào) 用 也就是說 用戶程序不得調(diào)用 OSMboxPend OSQPend OSSemPend OSTaskSuspend OS PR1O SELF OSTimeDly 或 OSTimeDlyHMSM 直到 OSLockNesting 回 零為止 因?yàn)檎{(diào)度器上了鎖 用戶就鎖住了系統(tǒng) 任何其它任務(wù)都不能運(yùn)行 當(dāng)?shù)蛢?yōu)先級的任務(wù)要發(fā)消息給多任務(wù)的郵箱 消息隊列 信號量時 見第 6 章 任務(wù)間 通訊和同步 用戶不希望高優(yōu)先級的任務(wù)在郵箱 隊列和信號量沒有得到消息之前就取得 了 CPU 的控制權(quán) 此時 用戶可以使用禁止調(diào)度器函數(shù) 程序清單程序清單 L3 9 給調(diào)度器上鎖給調(diào)度器上鎖 3 12 void OSSchedLock void if OSRunning TRUE OS ENTER CRITICAL OSLockNesting OS EXIT CRITICAL 程序清單程序清單 L3 10L3 10 給調(diào)度器開鎖給調(diào)度器開鎖 void OSSchedUnlock void if OSRunning TRUE OS ENTER CRITICAL if OSLockNesting 0 OSLockNesting if OSLockNesting OSIntNesting 0 1 OS EXIT CRITICAL OSSched 2 else OS EXIT CRITICAL else OS EXIT CRITICAL 3 7空閑任務(wù)空閑任務(wù) Idle Idle Task Task C OS 總是建立一個空閑任務(wù) 這個任務(wù)在沒有其它任務(wù)進(jìn)入就緒態(tài)時投入運(yùn)行 這個空閑任務(wù) OSTaskIdle 永遠(yuǎn)設(shè)為最低優(yōu)先級 即 OS LOWEST PRI0 空閑任務(wù) OSTaskIdle 什么也不做 只是在不停地給一個 32 位的名叫 OSIdleCtr 的計數(shù)器加 1 統(tǒng) 計任務(wù) 見 3 08 節(jié) 統(tǒng)計任務(wù) 使用這個計數(shù)器以確定現(xiàn)行應(yīng)用軟件實(shí)際消耗的 CPU 時間 程序清單 L3 11 是空閑任務(wù)的代碼 在計數(shù)器加 1 前后 中斷是先關(guān)掉再開啟的 因?yàn)?8 位以及大多數(shù) 16 位微處理器的 32 位加 1 需要多條指令 要防止高優(yōu)先級的任務(wù)或中斷服 務(wù)子程序從中打入 空閑任務(wù)不可能被應(yīng)用軟件刪除 程序清單程序清單 L3 11L3 11 C OS C OS 的空閑任務(wù)的空閑任務(wù) void OSTaskIdle void pdata pdata pdata for 3 13 OS ENTER CRITICAL OSIdleCtr OS EXIT CRITICAL 3 8統(tǒng)計任務(wù)統(tǒng)計任務(wù) C OS 有一個提供運(yùn)行時間統(tǒng)計的任務(wù) 這個任務(wù)叫做 OSTaskStat 如果用戶將 系統(tǒng)定義常數(shù) OS TASK STAT EN 見文件 OS CFG H 設(shè)為 1 這個任務(wù)就會建立 一旦得 到了允許 OSTaskStat 每秒鐘運(yùn)行一次 見文件 OS CORE C 計算當(dāng)前的 CPU 利用率 換句話說 OSTaskStat 告訴用戶應(yīng)用程序使用了多少 CPU 時間 用百分比表示 這個值 放在一個有符號 8 位整數(shù) OSCPUsage 中 精讀度是 1 個百分點(diǎn) 如果用戶應(yīng)用程序打算使用統(tǒng)計任務(wù) 用戶必須在初始化時建立一個唯一的任務(wù) 在 這個任務(wù)中調(diào)用 OSStatInit 見文件 OS CORE C 換句話說 在調(diào)用系統(tǒng)啟動函數(shù) OSStart 之前 用戶初始代碼必須先建立一個任務(wù) 在這個任務(wù)中調(diào)用系統(tǒng)統(tǒng)計初始化函 數(shù) OSStatInit 然后再建立應(yīng)用程序中的其它任務(wù) 程序清單 L3 12 是統(tǒng)計任務(wù)的示意 性代碼 程序清單程序清單 L3 12L3 12 初始化統(tǒng)計任務(wù)初始化統(tǒng)計任務(wù) void main void OSInit 初始化uC OS II 1 安裝uC OS II的任務(wù)切換向量 創(chuàng)建用戶起始任務(wù) 為了方便討論 這里以TaskStart 作為起始任務(wù) 2 OSStart 開始多任務(wù)調(diào)度 3 void TaskStart void pdata 安裝并啟動uC OS II的時鐘節(jié)拍 4 OSStatInit 初始化統(tǒng)計任務(wù) 5 創(chuàng)建用戶應(yīng)用程序任務(wù) for 這里是TaskStart 的代碼 因?yàn)橛脩舻膽?yīng)用程序必須先建立一個起始任務(wù) TaskStart 當(dāng)主程序 main 調(diào) 用系統(tǒng)啟動函數(shù) OSStcnt 的時候 C OS 只有 3 個要管理的任務(wù) TaskStart OSTaskIdle 和 OSTaskStat 請注意 任務(wù) TaskStart 的名稱是無所謂的 叫什么名 3 14 字都可以 因?yàn)?C OS 已經(jīng)將空閑任務(wù)的優(yōu)先級設(shè)為最低 即 OS LOWEST PR10 統(tǒng)計 任務(wù)的優(yōu)先級設(shè)為次低 OS LOWEST PR10 1 啟動任務(wù) TaskStart 總是優(yōu)先級最高的任 務(wù) 圖 F3 4 解釋初始化統(tǒng)計任務(wù)時的流程 用戶必須首先調(diào)用的是 C OS 中的系統(tǒng)初 始化函數(shù) OSInit 該函數(shù)初始化 C OS 圖 F3 4 2 有的處理器 例如 Motorola 的 MC68HC11 不需要 設(shè)置 中斷向量 中斷向量已經(jīng)在 ROM 中有了 用戶必須調(diào)用 OSTaskCreat 或者 OSTaskCreatExt 以建立 TaskStart 圖 F3 4 3 進(jìn)入多任務(wù)的條 件準(zhǔn)備好了以后 調(diào)用系統(tǒng)啟動函數(shù) OSStart 這個函數(shù)將使 TaskStart 開始執(zhí)行 因 為 TaskStart 是優(yōu)先級最高的任務(wù) 圖 F3 4 4 圖 F3 4 統(tǒng)計任務(wù)的初始化 TaskStart 負(fù)責(zé)初始化和啟動時鐘節(jié)拍 圖 F3 4 5 在這里啟動時鐘節(jié)拍是必要的 因 為用戶不會希望在多任務(wù)還沒有開始時就接收到時鐘節(jié)拍中斷 接下去 TaskStart 調(diào)用 統(tǒng)計初始化函數(shù) OSStatInit 圖 F3 4 6 統(tǒng)計初始化函數(shù) OSStatInit 決定在沒有 其它應(yīng)用任務(wù)運(yùn)行時 空閑計數(shù)器 OSIdleCtr 的計數(shù)有多快 奔騰 II 微處理器以 333MHz 運(yùn)行時 加 1 操作可以使該計數(shù)器的值達(dá)到每秒 15 000 000 次 OSIdleCtr 的值離 32 位計數(shù)器的溢出極限值 4 294 967 296 還差得遠(yuǎn) 微處理器越來越快 用戶要注意這里 可能會是將來的一個潛在問題 系統(tǒng)統(tǒng)計初始化任務(wù)函數(shù) OSStatInit 調(diào)用延遲函數(shù) OSTimeDly 將自身延時 2 個時 鐘節(jié)拍以停止自身的運(yùn)行 圖 F3 4 7 這是為了使 OSStatInit 與時鐘節(jié)拍同步 C OS 然后選下一個優(yōu)先級最高的進(jìn)入就緒態(tài)的任務(wù)運(yùn)行 這恰好是統(tǒng)計任務(wù) OSTaskStat 讀者會在后面讀到 OSTaskStat 的代碼 但粗看一下 OSTaskStat 所要 做的第一件事就是查看統(tǒng)計任務(wù)就緒標(biāo)志是否為 假 如果是的話 也要延時兩個時鐘節(jié) 3 15 拍 圖 F3 4 8 一定會是這樣 因?yàn)闃?biāo)志 OSStatRdy 已被 OSInit 函數(shù)初始化為 假 所以實(shí)際上 DSTaskStat 也將自己推入休眠態(tài) Sleep 兩個時鐘節(jié)拍 圖 F3 4 9 于是 任務(wù)切換到空閑任務(wù) OSTaskIdle 開始運(yùn)行 這是唯一一個就緒態(tài)任務(wù)了 CPU 處在空 閑任務(wù) OSTaskIdle 中 直到 TaskStart 的延遲兩個時鐘節(jié)拍完成 圖 3 4 10 兩個時 鐘節(jié)拍之后 TaskStart 恢復(fù)運(yùn)行 圖 F3 4 11 在執(zhí)行 OSStartInit 時 空閑計 數(shù)器 OSIdleCtr 被清零 圖 F3 4 12 然后 OSStatInit 將自身延時整整一秒 圖 F3 4 13 因?yàn)闆]有其它進(jìn)入就緒態(tài)的任務(wù) OSTaskIdle 又獲得了 CPU 的控制權(quán) 圖 F3 4 14 一秒鐘以后 TaskStart 繼續(xù)運(yùn)行 還是在 OSStatInit 中 空閑計數(shù)器將 1 秒鐘內(nèi)計數(shù)的值存入空閑計數(shù)器最大值 OSIdleCtrMax 中 圖 F3 4 15 OSStarInit 將統(tǒng)計任務(wù)就緒標(biāo)志 OSStatRdy 設(shè)為 真 圖 F3 4 16 以此來允許兩 個時鐘節(jié)拍以后 OSTaskStat 開始計算 CPU 的利用率 統(tǒng)計任務(wù)的初始化函數(shù) OSStatInit 的代碼如程序清單L3 13 所示 程序清單程序清單 L3 13L3 13 統(tǒng)計任務(wù)的初始化統(tǒng)計任務(wù)的初始化 void OSStatInit void OSTimeDly 2 OS ENTER CRITICAL OSIdleCtr 0L OS EXIT CRITICAL OSTimeDly OS TICKS PER SEC OS ENTER CRITICAL OSIdleCtrMax OSIdleCtr OSStatRdy TRUE OS EXIT CRITICAL 統(tǒng)計任務(wù) OSStat 的代碼程序清單 L3 14 所示 在前面一段中 已經(jīng)討論了為什么要等待 統(tǒng)計任務(wù)就緒標(biāo)志 OSStatRdy L3 14 1 這個任務(wù)每秒執(zhí)行一次 以確定所有應(yīng)用程序 中的任務(wù)消耗了多少 CPU 時間 當(dāng)用戶的應(yīng)用程序代碼加入以后 運(yùn)行空閑任務(wù)的 CPU 時 間就少了 OSIdleCtr 就不會像原來什么任務(wù)都不運(yùn)行時有那么多計數(shù) 要知道 OSIdleCtr 的最大計數(shù)值是 OSStatInit 在初始化時保存在計數(shù)器最大值 OSIdleCtrMax 中 的 CPU 利用率 表達(dá)式 3 1 是保存在變量 OSCPUsage L3 14 2 中的 3 1 表達(dá)式 Need to typeset the equation 一旦上述計算完成 OSTaskStat 調(diào)用任務(wù)統(tǒng)計外界接入函數(shù) OSTaskStatHook L3 14 3 這是一個用戶可定義的函數(shù) 這個函數(shù)能使統(tǒng)計任務(wù)得到擴(kuò)展 這樣 用戶 可以計算并顯示所有任務(wù)總的執(zhí)行時間 每個任務(wù)執(zhí)行時間的百分比以及其它信息 參見 1 09 節(jié)例 3 程序清單程序清單 L3 14L3 14 統(tǒng)計任務(wù)統(tǒng)計任務(wù) void OSTaskStat void pdata 3 16 INT32U run INT8S usage pdata pdata while OSStatRdy FALSE 1 OSTimeDly 2 OS TICKS PER SEC for OS ENTER CRITICAL OSIdleCtrRun OSIdleCtr run OSIdleCtr OSIdleCtr 0L OS EXIT CRITICAL if OSIdleCtrMax 0L usage INT8S 100L 100L run OSIdleCtrMax 2 if usage 100 OSCPUUsage 100 else if usage 0 C OS 將被返回到被中斷了的任務(wù) 以上描述的詳細(xì)解釋如圖 F3 5 所示 中斷來到了 F3 5 1 但還不能被被 CPU 識別 也許是因?yàn)橹袛啾?C OS 或用戶應(yīng)用程序關(guān)了 或者是因?yàn)?CPU 還沒執(zhí)行完當(dāng)前指令 一旦 CPU 響應(yīng)了這個中斷 F3 5 2 CPU 的中斷向量 至少大多數(shù)微處理器是如此 跳轉(zhuǎn) 到中斷服務(wù)子程序 F3 5 3 如上所述 中斷服務(wù)子程序保存 CPU 寄存器 也叫做 CPU context F3 5 4 一旦做完 用戶中斷服務(wù)子程序通知 C OS 進(jìn)入中斷服務(wù)子程 序了 辦法是調(diào)用 OSIntEnter 或者給 OSIntNesting 直接加 1 F3 5 5 然后用戶中斷 服務(wù)代碼開始執(zhí)行 F3 5 6 用戶中斷服務(wù)中做的事要盡可能地少 要把大部分工作留給 任務(wù)去做 中斷服務(wù)子程序通知某任務(wù)去做事的手段是調(diào)用以下函數(shù)之一 OSMboxPost OSQPost OSQPostFront OSSemPost 中斷發(fā)生并由上述函數(shù)發(fā)出消息時 接收消 息的任務(wù)可能是 也可能不是掛起在郵箱 隊列或信號量上的任務(wù) 用戶中斷服務(wù)完成以 后 要調(diào)用 OSIntExit F3 5 7 從時序圖上可以看出 對被中斷了的任務(wù)說來 如果 沒有高優(yōu)先級的任務(wù)被中斷服務(wù)子程序激活而進(jìn)入就緒態(tài) OSIntExit 只占用很短的運(yùn)行 時間 進(jìn)而 在這種情況下 CPU 寄存器只是簡單地恢復(fù) F3 5 8 并執(zhí)行中斷返回指令 F3 5 9 如果中斷服務(wù)子程序使一個高優(yōu)先級的任務(wù)進(jìn)入了就緒態(tài) 則 OSIntExit 將占 用較長的運(yùn)行時間 因?yàn)檫@時要做任務(wù)切換 F3 5 10 新任務(wù)的寄存器內(nèi)容要恢復(fù)并執(zhí)行 中斷返回指令 F3 5 12 3 18 圖 3 5 中斷服務(wù) 進(jìn)入中斷函數(shù) OSIntEnter 的代碼如程序清單 L3 16 所示 從中斷服務(wù)中退出函數(shù) OSIntExit 的代碼如程序清單 L3 17 所示 如前所述 OSIntEnter 所做的事是非常少的 程序清單程序清單 L3 16 通知通知 C OS C OS 中斷服務(wù)子程序開始了 中斷服務(wù)子程序開始了 void OSIntEnter void OS ENTER CRITICAL OSIntNesting OS EXIT CRITICAL 程序清單程序清單 L3 17 通知通知 C OS C OS 脫離了中斷服務(wù) 脫離了中斷服務(wù) void OSIntExit void OS ENTER CRITICAL 1 if OSIntNesting OSLockNesting 0 2 OSIntExitY OSUnMapTbl OSRdyGrp 3 3 19 OSPrioHighRdy IN

溫馨提示

  • 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論