ucos學習筆記

前一段時間筆者學習uCOS-III,第一次接觸OS這個概念吧。下面把個人的學習筆記分享出來,僅供參考。

1、前後臺系統:後臺程序是一個死循環,也稱爲“ 任務級 ”,前臺程序則是中斷服務程序,也稱爲“ 中斷級 ”;一般的低成本應用多采用這種程序結構。

2、實時內核:僅爲一段軟件代碼,它把系統功能劃分爲多個任務,每個任務只完成特定的一個功能,通常都爲死循環;CPU在任意時刻只能執行一個任務,但每個任務都認爲自己在獨自使用整個CPU,由於處理器速度非常快,任務切換的速度也非常快,所以看起來幾乎多個任務同時被執行;對多任務的管理就是實時內核所要做的工作,實現CPU資源的最大化利用。

3、uC/OS-III是一個可剝奪型內核(搶佔式內核,Preemptive Kernel),它總是執行當前就緒任務中優先級最高的那個;uC/OS-III被設計用於32位處理器; uC/OS-III至少需要4KB RAM資源的微控制器上運行

4、uC/OS-III的特性:

l 同優先級任務的時間片輪轉調度
l 任務數目不受限制
l 優先級數目不受限制
l 內核對象數目不受限制
l 可嵌套的任務掛起(suspension),嵌套掛起深度最大可達250層
l 直接向任務發送信號
l 直接向任務發送消息
l 任務級時鐘節拍處理
5、臨界段代碼:不可被打斷的代碼(在運行這些代碼時,需要關閉中斷,運行完後再開啓)。有兩種方式保護臨界段代碼:1、關中斷;2、調度器上鎖。兩種方法均可以測得中斷關閉時間

6、任務的類型有兩種:運行至完成型、無限循環型(大多數嵌入式系統採用這種);任務與C函數不同,任務不允許返回;在創建一個任務時,必須爲任務分配一個任務控制塊(OS_TCB);每一個任務都要有屬於自己的棧(類型爲CPU_STK);每一個任務都必須調用一個可以引發任務“等待某事件”的函數,比如一段延遲結束(OSTimeDly()或OSTimeDlyHMSM()),在等待一個事件時,它不會佔用CPU時間,這是與前後臺系統不同的地方;任務的三個重要參數:任務控制模塊TCB、優先級、棧空間(存放局部變量、函數調用返回地址、ISR嵌套。如果出現一些很奇怪的結果,首先懷疑佔空間是否給小了);每個任務都有自己獨立的CPU寄存器

7、uC/OS-III 允許任務停止自身或者停止另外的任務。停止一個任務意味着這個任務將不再執行直到被其他的任務恢復。停止可以被嵌套到250級。換句話說,一個任務可以停止另外的任務多達250次。當然,這個任務必須被恢復同等次數纔有資格再次獲得CPU。

8、OSInit()會創建2~5個任務,其中空閒任務(OS_IdleTask())和時鐘節拍任務(OS_TickTask())是必須要創建的2個任務,其他的統計任務(OS_StatTask())、定時任務(OS_TmrTask())和中斷處理隊列管理任務(OS_IntQTask())由#define使能;main函數必須在調用其他任務uC/OS-III函數之前調用OSInit()

l 空閒任務(OS_IdleTask(),os_core.c)
【必須創建】uC/OS-III創建的第一個任務,優先級總是OS_CFG_PRIO_MAX-1(最低優先級)

真正的無限循環,即不會調用任務會使其進入等待狀態的服務函數

l 時鐘節拍任務(OS_TickTask(),os_tick.c)
【必須創建】該任務的優先級應當只比用戶的系統中最重要的任務的優先級略低一點[注:P77]

時鐘節拍列表=數據表(OSCfg_TickWheel[])+計數器(OSTickCtr),數據表的表項數目OS_CFG_TICK_WHEEL_SIZE一般設置爲任務數的1/4左右,且最好爲素數;每當時鐘節拍任務接收到時鐘節拍ISR發送的信號量時,OSTickCtr自動+1

每次節拍中斷髮生時,只有其中一個表項上的任務可能延遲結束

l 統計任務(OS_StatTask(),os_stat.c)
總CPU利用率、各任務的CPU利用率和各任務的堆棧使用量

在main()函數創建的第一個也是唯一一個應用任務中調用OSStatTaskCPUUsageInit(),這個應用任務應該分配一個很高的優先級(0除外);uC/OS-III允許用戶在調用OSStart()之前創建任意數目的任務,然而,要使用統計任務時,只能創建一個任務,在該任務中調用OSStatTaskCPUUsageInit()。

l 定時任務(OS_TmrTask(),os_tmr.c)
一個遞減的計數器,減爲0時,可以啓動一個用戶自定義的回調函數(Callback Funcion),避免在回調函數中使用阻塞調用(OSTimeDly()、OSTimeDlyHMSM()、OS???Pend()),回調函數的執行實在定時器任務內完成的;與時鐘節拍任務使用相同的中斷源

優先級一般爲中等優先級

l 中斷處理隊列管理任務(OS_IntQTask(),os_int.c)
相當於在ISR和任務中插入了一腳,負責“延遲”(deferring)在ISR中調用的系統post服務函數的行爲[注:P86]

優先級永遠爲最高的0,系統保留優先級

9、通過OSTaskCreate()函數創建一個任務,該任務有13個參數

10、任務的優先級:數值越小,優先級越高,其範圍爲1~(OS_CFG_PRIO_MAX-2);0和OS_CFG_PRIO_MAX-1爲兩個保留的優先級

11、多任務系統管理函數OSStart()一般爲main函數的最後一步,注意:uC/OS-III會首先運行在調用OSStart()之前已經創建的優先級最高的任務,並且可以創建任務數量的任務,但是建議只創建一個任務[注:P33]

12、任務狀態:從用戶角度來看,任務的狀態只有5種:休眠態、就緒態、運行態、等待態和中斷服務態;在uC/OS-III內部,狀態則有8種:延遲、就緒、帶超時檢測的等待、等待、延遲被掛起、被掛起、帶超時檢測的等待且被掛起和等待且被掛起

13、任務被刪除OSTaskDel(),代表任務進入休眠態,使得該代碼無法獲得CPU的使用權

14、一個任務可以創建其它任務(OSTaskCreate())、停止或者恢復其它(OSTaskSuspned()和OSTaskResume())、提交信號量到其它任務、發送消息到其它任務、提供共享資源等。換句話說,任務不是隻被限制於“等待事件”。

15、就緒表=就緒優先級位映射表OSPrioTbl[](標明哪個優先級下有任務就緒)+就緒任務列表OSRdyList[](包含指向就緒任務的指針)

16、擁有“ 計算前導零 ”(CLZ , Count Leading Zeros)的處理器可以加速查找最高優先級任務的過程

17、uC/OS-III有兩種不同方法處理中斷服務程序發佈的事件:直接發佈(direct post)和延遲發佈(deferred post),其最終的結果都是高優先級的任務獲得了CPU控制權,但是延遲發佈多了一箇中斷處理任務,ISR發佈消息後由ISR hander task接管,而非“直接發佈”中的直接跳轉到高優先級的任務中(這樣做是爲了避免使用關中斷的方法來保護臨界段代碼);直接發佈,uC/OS-III必須關閉中斷以保護臨界段代碼,防止中斷處理程序訪問這些臨界段代碼;延遲發佈,uC/OS-III通過給任務調度器上鎖的方式來保護臨界段代碼

18、時間片輪轉調度:當兩個或更多的任務擁有相同的優先級時,uC/OS-III允許一個任務運行一段指定的時間,然後輪到下一個任務;如果一個任務不需要執行完時間片,則主動放棄CPU的控制權讓下一個任務運行,稱爲“禮讓”(yielding)

19、任務調度通過兩個函數來執行:OSSched()(任務級代碼使用)和OSIntExit()(中斷服務程序結束時使用);OSSched()的任務切換部分的工作由OSCtxSw()完成,OSIntExit( )中任務的切換工作由OSIntCtxSw()完成

20、時鐘節拍通常頻率設置爲10~1000Hz,過高的頻率會增加系統的額外開銷

21、當一個任務等待信號量、互斥型信號量、事件標誌組和消息隊列時,該任務就被放入任務掛起表(pend lists)或等待表中(wait lists)

22、常見時間服務用戶程序:

OSTimeDly()任務延時n個時鐘節拍;三種模式(相對模式、週期模式、絕對模式,推薦使用週期模式以獲得長時間運行的週期性延遲,比如週期掃描鍵盤,週期採集某傳感器的值,絕對模式一般用於上電後指定的時間執行具體動作,比如上電10s後關閉某盞燈)

OSTimeDlyHMSM() 任務延時指定的時間,採用“時:分:秒:毫秒”方式;延遲精度極大取決與時鐘節拍頻率,如果頻率設定爲1000Hz,那麼延時的精度爲1ms

OSTimeDlyResume()恢復被延遲的任務;謹慎使用,因爲它無法分辨是延時結束還是被恢復

OSTimeGet() 獲取當前時鐘節拍計數器的值

OSTimeSet() 設置時鐘節拍計數器的值

OSTimeTick() 觸發一次時鐘節拍任務;每次時鐘節拍中斷到來時,中斷服務程序必須調用該函數

23、uC/OS-III中定時器的時間分辨率由定時器任務頻率來配置(OS_CFG_TMR_TASK_RATE_HZ),若定時器任務頻率爲10Hz,那麼所有定時器的時間分辨率爲1/10s;定時器的運行模式有三種:單次定時器、週期定時器(無初始延遲)、週期定時器(有初始延遲)

24、最常用的獨佔共享資源和創建臨界區的方法:

l關中斷不推薦,會增加系統中斷延遲;而這種方法也是任務和中斷服務程序共享變量的唯一方法
l 禁止任務調度 不推薦,有悖於可剝奪型內核的設計初衷,因爲該任務即爲最高優先級任務
l 使用信號量 速度比互斥型信號量稍快一些,但是會遇到優先級反轉問題
l 使用互斥型信號量(mutex) 比信號量稍慢,但是解決了優先級反轉問題
25、信號量就像一種上鎖機制,必須獲得對應的鑰匙才能執行代碼;信號量通常分爲兩種:二進制信號量、計數型信號量;在共享資源時,只有任務才能使用信號量,中斷服務程序則不能使用,當用信號量發送信號時,則沒有限制;信號量一般用於訪問I/O設備

26、在使用信號量之前必須先創建信號量

27、無界優先級反轉問題:低優先級的任務正在訪問某共享資源,此時高優先級的任務進行內核剝奪,搶走CPU使用權,但是高優先級也要訪問該共享資源,因此調度器再次轉回低優先級任務等待其釋放信號量,如果此時有中優先級的任務插入,那麼調度器會直接進入該任務,忽略高優先級的任務。導致的結果就是高優先級反轉。解決辦法:互斥型信號量(mutex),原理爲將使用共享資源的低優先級的任務提升至與高優先級任務一樣,此時調度器再次返回低優先級任務,等待其執行完畢釋放信號量後回到高優先級處繼續執行,中優先級則不會插入。因此,低優先級的任務訪問共享資源的速度越快越好

28、如果沒有任務對共享資源的訪問有截止時間,那麼普通信號量就可以替代互斥型信號量

29、死鎖(deadlock)也稱爲抱死(deadly embrace),指兩個任務無限制的等待對方控制的資源。解決辦法:

l 先得到全部資源,再進行下一步操作
l 用相同的順序申請多個資源
l 在調用請求信號量的函數時設定超過時間
30、uC/OS-III中有兩種基本的同步機制:信號量和事件標誌(第三種爲任務信號量)

31、任務或者ISR可以使用信號量同步任務,這種同步操作叫做單向同步;當多個任務等待同一個信號量時,可以在發佈信號時指定OS_OPT_POST_ALL開啓“廣播”功能;任務或者ISR也可以使用任務信號量同步任務,這種方法比較常用,在uC/OS-III中,每個任務都有自己的內嵌信號量;事件標誌給與了任務同步更多的同步選擇和方法,在事件標誌組(OS_FLAG_GRP)中可以用“與AND”“或OR”產生更多的不同事件(flag)組合,注意:事件標誌組必須在啓動uC/OS-III 之前創建

32、如果任務或者ISR需要給單個任務發信號,則使用任務信號量更爲恰當,因爲此時不需要再聲明一個外部信號量對象,而且任務信號服務函數的執行速度比信號服務函數的執行速度要快

33、消息傳遞:任務或者中斷服務程序需要交流信息,這種交流有兩種途徑:

l 全局變量
如果一個資源有中斷服務程序的參與,唯一保證對共享變量獨佔訪問的方法就是關中斷

如果只是兩個任務共享數據:關中斷、給調度器上鎖、使用信號量或者使用互斥型信號量(推薦)

注意:任務想要與中斷服務通訊,只能通過全局變量

l 發佈消息
34、消息隊列的相關函數,中斷服務程序只能調用OSQPost();消息隊列的讀取一般採用先進先出(FIFO),有時候也會使用後進先出(LIFO)的方式;消息的獲取可以設置按照優先級或者廣播

35、更爲廣泛使用的消息隊列一般爲任務內建的消息隊列(更高效,不用創建外部消息隊列,如同信號量與任務信號量的關係)。

36、同事件標誌組,消息隊列也要求在啓動uC/OS-III 之前創建

37、發送的消息通常是一個指針,這些數據必須保持不變,直到接收者完成相應的數據處理

38、移植uC/OS-III需要修改的文件:

l uC/CPU:cpu.h(數據類型與字長)、cpu_c.c(中斷控制器)、cpu_a.asm(開、關中斷,CLZ指令)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章