日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

freeRtos学习笔(2)任务管理

發布時間:2025/4/16 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 freeRtos学习笔(2)任务管理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

freeRtos學習筆記

freeRtos任務管理

freeRtos任務狀態

freeRtos中任務有四種狀態:就緒態、運行態、杜塞態、掛起態。


圖 16-1(1): 創建任務→就緒態(Ready):任務創建完成后進入就緒態,表明任務已準備就緒,隨時可以運行,只等待調度器進行調度。

圖 16-1(2): 就緒態→運行態(Running):發生任務切換時,就緒列表中最高優先級的任務被執行,從而進入運行態。

圖 16-1(3): 運行態→就緒態:有更高優先級任務創建或者恢復后,會發生任務調度,此刻就緒列表中最高優先級任務變為運行態,那么原先運行的任務由運行態變為就緒態,依然在就緒列表中,等待最高優先級的任務運行完畢繼續運行原來的任務(此處可以看做是 CPU 使用權被更高優先級的任務搶占了)。

圖 16-1(4): 運行態→阻塞態(Blocked):正在運行的任務發生阻塞(延時、讀信號量等待)時,該任務會從就緒列表中刪除,任務狀態由運行態變成阻塞態,然后發生任務切換,運行就緒列表中當前最高優先級任務。

圖 16-1(5): 阻塞態→就緒態:阻塞的任務被恢復后(任務恢復、延時時間超時、讀信號量超時或讀到信號量等),此時被恢復的任務會被加入就緒列表,從而由阻塞態變成就緒態;如果此時被恢復任務的優先級高于正在運行任務的優先級,則會發生任務切換,將該任務將再次轉換任務狀態,由就緒態變成運行態。

圖 16-1(6) (7) (8): 就緒態、阻塞態、運行態→掛起態(Suspended):任務可以通過調用 vTaskSuspend() API 函數都可以將處于任何狀態的任務掛起,被掛起的任務得不到CPU 的使用權,也不會參與調度,除非它從掛起態中解除。

圖 16-1(9): 掛起態→就緒態: 把一個掛起狀態的任務恢復的唯一途徑就是調用 vTaskResume() 或 xTaskResumeFromISR() API 函數,如果此時被恢復任務的優先級高于正在運行任務的優先級,則會發生任務切換,將該任務將再次轉換任務狀態,由就緒態變成運行態。

freeRtos啟動

void vTaskStartScheduler(void);

啟動freeRtos的任務調度器,空閑任務和定時器任務是在調用這個函數后才自動創建的。

動態創建任務

BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, /* 任務入口函數 */const char * const pcName, /* 任務名 */const configSTACK_DEPTH_TYPE usStackDepth,/* 任務棧大小 單位為字 */void * const pvParameters, /* 任務入口參數 不用的時候配置為0 */UBaseType_t uxPriority, /* 任務任務優先級 空閑任務優先級0 */TaskHandle_t * const pxCreatedTask ) /* 任務控制塊指針 */

函數 xTaskCreate 用于實現 FreeRTOS 操作系統的任務創建,并且還可以自定義任務棧的大小。

  • 第 1 個參數填創建任務的函數名。
  • 第 2 個參數是任務名,這個參數主要是用于調試目的,調試的時候方便看是哪個任務。
  • 第 3 個參數是任務棧大小,單位 word,也就是 4 字節。
  • 第 4 個參數是創建的任務函數的形參。
  • 第 5 個參數是任務優先級,越大優先級越高
  • 第 6 個參數是任務句柄,用于區分不同的任務。
  • 返回值:當任務創建成功,返回pdPASS,否則返回pdFALL.

刪除任務

void vTaskDelete( TaskHandle_t xTaskToDelete )

使用這個函數要注意以下問題:

  • 使用此函數需要在 FreeRTOSConfig.h 配置文件中配置如下宏定義為 1
    #define INCLUDE_vTaskDelete 1
  • 如果用往此函數里面填的任務 ID 是 NULL,即數值 0 的話,那么刪除的就是當前正在執行的任務,此任務被刪除后, FreeRTOS 會切換到任務就緒列表里面下一個要執行的最高優先級任務。
  • 在 FreeRTOS 中,創建任務所需的內存需要在空閑任務中釋放, 如果用戶在 FreeRTOS 中調用了這個函數的話,一定要讓空閑任務有執行的機會, 否則這塊內存是無法釋放的。另外, 創建的這個任務在使用中申請了動態內存,這個內存不會因為此任務被刪除而刪除,這一點要注意, 一定要在刪除前將此內存釋放
  • 掛起任務

    void vTaskSuspend(TaskHandle xTaskToSuspend);

    函數 vTaskSuspend 用于實現 FreeRTOS 操作系統的任務掛起。
    第 1 個參數填要掛起任務的句柄
    使用這個函數要注意以下問題:

  • 使用此函數需要在 FreeRTOSConfig.h 配置文件中配置如下宏定義為 1
    #define INCLUDE_vTaskSuspend 1
  • 如果用往此函數里面填的任務 ID 是 NULL,即數值 0 的話,那么掛起的就是當前正在執行的任務,
    此任務被掛起后, FreeRTOS 會切換到任務就緒列表里面下一個要執行的高優先級任務。
  • 多次調用此函數的話,只需調用一次 vTaskResume 即可將任務從掛起態恢復。
  • 恢復掛起任務

    void vTaskResume(TaskHandle xTaskToResume); BaseType_t xTaskResumeFromISR(TaskHandle xTaskToResume);

    函數 vTaskResume 用于實現 FreeRTOS 操作系統的任務掛起
    第 1 個參數填要恢復任務的句柄
    使用這個函數要注意以下問題:

  • 使用此函數需要在 FreeRTOSConfig.h 配置文件中配置如下宏定義為 1
    #define INCLUDE_vTaskSuspend 1
  • 多次調用函數 vTaskSuspend 的話,只需調用一次 vTaskResume 即可將任務從掛起態恢復。
  • 此函數是用于任務代碼中調用的,故不可以在中斷服務程序中調用此函數,中斷服務程序中使用的
    xTaskResumeFromISR(), 以后綴 FromISR 結尾。
  • xTaskResumeFromISR()返回值:如果恢復掛起任務后會導致任務調度返回pdTRUE
  • 修改任務優先級

    void vTaskPrioritySet(TaskHandle xTask, UBaseType_t uxNewPriority);

    函數 vTaskPrioritySet 用于實現 FreeRTOS 任務優先級的修改。
    第 1 個參數是任務句柄,用于區分不同的任務。
    第 2 個參數是給任務配置的新優先級。
    使用這個函數要注意以下問題:

  • 使用此函數需要在 FreeRTOSConfig.h 配置文件中配置如下宏定義為 1
    #define INCLUDE_vTaskPrioritySet 1
  • 如果第一個參數里面填的是 NULL,即數值 0 的話,那么配置的就是當前正在執行的任務。
  • 如果被修改的任務的優先級,修改后高于正在執行的任務, 將執行任務切換,切換到修改好的高優先級任務。
  • 第二個參數數值不可大于等于 FreeRTOSConfig.h 文件中的宏定義:
    #define configMAX_PRIORITIES 配置的數值。
  • 獲取任務優先級

    UBaseType_t uxTaskPriorityGet(TaskHandle xTask); UBaseType_t uxTaskPriorityGetFromISR(TaskHandle_t xTask);

    函數 vTaskPriorityGet 用于獲取 FreeRTOS 任務優先級。
    第 1 個參數是任務句柄,用于區分不同的任務。
    使用這個函數要注意以下問題:

  • 使用此函數需要在 FreeRTOSConfig.h 配置文件中配置如下宏定義為 1
    #define INCLUDE_vTaskPriorityGet 1
  • 如果第1個參數里面填的是 NULL,即數值 0 的話,那么獲取的優先級就是當前正在執行的任務。
  • 此函數是用于任務代碼中調用的,故不可以在中斷服務程序中調用此函數,中斷服務程序中使用的
    uxTaskPriorityGetFromISR(), 以后綴 FromISR 結尾。
  • 切換任務

    taskYIELD()

    調用 taskYIELD() 宏可以立刻進行任務調度,切換到就緒的最高優先級任務

    獲取當前系統時間

    volatile TickType_t xTaskGetTickCount(void); volatile TickType_t xTaskGetTickCountFromISR(void);

    函數 xTaskGetTickCount 用于獲取系統當前運行的時鐘節拍數。
    使用這個函數要注意以下問題:

  • 此函數用于在任務代碼里面調用, 如果在中斷服務程序里面調用的話, 需要使用函數
    xTaskGetTickCountFromISR, 這兩個函數切不可混用
  • 任務延時

    void vTaskDelay(TickType_t xTickToDelay);

    函數 vTaskDelay 用于任務的延遲。
    參數 xTicksToDelay 用于設置延遲的時鐘節拍個數,范圍 1- 0xFFFFFFFF。 延遲時間的最大值在
    portmacro.h 文件里面有定義:
    typedef uint32_t TickType_t;
    #define portMAX_DELAY ( TickType_t )0xffffffffUL
    即延遲時間的范圍是: 1- 0xFFFFFFFF
    延時后會進行任務調度

    任務絕對延時

    void vTaskDelayUntil(TickType_t* pxPreviousWakeTime, TickType_t xTimeIncrement);

    函數 vTaskDelayUntil 用于周期性延遲。
    ? 第 1 個參數,存儲任務上次處于非阻塞狀態時刻的變量地址。
    ? 第 2 個參數,周期性延遲時間。
    使用這個函數要注意以下問題:

  • 使用此函數需要在 FreeRTOSConfig.h 配置文件中配置如下宏定義為 1
    #define INCLUDE_vTaskDelayUntil 1
  • 用戶要注意此函數跟 vTaskDelay 的區別是,例如在兩個相同任務,用戶處理程序運行需要50ms,然后分別使用vTaskDelay()和vTaskDelayUntil()進行200ms的延時,使用vTaskDelay()做200ms延時,整個任務運行狀況就是先用戶處理消耗50ms,再延時200ms,也就是250ms任務運行一次;而使用vTaskDelayUntil()進行200ms的延時,整個任務運行狀況就是先用戶處理消耗50ms,再延時150ms,也就是200ms任務運行一次;
  • 下面是一個使用vTaskDelay()實現vTaskDelayUntil()的過程。

    void vTaskA(void *pvParame) {TickType_t xDelay, xNextTime;/* 200ms執行一次該任務 */const TickType_t xFrequency = 200;/* 獲取 xFrequency 個時鐘節拍后的時間 */xNextTime = xTaskGetTickCount() + xFrequency;while(1){/* 如果用戶函數需要運行50ms */..../* 計算實際需要延時的時間 200 - 50 = 150 */xDelay = xNextTime - xTaskGetTickCount();xNextTime += xFrequency;if(xDelay <= xFrequency){vTaskDelay(xDelay);}} }void vTaskB(void *pvParame) {TickType_t xLastWakeTime;/* 200ms執行一次該任務 */const TickType_t xFrequency = 200;while(1){/* 如果用戶函數需要運行50ms */....vTaskDelayUntil(&xLastWakeTime, xFrequency);}}

    調度器掛起

    void vTaskSuspendAll(void);

    函數 vTaskSuspendAll 用于實現 FreeRTOS 調度器掛起。
    使用這個函數要注意以下問題:

  • 注意和進入臨界區不同,這里只是關掉了任務調度器,只能運行當前任務,但是并沒有關中斷,中斷服務函數還是可以運行的。
  • 調度鎖開啟函數 vTaskSuspendAll 和調度鎖關閉函數 xTaskResumeAll 一定要成對使用。
  • 切不可在調度鎖開啟函數 vTaskSuspendAll 和調度鎖關閉函數 xTaskResumeAll 之間調用任何會引
    起任務切換的 API, 比如 vTaskDelayUntil、 vTaskDelay、 xQueueSend 等(調用了也不會執行調度)。
  • 調度器恢復

    BaseType_t xTaskResumeAll(void);

    函數 xTaskResumeAll 用于實現 FreeRTOS 調度器恢復
    由于調度器操作可以進行嵌套,如果執行了兩次調度器掛起,那么在第一次執行調度器恢復函數時,此函數返回 pdFALSE,調度器并沒有恢復,第二次執行調度器恢復函數才會返回pdTRUE,調度器才會恢復正常。
    使用這個函數要注意以下問題:

  • 注意和進入臨界區不同,這里只是關掉了任務調度器,只能運行當前任務,但是并沒有關中斷,中斷服務函數還是可以運行的。
  • 調度鎖開啟函數 vTaskSuspendAll 和調度鎖關閉函數 xTaskResumeAll 一定要成對使用。
  • 切不可在調度鎖開啟函數 vTaskSuspendAll 和調度鎖關閉函數 xTaskResumeAll 之間調用任何會引
    起任務切換的 API, 比如 vTaskDelayUntil、 vTaskDelay、 xQueueSend 等(調用了也不會執行調度)
  • 本文參考 freertos官方文檔 https://freertos.org/a00110.html
    《野火-FreeRTOS 內核實現與應用開發實戰指南》
    《安富萊 STM32-V6 開發板 FreeRTOS 教程》

    總結

    以上是生活随笔為你收集整理的freeRtos学习笔(2)任务管理的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。