<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          FreeRTOS系列第9篇---FreeRTOS任務(wù)概述基礎(chǔ)篇

          共 5014字,需瀏覽 11分鐘

           ·

          2020-07-29 01:29


          關(guān)注、星標(biāo)公眾號,直達(dá)精彩內(nèi)容

          ID:技術(shù)讓夢想更偉大

          作者:李肖遙


          1. 任務(wù)和協(xié)程(Co-routines)

          應(yīng)用程序可以使用任務(wù)也可以使用協(xié)程,或者兩者混合使用,但是任務(wù)和協(xié)程使用不同的API函數(shù),因此在任務(wù)和協(xié)程之間不能使用同一個隊(duì)列或信號量傳遞數(shù)據(jù)。

          通常情況下,協(xié)程僅用在資源非常少的微處理器中,特別是RAM非常稀缺的情況下。

          目前協(xié)程很少被使用到,因此對于協(xié)程FreeRTOS作者既沒有把它刪除也沒有進(jìn)一步開發(fā)。

          所以本系列文章以后不會對協(xié)程過多描述,包括其API函數(shù)。

          1.1任務(wù)的特性

          「簡而言之:」

          使用RTOS的實(shí)時應(yīng)用程序可認(rèn)為是一系列獨(dú)立任務(wù)的集合。每個任務(wù)在自己的環(huán)境中運(yùn)行,不依賴于系統(tǒng)中的其它任務(wù)或者RTOS調(diào)度器。

          在任何時刻,只有一個任務(wù)得到運(yùn)行,RTOS調(diào)度器決定運(yùn)行哪個任務(wù)。調(diào)度器會不斷的啟動、停止每一個任務(wù),宏觀看上去就像整個應(yīng)用程序都在執(zhí)行。

          作為任務(wù),不需要對調(diào)度器的活動有所了解,在任務(wù)切入切出時保存上下文環(huán)境(寄存器值、堆棧內(nèi)容)是調(diào)度器主要的職責(zé)。

          為了實(shí)現(xiàn)這點(diǎn),每個任務(wù)都需要有自己的堆棧。當(dāng)任務(wù)切出時,它的執(zhí)行環(huán)境會被保存在該任務(wù)的堆棧中,這樣當(dāng)再次運(yùn)行時,就能從堆棧中正確的恢復(fù)上次的運(yùn)行環(huán)境。

          1.2任務(wù)概要

          • 簡單
          • 沒有使用限制
          • 支持完全搶占
          • 支持優(yōu)先級
          • 每個任務(wù)都有自己的堆棧,消耗RAM較多
          • 如果使用搶占,必須小心的考慮可重入問題

          2. 任務(wù)狀態(tài)

          「一個任務(wù)可為下面中的一個:」

          1. 「運(yùn)行」:如果一個任務(wù)正在執(zhí)行,那么說這個任務(wù)處于運(yùn)行狀態(tài)。此時它占用處理器。
          2. 「就緒」:就緒的任務(wù)已經(jīng)具備執(zhí)行的能力(不同于阻塞和掛起),但是因?yàn)橛幸粋€同優(yōu)先級或者更高優(yōu)先級的任務(wù)處于運(yùn)行狀態(tài)而還沒有真正執(zhí)行。
          3. 「阻塞」:如果任務(wù)當(dāng)前正在等待某個時序或外部中斷,我們就說這個任務(wù)處于阻塞狀態(tài)。比如一個任務(wù)調(diào)用vTaskDelay()后會阻塞到延時周期到為止。任務(wù)也可能阻塞在隊(duì)列或信號量的事件上。進(jìn)入阻塞狀態(tài)的任務(wù)通常有一個“超時”周期,當(dāng)事件超時后解除阻塞。
          4. 「掛起」:處于掛起狀態(tài)的任務(wù)同樣對調(diào)度器無效。僅當(dāng)明確的分別調(diào)用vTaskSuspend()xTaskResume() API函數(shù)后,任務(wù)才會進(jìn)入或退出掛起狀態(tài)。不可以指定超時周期事件(不可以通過設(shè)定超時事件而退出掛起狀態(tài))

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

          每個任務(wù)都要被指定一個優(yōu)先級,從0~configMAX_PRIORITIESconfigMAX_PRIORITIES定義在FreeRTOSConfig.h中。

          如果某架構(gòu)硬件支持CLZ(或類似)指令(計(jì)算前導(dǎo)零的數(shù)目,Cortex-M3是支持該指令的,從ARMv6T2才支持這個指令),并且打算在移植層使用這個特性來優(yōu)化任務(wù)調(diào)度機(jī)制,需要有一些步驟。

          首先將FreeRTOSConfig.h中configUSE_PORT_OPTIMISED_TASK_SELECTION設(shè)置為1,并且最大優(yōu)先級數(shù)目configMAX_PRIORITIES不能大于32。

          除此之外,configMAX_PRIORITIES可以設(shè)置為任意值,但是考慮到configMAX_PRIORITIES設(shè)置越大,RAM消耗也越大,一般設(shè)置為滿足使用的最小值。

          低優(yōu)先級數(shù)值代表低優(yōu)先級。空閑任務(wù)(idle task)的優(yōu)先級為0(tskIDLE_PRIORITY)。

          FreeRTOS調(diào)度器確保處于最高優(yōu)先級的就緒或運(yùn)行態(tài)任務(wù)獲取處理器,換句話說,處于運(yùn)行狀態(tài)的任務(wù),只有其中的最高優(yōu)先級任務(wù)才會運(yùn)行。

          任何數(shù)量的任務(wù)可以共享同一個優(yōu)先級。如果宏configUSE_TIME_SLICING未定義或者宏configUSE_TIME_SLICING定義為1,處于就緒態(tài)的多個相同優(yōu)先級任務(wù)將會以時間片切換的方式共享處理器。

          4.實(shí)現(xiàn)一個任務(wù)

          「一個任務(wù)具有以下結(jié)構(gòu):」

          void?vATaskFunction(?void?*pvParameters?)
          {
          ????for(?;;?)
          ????{
          ????????/*--?應(yīng)用程序代碼放在這里.?--*/
          ????}
          ?
          ????/*?任務(wù)不可以從這個函數(shù)返回或退出。在較新的FreeRTOS移植包中,如果
          ????試圖從一個任務(wù)中返回,將會調(diào)用configASSERT()(如果定義的話)。
          ????如果一個任務(wù)確實(shí)要退出函數(shù),那么這個任務(wù)應(yīng)調(diào)用vTaskDelete(NULL)
          ????函數(shù),以便處理一些清理工作。*/
          ????vTaskDelete(?NULL?);
          }

          任務(wù)函數(shù)返回為void,參數(shù)只有一個void類型指針。所有的任務(wù)函數(shù)都應(yīng)該是這樣。void類型指針可以向任務(wù)傳遞任意類型信息。

          任務(wù)函數(shù)決不應(yīng)該返回,因此通常任務(wù)函數(shù)都是一個死循環(huán)。

          任務(wù)由xTaskCreate()函數(shù)創(chuàng)建,由vTaskDelete()函數(shù)刪除。

          5.空閑任務(wù)和空閑任務(wù)鉤子(idle task和Idle Task hook)

          5.1空閑任務(wù)

          空閑任務(wù)是啟動RTOS調(diào)度器時由內(nèi)核自動創(chuàng)建的任務(wù),這樣可以確保至少有一個任務(wù)在運(yùn)行。

          空閑任務(wù)具有最低任務(wù)優(yōu)先級,這樣如果有其它更高優(yōu)先級的任務(wù)進(jìn)入就緒態(tài)就可以立刻讓出CPU。

          刪除任務(wù)后,空閑任務(wù)用來釋放RTOS分配給被刪除任務(wù)的內(nèi)存。因此,在應(yīng)用中使用vTaskDelete()函數(shù)后確保空閑任務(wù)能獲得處理器時間就很重要了。

          除此之外,空閑任務(wù)沒有其它有效功能,所以可以被合理的剝奪處理器時間,并且它的優(yōu)先級也是最低的。

          應(yīng)用程序任務(wù)共享空閑任務(wù)優(yōu)先級(tskIDLE_PRIORITY)也是可能的。這種情況如何配置可以參考configIDLE_SHOULE_YIELD配置參數(shù)類獲取更多信息。

          5.2空閑任務(wù)鉤子

          空閑任務(wù)鉤子是一個函數(shù),每一個空閑任務(wù)周期被調(diào)用一次。如果你想將任務(wù)程序功能運(yùn)行在空閑優(yōu)先級上,可以有兩種選擇:

          1. 在一個空閑任務(wù)鉤子中實(shí)現(xiàn)這個功能:因?yàn)镕reeRTOS必須至少有一個任務(wù)處于就緒或運(yùn)行狀態(tài),因此鉤子函數(shù)不可以調(diào)用可能引起空閑任務(wù)阻塞的API函數(shù)(比如vTaskDelay()或者帶有超時事件的隊(duì)列或信號量函數(shù))

          2. 創(chuàng)建一個具有空閑優(yōu)先級的任務(wù)去實(shí)現(xiàn)這個功能:這是個更靈活的解決方案,但是會帶來更多RAM開銷。

          「創(chuàng)建一個空閑鉤子步驟如下」

          • FreeRTOSConfig.h頭文件中設(shè)置configUSE_IDLE_HOOK為1;
          • 定義一個函數(shù),名字和參數(shù)原型如下所示:
          void?vApplicationIdleHook(?void?);

          通常,使用這個空閑鉤子函數(shù)設(shè)置CPU進(jìn)入低功耗模式。

          6.任務(wù)創(chuàng)建

          任務(wù)創(chuàng)建和刪除API函數(shù)位于文件task.c中,需要包含task.h頭文件。

          6.1 函數(shù)描述

          BaseType_t?xTaskCreate(
          ????????TaskFunction_t?pvTaskCode,
          ????????const?char?*?const?pcName,
          ????????unsigned?short?usStackDepth,
          ????????void?*pvParameters,
          ????????UBaseType_t?uxPriority,
          ????????TaskHandle_t?*?pvCreatedTask
          ??????);

          創(chuàng)建新的任務(wù)并加入任務(wù)就緒列表。

          如果使用FreeRTOS-MPU(在官方下載包中,為Cortex-M3內(nèi)核寫了兩個移植方案,一個是普通的FreeRTOS移植層,還有一個是FreeRTOS-MPU移植層。后者包含完整的內(nèi)存保護(hù)),那么推薦使用函數(shù)xTaskCreateRestricted()來代替xTaskCreate()

          在使用FreeRTOS-MPU的情況下,使用xTaskCreate()函數(shù)可以創(chuàng)建運(yùn)行在特權(quán)模式或用戶模式(見下面對函數(shù)參數(shù)uxPriority的描述)的任務(wù)。

          當(dāng)運(yùn)行在特權(quán)模式下,任務(wù)可以訪問整個內(nèi)存映射;當(dāng)處于用戶模式下,任務(wù)僅能訪問自己的堆棧。

          無論在何種模式下,MPU都不會自動捕獲堆棧溢出,因此標(biāo)準(zhǔn)的FreeRTOS堆棧溢出檢測機(jī)制仍然會被用到。xTaskCreateRestricted()函數(shù)具有更大的靈活性。

          6.2參數(shù)描述

          • 「pvTaskCode」:指針,指向任務(wù)函數(shù)的入口。任務(wù)永遠(yuǎn)不會返回(位于死循環(huán)內(nèi))。該參數(shù)類型TaskFunction_t定義在文件projdefs.h中,定義為:typedefvoid (*TaskFunction_t)( void * )
          • 「pcName」:任務(wù)描述。主要用于調(diào)試。字符串的最大長度由宏configMAX_TASK_NAME_LEN指定,該宏位于FreeRTOSConfig.h文件中。
          • 「usStackDepth」:指定任務(wù)堆棧大小,能夠支持的堆棧變量數(shù)量,而不是字節(jié)數(shù)。比如,在16位寬度的堆棧下,usStackDepth定義為100,則實(shí)際使用200字節(jié)堆棧存儲空間。堆棧的寬度乘以深度必須不超過size_t類型所能表示的最大值。比如,size_t為16位,則可以表示的最大值是65535。
          • 「pvParameters」:指針,當(dāng)任務(wù)創(chuàng)建時,作為一個參數(shù)傳遞給任務(wù)。
          • uxPriority:任務(wù)的優(yōu)先級。具有MPU支持的系統(tǒng),可以通過置位優(yōu)先級參數(shù)的portPRIVILEGE_BIT位,隨意的在特權(quán)(系統(tǒng))模式下創(chuàng)建任務(wù)。比如,創(chuàng)建一個優(yōu)先級為2的特權(quán)任務(wù),參數(shù)uxPriority可以設(shè)置為( 2 | portPRIVILEGE_BIT )。
          • 「pvCreatedTask」:用于回傳一個句柄(ID),創(chuàng)建任務(wù)后可以使用這個句柄引用任務(wù)。

          6.3返回值

          如果任務(wù)成功創(chuàng)建并加入就緒列表函數(shù)返回pdPASS,否則函數(shù)返回錯誤碼,具體參見projdefs.h

          6.4用法舉例

          /*?創(chuàng)建任務(wù).?*/
          void?vTaskCode(?void?*?pvParameters?)
          {
          ????for(?;;?)
          ????{
          ???????/*?任務(wù)代碼放在這里?*/
          ????}
          }
          ?
          /*?創(chuàng)建任務(wù)函數(shù)?*/
          void?vOtherFunction(?void?)
          {
          ????static?unsigned?char?ucParameterToPass;
          ????xTaskHandlexHandle;
          ?
          ?????/*?創(chuàng)建任務(wù),存儲句柄。注:傳遞的參數(shù)ucParameterToPass必須和任務(wù)具有相同的生存周期,
          ????????因此這里定義為靜態(tài)變量。如果它只是一個自動變量,可能不會有太長的生存周期,因?yàn)?br>????????????????中斷和高優(yōu)先級任務(wù)可能會用到它。?*/
          ?????xTaskCreate(?vTaskCode,?"NAME",?STACK_SIZE,&ucParameterToPass,?tskIDLE_PRIORITY,?&xHandle?);
          ?
          ?????/*?使用句柄刪除任務(wù).?*/
          ????if(?xHandle?!=NULL?)
          ????{
          ????????vTaskDelete(?xHandle?);
          ????}
          }

          7.任務(wù)刪除

          7.1 任務(wù)描述

          voidvTaskDelete(?TaskHandle_t?xTask?);

          從RTOS內(nèi)核管理器中刪除一個任務(wù)。任務(wù)刪除后將會從就緒、阻塞、暫停和事件列表中移除。在文件FreeRTOSConfig.h中,必須定義宏INCLUDE_vTaskDelete 為1,本函數(shù)才有效。

          「注意:」

          被刪除的任務(wù),其在任務(wù)創(chuàng)建時由內(nèi)核分配的存儲空間,會由空閑任務(wù)釋放。

          如果有應(yīng)用程序調(diào)用xTaskDelete(),必須保證空閑任務(wù)獲取一定的微控制器處理時間。

          任務(wù)代碼自己分配的內(nèi)存是不會自動釋放的,因此刪除任務(wù)前,應(yīng)該將這些內(nèi)存釋放。

          7.2參數(shù)描述

          • 「xTask」:被刪除任務(wù)的句柄。為NULL表示刪除當(dāng)前任務(wù)。
          推薦閱讀:


          嵌入式編程專輯
          Linux 學(xué)習(xí)專輯
          C/C++編程專輯

          關(guān)注微信公眾號『技術(shù)讓夢想更偉大』,后臺回復(fù)“m”查看更多內(nèi)容,回復(fù)“加群”加入技術(shù)交流群。

          長按前往圖中包含的公眾號關(guān)注

          瀏覽 46
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  诱咪一区二区三区四区 | 丰满老妇高潮一级A片 | 粉嫩逼逼 | 婷婷五月丁香久久 | 精品1卡二卡三卡四卡老狼 |