加入星計劃,您可以享受以下權益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴散
  • 作品版權保護
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
    • 一、 單任務系統(tǒng)(裸機)
    • 二、多任務系統(tǒng)(帶OS)
  • 相關推薦
  • 電子產(chǎn)業(yè)圖譜
申請入駐 產(chǎn)業(yè)圖譜

FreeRTOS學習筆記 | 基礎知識體系梳理

2022/09/19
1654
閱讀需 30 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

我發(fā)現(xiàn)學習 RTOS 是學習 Linux 內(nèi)核的好方法。大有彎道超車的可能。

1. 任務堆棧

2. 任務狀態(tài)

3. 任務優(yōu)先級

4. 任務調(diào)度

5. 臨界區(qū)、鎖與系統(tǒng)時間

  • 1.1 任務棧大小確定

    1.2 棧溢出檢測機制

    3.1任務優(yōu)先級說明

    3.2 任務優(yōu)先級分配方案

    3.3 任務優(yōu)先級與終端優(yōu)先級的區(qū)別

    4.1 調(diào)度器

    5.1 臨界區(qū)與開關中斷

    5.2 鎖

    5.3 FreeRTOS 系統(tǒng)時鐘節(jié)拍和時間管理

一、 單任務系統(tǒng)(裸機)

主要是采用超級循環(huán)系統(tǒng)(前后臺系統(tǒng)),應用程序是一個無限的循環(huán),循環(huán)中調(diào)用相應的函數(shù)完成相應的操作,這部分可以看做后臺行為;中斷服務程序處理異步事件,這部分可以看做是前臺行為。后臺也可以叫做任務級,前臺也叫作中斷級。

前后臺系統(tǒng)的編程思路有兩種:輪詢方式(實時性得不到保障,緊急與非緊急消息不能有效管理)、中斷方式(可以保證一定的實時性,緊急消息可以得到響應)。

 

采用中斷和查詢結(jié)合的方式可以解決大部分裸機應用,但隨著工程的復雜,裸機方式的缺點就暴露出來了:

必須在中斷(ISR)內(nèi)處理時間關鍵運算:

ISR 函數(shù)變得非常復雜,并且需要很長執(zhí)行時間。

ISR 嵌套可能產(chǎn)生不可預測的執(zhí)行時間和堆棧需求。

超級循環(huán)和 ISR 之間的數(shù)據(jù)交換是通過全局共享變量進行的:應用程序的程序員必須確保數(shù)據(jù)一致性。

超級循環(huán)可以與系統(tǒng)計時器輕松同步,但:

如果系統(tǒng)需要多種不同的周期時間,則會很難實現(xiàn)。

超過超級循環(huán)周期的耗時函數(shù)需要做拆分。

增加軟件開銷,應用程序難以理解。

超級循環(huán)使得應用程序變得非常復雜,因此難以擴展:一個簡單的更改就可能產(chǎn)生不可預測的副作用,對這種副作用進行分析非常耗時。超級循環(huán)概念的這些缺點可以通過使用實時操作系統(tǒng) (RTOS) 來解決。

二、多任務系統(tǒng)(帶OS)

采用多任務系統(tǒng)可以以上的裸機開發(fā)遇到的4大缺點。

 

RTOS的實現(xiàn)重點就在這個OS任務調(diào)度器上,調(diào)度器的作用就是使用相關的調(diào)度算法來決定當前需要執(zhí)行的任務。

FreeRTOS就是一款支持多任務運行的實時操作系統(tǒng),具有時間片、搶占式和合作式三種調(diào)度方式。通過 FreeRTOS 實時操作系統(tǒng)可以將程序函數(shù)分成獨立的任務,并為其提供合理的調(diào)度方式。

1. 任務堆棧

 

棧大小 0x400 = 1024,單位字節(jié)。在RTOS下,上面截圖里設置的棧大小有了一個新名字叫做系統(tǒng)棧空間,而任務棧是不使用這里的空間,哪里使用這里的棧空間呢,實際上是中斷函數(shù)和中斷嵌套。

由于 Cortex-M3 和 M4 內(nèi)核具有雙堆棧指針,MSP 主堆棧指針和 PSP 進程堆棧指針,或者叫 PSP 任務堆棧指針也是可以的。在 FreeRTOS 操作系統(tǒng)中,主堆棧指針 MSP 是給系統(tǒng)??臻g使用的,進 程堆棧指針 PSP 是給任務棧使用的。也就是說,在 FreeRTOS 任務中,所有??臻g的使用都是通過 PSP 指針進行指向的。一旦進入了中斷函數(shù)以及可能發(fā)生的中斷嵌套都是用的 MSP 指針。這個知識 點要記住它,當前可以不知道這是為什么,但是一定要記住。

實際應用中系統(tǒng)棧空間分配多大,主要是看可能發(fā)生的中斷嵌套層數(shù),下面我們就按照最壞執(zhí)行情況 進行考慮,所有的寄存器都需要入棧,此時分為兩種情況:

64 字節(jié):對于 Cortex-M3 內(nèi)核和未使用 FPU(浮點運算單元)功能的 Cortex-M4 內(nèi)核在發(fā)生中斷時需要將 16 個通用寄存器全部入棧,每個寄存器占用 4 個字節(jié),也就是 16*4 = 64 字節(jié)的空間。可能發(fā)生幾次中斷嵌套就是要 64 乘以幾即可。當然,這種是最壞執(zhí)行情況,也就是所有的寄存器都入棧。(注:任務執(zhí)行的過程中發(fā)生中斷的話,有 8 個寄存器是自動入棧的,這個棧是任務棧,進入中斷以后其余寄存器入棧以及發(fā)生中斷嵌套都是用的系統(tǒng)棧)

200 字節(jié): 對于具有 FPU(浮點運算單元)功能的 Cortex-M4 內(nèi)核,如果在任務中進行了浮點運算,那么在發(fā)生中斷的時候除了 16 個通用寄存器需要入棧,還有 34 個浮點寄存器也是要入棧的,也就是(16+34)*4 = 200 字節(jié)的空間。當然,這種是最壞執(zhí)行情況,也就是所有的寄存器都入棧。

1.1 任務棧大小確定

函數(shù)的棧大小計算起來是比較麻煩的,那么有沒有簡單的辦法來計算呢?有的,一般 IDE 開發(fā)環(huán)境都有這樣的功能,比如 MDK 會生成一個 htm 文件,通過這個文件用戶可以知道每個被調(diào)用函數(shù)的最大棧需求以及各個函數(shù)之間的調(diào)用關系。但是 MDK 無法確定通過函數(shù)指針實現(xiàn)函數(shù)調(diào)用時的棧需求。另外,發(fā)生中斷或中斷嵌套時的現(xiàn)場保護需要的??臻g也不會統(tǒng)計。

一般來說,用戶可以事先給任務分配一個大的??臻g,然后通過打印任務棧的使用情況,運行一段時間就會有個大概的范圍了。這種方法比較簡單且實用些。

1.2 棧溢出檢測機制

棧生長方向從高地址向低地址生長(M4 和 M3 是這種方式)

 

上圖標識 3 的位置是局部變量 int i 和 int array[10]占用的??臻g,但申請了??臻g后已經(jīng)越界了。這個就是所謂的棧溢出了。如果用戶在函數(shù) test 中通過數(shù)組 array 修改了這部分越界區(qū)的數(shù)據(jù)且這部分越界的棧空間暫時沒有用到或者數(shù)據(jù)不是很重要,情況還不算嚴重,但是如果存儲的是關鍵數(shù)據(jù),會直接導致系統(tǒng)崩潰。

上圖標識 4 的位置是局部變量申請了??臻g后,棧指針向下偏移(返回地址+變量 i+10 個數(shù)組元素)*4 =48 個字節(jié)。

上圖標識 5 的位置可能是其它任務的??臻g,也可能是全局變量或者其它用途的存儲區(qū),如果 test函數(shù)在使用中還有用到棧的地方就會從這里申請,這部分越界的空間暫時沒有用到或者數(shù)據(jù)不是很重要,情況還不算嚴重,但是如果存儲的是關鍵數(shù)據(jù),會直接導致系統(tǒng)崩潰。

FreeRTOS 提供了兩種棧溢出檢測機制,這兩種檢測都是在任務切換時才會進行:

在任務切換時檢測任務棧指針是否過界了,如果過界了,在任務切換的時候會觸發(fā)棧溢出鉤子函數(shù)。void vApplicationStackOverflowHook( TaskHandle_t xTask,signed char *pcTaskName ); 用戶可以在鉤子函數(shù)里面做一些處理。這種方法不能保證所有的棧溢出都能檢測到。比如任務在執(zhí)行的過程中出現(xiàn)過棧溢出。任務切換前棧指針又恢復到了正常水平,這種情況在任務切換的時候是檢測不到的。又比如任務棧溢出后,把這部分棧區(qū)的數(shù)據(jù)修改了,這部分棧區(qū)的數(shù)據(jù)不重要或者暫時沒有用到還好,但如果是重要數(shù)據(jù)被修改將直接導致系統(tǒng)進入硬件異常,這種情況下,棧溢出檢測功能也是檢測不到的。

使用方法一需要用戶在 FreeRTOSConfig.h 文件中配置如下宏定義:

#define configCHECK_FOR_STACK_OVERFLOW 1

任務創(chuàng)建的時候?qū)⑷蝿諚K袛?shù)據(jù)初始化為 0xa5,任務切換時進行任務棧檢測的時候會檢測末尾的 16 個字節(jié)是否都是 0xa5,通過這種方式來檢測任務棧是否溢出了。相比方法一,這種方法的速度稍慢些,但是這樣就有效地避免了方法一里面的部分情況。不過依然不能保證所有的棧溢出都能檢測到,比如任務棧末尾的 16 個字節(jié)沒有用到,即沒有被修改,但是任務棧已經(jīng)溢出了,這種情況是檢測不到的。另外任務棧溢出后,任務棧末尾的 16 個字節(jié)沒有修改,但是溢出部分的棧區(qū)數(shù)據(jù)被修改了,這部分棧區(qū)的數(shù)據(jù)不重要或者暫時沒有用到還好,但如果是重要數(shù)據(jù)被修改將直接導致系統(tǒng)進入硬件異常,這種情況下,棧溢出檢測功能也是檢測不到的。

使用方法二需要用戶在 FreeRTOSConfig.h 文件中配置如下宏定義:

#define configCHECK_FOR_STACK_OVERFLOW 2

除了 FreeRTOS 提供的這兩種棧溢出檢測機制,還有其它的棧溢出檢測機制,大家可以在 Mircrium 官方發(fā)布的如下這個博文中學習:https://www.micrium.com/detecting-stack-overflows-part-2-of-2/

2. 任務狀態(tài)

FreeRTOS的任務狀態(tài)(4種):1.運行態(tài)(Running) 2.就緒態(tài)(Ready) 3.阻塞態(tài)(Blocked) 4.掛起態(tài)(Suspended)

ucos的任務狀態(tài)(5種):1.睡眠狀態(tài) 2.就緒狀態(tài) 3.等待狀態(tài) 4.中斷服務狀態(tài) 5.執(zhí)行狀態(tài)

Running—運行態(tài)

當任務處于實際運行狀態(tài)被稱之為運行態(tài),即 CPU 的使用權被這個任務占用。

Ready—就緒態(tài)

處于就緒態(tài)的任務是指那些能夠運行(沒有被阻塞和掛起),但是當前沒有運行的任務,因為同優(yōu)先 級或更高優(yōu)先級的任務正在運行。

Blocked—阻塞態(tài)

由于等待信號量,消息隊列,事件標志組等而處于的狀態(tài)被稱之為阻塞態(tài),另外任務調(diào)用延遲函數(shù)也 會處于阻塞態(tài)。

Suspended—掛起態(tài)

類似阻塞態(tài),通過調(diào)用函數(shù) vTaskSuspend()對指定任務進行掛起,掛起后這個任務將不被執(zhí)行,只 有調(diào)用函數(shù) xTaskResume()才可以將這個任務從掛起態(tài)恢復。

 

3. 任務優(yōu)先級

3.1任務優(yōu)先級說明

FreeRTOS 中任務的最高優(yōu)先級是通過 FreeRTOSConfig.h 文件中的 configMAX_PRIORITIES 進行配置的,用戶實際可以使用的優(yōu)先級范圍是 0 到 configMAX_PRIORITIES – 1。比如我們配置此宏定義為 5,那么用戶可以使用的優(yōu)先級號是 0,1,2,3,4,不包含 5,對于這一點,初學者要特別的注意。

用戶配置任務的優(yōu)先級數(shù)值越小,那么此任務的優(yōu)先級越低,空閑任務的優(yōu)先級是 0。

建議用戶配置宏定義 configMAX_PRIORITIES 的最大值不要超過 32,即用戶任務可以使用的優(yōu)先級范圍是0到31。

3.2 任務優(yōu)先級分配方案

 

IRQ 任務:IRQ 任務是指通過中斷服務程序進行觸發(fā)的任務,此類任務應該設置為所有任務里面優(yōu)先級最高的。

高優(yōu)先級后臺任務:比如按鍵檢測,觸摸檢測,USB 消息處理,串口消息處理等,都可以歸為這一類任務。

低優(yōu)先級的時間片調(diào)度任務:比如 emWin 的界面顯示,LED 數(shù)碼管的顯示等不需要實時執(zhí)行的都可以歸為這一類任務。實際應用中用戶不必拘泥于將這些任務都設置為優(yōu)先級 1 的同優(yōu)先級任務,可以設置多個優(yōu)先級,只需注意這類任務不需要高實時性。

空閑任務:空閑任務是系統(tǒng)任務。

特別注意:IRQ 任務和高優(yōu)先級任務必須設置為阻塞式(調(diào)用消息等待或者延遲等函數(shù)即可),只有這樣,高優(yōu)先級任務才會釋放 CPU 的使用權,,從而低優(yōu)先級任務才有機會得到執(zhí)行。這里的優(yōu)先級分配方案是我們推薦的一種方式,實際項目也可以不采用這種方法。調(diào)試出適合項目需求的才是最好的。

3.3 任務優(yōu)先級與終端優(yōu)先級的區(qū)別

這兩個之間沒有任何關系,不管中斷的優(yōu)先級是多少,中斷的優(yōu)先級永遠高于任何任務的優(yōu)先級,即任務在執(zhí)行的過程中,中斷來了就開始執(zhí)行中斷服務程序。

另外對于 STM32F103,F(xiàn)407 和 F429 來說,中斷優(yōu)先級的數(shù)值越小,優(yōu)先級越高。而 FreeRTOS的任務優(yōu)先級是,任務優(yōu)先級數(shù)值越小,任務優(yōu)先級越低。

4. 任務調(diào)度

FreeRTOS就是一款支持多任務運行的實時操作系統(tǒng),具有時間片、搶占式和合作式三種調(diào)度方式。

合作式調(diào)度,主要用在資源有限的設備上面,現(xiàn)在已經(jīng)很少使用了。出于這個原因,后面的 FreeRTOS 版本中不會將合作式調(diào)度刪除掉,但也不會再進行升級了。

搶占式調(diào)度,每個任務都有不同的優(yōu)先級,任務會一直運行直到被高優(yōu)先級任務搶占或者遇到阻塞式的 API 函數(shù),比如 vTaskDelay。

時間片調(diào)度,每個任務都有相同的優(yōu)先級,任務會運行固定的時間片個數(shù)或者遇到阻塞式的 API 函數(shù),比如vTaskDelay,才會執(zhí)行同優(yōu)先級任務之間的任務切換。

4.1 調(diào)度器

調(diào)度器就是使用相關的調(diào)度算法來決定當前需要執(zhí)行的任務。所有的調(diào)度器有一個共同的 特性:

調(diào)度器可以區(qū)分就緒態(tài)任務和掛起任務(由于延遲,信號量等待,郵箱等待,事件組等待等原因而使 得任務被掛起)。
調(diào)度器可以選擇就緒態(tài)中的一個任務,然后激活它(通過執(zhí)行這個任務)。當前正在執(zhí)行的任務是運 行態(tài)的任務。

不同調(diào)度器之間最大的區(qū)別就是如何分配就緒態(tài)任務間的完成時間。

嵌入式實時操作系統(tǒng)的核心就是調(diào)度器和任務切換,調(diào)度器的核心就是調(diào)度算法。任務切換的實現(xiàn)在不同的嵌 入式實時操作系統(tǒng)中區(qū)別不大,基本相同的硬件內(nèi)核架構,任務切換也是相似的。調(diào)度算法就有些區(qū)別了。

4.1.1 搶占式調(diào)度器

使用了搶占式調(diào)度,最高優(yōu)先級的任務一旦就緒,總能得到 CPU 的控制權。比如,當一個運行著的任務被其它高優(yōu)先級的任務搶占,當前任務的 CPU 使用權就被剝奪了,或者說被掛起了,那個高優(yōu)先級的任務立刻得到了 CPU 的控制權并運行。又比如,如果中斷服務程序使一個高優(yōu)先級的任務進入就緒態(tài),中斷完成時,被中斷的低優(yōu)先級任務被掛起,優(yōu)先級高的那個任務開始運行。使用搶占式調(diào)度器,使得最高優(yōu)先級的任務什么時候可以得到 CPU 的控制權并運行是可知的,同時使得任務級響應時間得以最優(yōu)化。

總的來說,學習搶占式調(diào)度要掌握的最關鍵一點是:每個任務都被分配了不同的優(yōu)先級,搶占式調(diào)度器會獲得就緒列表中優(yōu)先級最高的任務,并運行這個任務。

在 FreeRTOS 的配置文件 FreeRTOSConfig.h 中禁止使用時間片調(diào)度,那么每個任務必須配置不同的優(yōu)先級。當 FreeRTOS 多任務啟動執(zhí)行后,基本會按照如下的方式去執(zhí)行:

首先執(zhí)行的最高優(yōu)先級的任務 Task1,Task1 會一直運行直到遇到系統(tǒng)阻塞式的 API 函數(shù),比如延遲,事件標志等待,信號量等待,Task1 任務會被掛起,也就是釋放 CPU 的執(zhí)行權,讓低優(yōu)先級的任務得到執(zhí)行。

FreeRTOS 操作系統(tǒng)繼續(xù)執(zhí)行任務就緒列表中下一個最高優(yōu)先級的任務 Task2,Task2 執(zhí)行過程中有兩種情況:

Task1由于延遲時間到,接收到信號量消息等方面的原因,使得 Task1從掛起狀態(tài)恢復到就緒態(tài), 在搶占式調(diào)度器的作用下,Task2 的執(zhí)行會被 Task1 搶占。

Task2 會一直運行直到遇到系統(tǒng)阻塞式的 API 函數(shù),比如延遲,事件標志等待,信號量等待,Task2任務會被掛起,繼而執(zhí)行就緒列表中下一個最高優(yōu)先級的任務。

如果用戶創(chuàng)建了多個任務并且采用搶占式調(diào)度器的話,基本都是按照上面兩條來執(zhí)行。根據(jù)搶占式調(diào)度器,當前的任務要么被高優(yōu)先級任務搶占,要么通過調(diào)用阻塞式 API 來釋放 CPU 使用權讓低優(yōu)先級任務執(zhí)行,沒有用戶任務執(zhí)行時就執(zhí)行空閑任務.

 

4.1.2 時間片調(diào)度器

在小型的嵌入式 RTOS 中,最常用的的時間片調(diào)度算法就是 Round-robin 調(diào)度算法。這種調(diào)度算法可以用于搶占式或者合作式的多任務中。另外,時間片調(diào)度適合用于不要求任務實時響應的情況。

實現(xiàn) Round-robin 調(diào)度算法需要給同優(yōu)先級的任務分配一個專門的列表,用于記錄當前就緒的任務,并為每個任務分配一個時間片(也就是需要運行的時間長度,時間片用完了就進行任務切換)。

在 FreeRTOS 操作系統(tǒng)中只有同優(yōu)先級任務才會使用時間片調(diào)度,另外還需要用戶在FreeRTOSConfig.h 文件中使能宏定義:

#define configUSE_TIME_SLICING 1

默認情況下,此宏定義已經(jīng)在 FreeRTOS.h 文件里面使能了,用戶可以不用在FreeRTOSConfig.h 文件中再單獨使能。示例:

創(chuàng)建 4 個同優(yōu)先級任務 Task1,Task2,Task3 和 Task4。

先運行任務 Task1,運行夠 5 個系統(tǒng)時鐘節(jié)拍后,通過時間片調(diào)度切換到任務 Task2。

任務 Task2 運行夠 5 個系統(tǒng)時鐘節(jié)拍后,通過時間片調(diào)度切換到任務 Task3。

任務 Task3 在運行期間調(diào)用了阻塞式 API 函數(shù),調(diào)用函數(shù)時,雖然 5 個系統(tǒng)時鐘節(jié)拍的時間片大小還沒有用完,此時依然會通過時間片調(diào)度切換到下一個任務 Task4。(注意,沒有用完的時間片不會再使用,下次任務 Task3 得到執(zhí)行還是按照 5 個系統(tǒng)時鐘節(jié)拍運行)

任務 Task4 運行夠 5 個系統(tǒng)時鐘節(jié)拍后,通過時間片調(diào)度切換到任務 Task1。

 

 

5. 臨界區(qū)、鎖與系統(tǒng)時間

5.1 臨界區(qū)與開關中斷

代碼的臨界臨界區(qū),一旦這部分代碼開始執(zhí)行,則不允許任何中斷打斷。為確保臨界區(qū)代碼的執(zhí)行不被中斷,在進入臨界區(qū)之前須關中斷,而臨界區(qū)代碼執(zhí)行完畢后,要立即開中斷。

FreeRTOS 的源碼中有多處臨界段的地方, 臨界段雖然保護了關鍵代碼的執(zhí)行不被打斷, 但也會影響系統(tǒng)的實時性。比如此時某個任務正在調(diào)用系統(tǒng) API 函數(shù),而且此時中斷正好關閉了,也就是進入到了臨界區(qū)中,這個時候如果有一個緊急的中斷事件被觸發(fā),這個中斷就不能得到及時執(zhí)行,必須等到中斷開啟才可以得到執(zhí)行, 如果關中斷時間超過了緊急中斷能夠容忍的限度, 危害是可想而知的。

FreeRTOS 源碼中就有多處臨界段的處理,跟 FreeRTOS 一樣,uCOS-II 和 uCOS-III 源碼中都是有臨界段的,而 RTX 的源碼中不存在臨界段。另外,除了 FreeRTOS 操作系統(tǒng)源碼所帶的臨界段以外,用戶寫應用的時候也有臨界段的問題,比如以下兩種:

讀取或者修改變量(特別是用于任務間通信的全局變量)的代碼,一般來說這是最常見的臨界代碼。

調(diào)用公共函數(shù)的代碼,特別是不可重入的函數(shù),如果多個任務都訪問這個函數(shù),結(jié)果是可想而知的??傊?,對于臨界段要做到執(zhí)行時間越短越好,否則會影響系統(tǒng)的實時性。

重入函數(shù)的實現(xiàn)特征一般而言,重入函數(shù)具有如下特征:

函數(shù)內(nèi)部無整個軟件生命周期的變量(靜態(tài)變量)
未引用或者訪問整個軟件生命周期的變量(全局變量)

任務代碼臨界區(qū)處理

FreeRTOS 任務代碼中臨界段的進入和退出主要是通過操作寄存器 basepri 實現(xiàn)的。進入臨界段前操作寄存器 basepri 關閉了所有小于等于宏定義configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY所定義的中斷優(yōu)先級,這樣臨界段代碼就不會被中斷干擾到,而且實現(xiàn)任務切換功能的 PendSV 中斷和滴答定時器中斷是最低優(yōu)先級中斷,所以此任務在執(zhí)行臨界段代碼期間是不會被其它高優(yōu)先級任務打斷的。退出臨界段時重新操作 basepri 寄存器,即打開被關閉的中斷(這里我們不考慮不受 FreeRTOS 管理的更高優(yōu)先級中斷)。

中斷服務程序的臨界區(qū)處理

與任務代碼里臨界段的處理方式類似,中斷服務程序里面臨界段的處理也有一對開關中斷函數(shù)。

5.2 鎖

調(diào)度鎖

調(diào)度鎖就是 RTOS 提供的調(diào)度器開關函數(shù),如果某個任務調(diào)用了調(diào)度鎖開關函數(shù),處于調(diào)度鎖開和調(diào)度鎖關之間的代碼在執(zhí)行期間是不會被高優(yōu)先級的任務搶占的,即任務調(diào)度被禁止。這一點要跟臨界段的作用區(qū)分開,調(diào)度鎖只是禁止了任務調(diào)度,并沒有關閉任何中斷,中斷還是正常執(zhí)行的。而臨界段進行了開關中斷操作。調(diào)度鎖相關函數(shù);

任務鎖

簡單的說,為了防止當前任務的執(zhí)行被其它高優(yōu)先級的任務打斷而提供的鎖機制就是任務鎖。

FreeRTOS 也沒有專門的任務鎖函數(shù),但是使用 FreeRTOS 現(xiàn)有的功能有兩種實現(xiàn)方法:

(1) 通過給調(diào)度器加鎖實現(xiàn)。利用 FreeRTOS 的調(diào)度鎖功能給調(diào)度器加鎖的話,將關閉任務切換功能,從而高優(yōu)先級任務也就無法搶占低優(yōu)先級任務的執(zhí)行,同時高優(yōu)先級任務也是無法向低優(yōu)先級任務切換的。另外特別注意,調(diào)度鎖只是禁止了調(diào)度器工作,并沒有關閉任何中斷。

(2) 通過關閉任務切換中斷 PendSV 和系統(tǒng)時鐘節(jié)拍中斷 Systick利用 FreeRTOS 的任務代碼臨界段處理函數(shù)就可以關閉 PendSV 中斷和 Systick 中斷。因為進入臨界段前,操作寄存器 basepri 關閉了所有小于等于宏定義configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 所定義的中斷優(yōu)先級(實現(xiàn)任務切換功能的 PendSV 中斷和滴答定時器中斷是最低優(yōu)先級中斷,所以也是被關閉的),這樣低優(yōu)先級任務在執(zhí)行臨界段代碼期間是不會被高優(yōu)先級任務打斷的,從而就實現(xiàn)了任務鎖的效果。

中斷鎖

中斷鎖就是 RTOS 提供的開關中斷函數(shù),F(xiàn)reeRTOS 沒有專門的中斷鎖函數(shù),使用中斷服務程序臨界段處理函數(shù)就可以實現(xiàn)同樣效果。

5.3 FreeRTOS 系統(tǒng)時鐘節(jié)拍和時間管理

5.3.1 FreeRTOS 時鐘節(jié)拍

任何操作系統(tǒng)都需要提供一個時鐘節(jié)拍,以供系統(tǒng)處理諸如延時、 超時等與時間相關的事件。時鐘節(jié)拍是特定的周期性中斷,這個中斷可以看做是系統(tǒng)心跳。中斷之間的時間間隔取決于不同的應用,一般是 1ms – 100ms。時鐘的節(jié)拍中斷使得內(nèi)核可以將任務延遲若干個時鐘節(jié)拍,以及當任務等待事件發(fā)生時,提供等待超時等依據(jù)。時鐘節(jié)拍率越快,系統(tǒng)的額外開銷就越大。任何操作系統(tǒng)都需要提供一個時鐘節(jié)拍,以供系統(tǒng)處理諸如延時、 超時等與時間相關的事件。時鐘節(jié)拍是特定的周期性中斷,這個中斷可以看做是系統(tǒng)心跳。中斷之間的時間間隔取決于不同的應用,一般是 1ms – 100ms。時鐘的節(jié)拍中斷使得內(nèi)核可以將任務延遲若干個時鐘節(jié)拍,以及當任務等待事件發(fā)生時,提供等待超時等依據(jù)。時鐘節(jié)拍率越快,系統(tǒng)的額外開銷就越大。

對于 Cortex-M3 內(nèi)核的 STM32F103 和 Cortex-M4 內(nèi)核的 STM32F407 以及 F429,教程配套的例子都是用滴答定時器來實現(xiàn)系統(tǒng)時鐘節(jié)拍的。

5.3.2 FreeRTOS 時間管理

時間管理功能是 FreeRTOS 操作系統(tǒng)里面最基本的功能,同時也是必須要掌握好的。

時間延時

FreeRTOS 中的時間延遲函數(shù)主要有以下兩個作用:

為周期性執(zhí)行的任務提供延遲。

對于搶占式調(diào)度器,讓高優(yōu)先級任務可以通過時間延遲函數(shù)釋放 CPU 使用權,從而讓低優(yōu)先級任務可以得到執(zhí)行。

通過如下的框圖來說明一下延遲函數(shù)對任務運行狀態(tài)的影響,有一個形象的認識。

對任務 Task1 的運行狀態(tài)做說明,調(diào)度器支持時間片調(diào)度和搶占式調(diào)度。運行過程描述如下:

起初任務 Task1 處于運行態(tài),調(diào)用 vTaskDelay 函數(shù)后進入到阻塞狀態(tài),也就是 blocked 狀態(tài)。

vTaskDelay 函數(shù)設置的延遲時間到,由于任務 Task1 不是當前就緒的最高優(yōu)先級任務,所以不能進 入到運行狀態(tài),只能進入到就緒狀態(tài),也就是 ready 狀態(tài)。

一段時間后,調(diào)度器發(fā)現(xiàn)任務 Task1 是當前就緒的最高優(yōu)先級任務,從而任務從就緒態(tài)切換到運行態(tài)。

由于時間片調(diào)度,任務 Task1 由運行態(tài)切換到就緒態(tài)。

FreeRTOS

FreeRTOS

FreeRTOS 專職開發(fā)人員一直與芯片公司緊密合作, 為客戶提供市場領先external_link以及免費的商用級、高品質(zhì) RTOS和工具。

FreeRTOS 專職開發(fā)人員一直與芯片公司緊密合作, 為客戶提供市場領先external_link以及免費的商用級、高品質(zhì) RTOS和工具。收起

查看更多

相關推薦

電子產(chǎn)業(yè)圖譜

針對嵌入式人工智能,物聯(lián)網(wǎng)等專業(yè)技術分享和交流平臺,內(nèi)容涉及arm,linux,android等各方面。

Arm64 棧回溯
  • 查看更多