FreeRTOS 任務管理

FreeRTOS 任務管理

任務函數

在這裏插入圖片描述

  • 我們可以按照以上方式定義任務函數,可以更改函數名、變量名。
  • 每一個任務都有一個進入點,任務是一個死循環,一旦啓動不會自己停止。
  • 注意,任務函數是沒有返回值的,而且一定不能有return。任務可以被顯式刪除。
  • 一個任務函數可以創建任意個的任務

任務函數定義如下:
在這裏插入圖片描述

API

創建任務 (Creating Tasks)

The xTaskCreate()

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

示例1 任務創建

*pvTaskCode 是一個函數指針,也就是任務函數名稱。比如說,創建一個名爲vTask1的函數,注意,一定是個死循環!

void vTask1(void *pvParameters)
{
	for(;;)
	{
		vPrintString( "Hello world!" );
	}
}
void vTask2(void *pvParameters)
{
	for(;;)
	{
		// 此處省略
	}
}

在main()函數中創建任務,

int main( void )
{
	xTaskCreate( vTask1, // 函數指針
			 	"Task 1", // 任務名稱,實際作用不大,可用來Debug
			 	1000, // 堆棧大小,根據需要調整
			 	NULL, // 需要傳遞到任務的參數,沒有就設置爲NULL
			 	1, // 任務優先級
			 	NULL); // 任務句柄
	xTaskCreate(vTask2,"Task 2",1000,NULL,1,NULL);
	// xTaskCreate()的返回值是 pdPASS/pdFAIL
	vTaskStartScheduler();
	for(;;); // 我們的main()函數不能返回,開啓調度器後,FreeRTOS會接管系統。
}

如下圖所示:
在這裏插入圖片描述
我們也可以直接在一個任務中創建另一個任務:
在這裏插入圖片描述

示例 2 參數傳遞

我們也可以通過參數傳遞實現兩個不同的任務用同一個任務函數
任務函數:
在這裏插入圖片描述
創建任務:
在這裏插入圖片描述

任務優先級 (Task Priorities)

在創建任務時,FreeRTOS會根據xTaskCreate()中定義的初始值,確定任務優先級。在開啓調度之後,任務的優先級也可以通過vTaskPrioritySet()函數重新設定。
任務的最大優先級定義爲configMAX_PRIORITIES,最小優先級是0,所以選取 (configMAX_PRIORITIES – 1)範圍內的任意一個優先級都是被允許的。而且不同的任務可以擁有相同的優先級。當優先級相同時,調度器將交替執行任務。

FreeRTOS調度器允許以兩種方式調度。

  • 通用方式 Generic Method
    在這種情況下,FreeRTOS不限制最大優先級的數值,但是還是建議將最大優先級數設置在“夠用”的數值上,減少內存消耗。
    可以通過將configUSE_PORT_OPTIMISED_TASK_SELECTION設置爲0啓用這個方式。
  • 根據架構優化方式 Architecture Optimized Method
    這個方式比通用方式要快,因爲它是用來部分彙編代碼編寫。
    在這種情況下,configMAX_PRIORITIES不能超過32,同樣的,建議將最大優先級數設置在“夠用”的數值上,減少內存消耗。
    可以通過將configUSE_PORT_OPTIMISED_TASK_SELECTION設置爲1啓用這個模式。但是,並不是所有的FreeRTOS接口都支持這個模式。

時間測量和滴答中斷 (Time Measurement and the Tick Interrupt)

時間片 Time Slice:
時間片作爲最小的執行時間也叫滴答週期(Tick Period),可以通過configTICK_RATE_HZ設置。
爲了選擇下個需要運行的任務,調度器在每個時間片結束時都會執行調度,通過滴答中斷實現。如圖所示:
在這裏插入圖片描述
可以看到,黑色箭頭表示的是,任務結束->觸發滴答中斷->進行調度 的過程。

FreeRTOS通常以滴答週期作爲單位,表示爲 “xx ticks”, 可以通過pdMS_TO_TICKS()函數進行ms到ticks的單位換算。
在這裏插入圖片描述
注意,一般不建議直接用數值指定ticks,考慮到可移植性,使用pdMS_TO_TICKS()函數能避免很多麻煩。

示例

在這裏插入圖片描述
在這裏插入圖片描述
由於Task2的優先級比Task1高,所以只有Task2能執行

非運行狀態的情況 Expanding the ‘Not Running’ State

阻塞態 Blocked State

阻塞態有兩種可能情況:

  • 跟時間相關的事件(比如說,延時)
  • 同步事件(比如說,任務需要等待數據等)
    在FreeRTOS中,隊列,信號量,互斥量,事件組,任務通知都會產生同步事件

掛起態 Suspended State

掛起態的任務不會被調度,唯一可以導致掛起的操作是調用vTaskSuspend()函數,從掛起態跳出可以調用vTaskResume()和xTaskResumeFromISR(),大部分的應用不需要掛起態。

就緒態 Ready State

就緒態的任務處於等待調度上CPU的狀態

狀態機模型

在這裏插入圖片描述

延時函數 vTaskDelay()

在這裏插入圖片描述
在這裏插入圖片描述
示例程序:
在這裏插入圖片描述
vTaskDelay() 的延遲時間是相對的,他是 本次調用到再次調用 所經過的時間。所以,前提是需要調用vTaskDelay() 纔可以,如果這段時間中有別的任務搶佔CPU,就無法保證延遲是固定頻率的。

圖解:
在這裏插入圖片描述

延時函數 vTaskDelayUntil()

在這裏插入圖片描述
在這裏插入圖片描述
vTaskDelayUntil() 的延時時間是個固定值,參數代表了精確的延時時間。這樣,延時的執行頻率是固定的。在想讓任務以固定頻率執行時,應使用這種方式。

示例程序:
在這裏插入圖片描述
圖解:
在這裏插入圖片描述

  • t1時刻,Periodic任務剛執行完成,xLastWakeTime記錄下此時的tick count(tick count是從調度開始不斷遞增的一個計數器);Continuous1開始運行
  • t5時刻,調度器發現Periodic任務的延時時間已經到了,所以將其設置爲就緒態。同時,由於此任務優先級最高,於是開始執行。執行完成後切換到Continuous1任務。

空閒任務和空閒鉤子 The Idle Task and the Idle Task Hook

空閒任務

空閒任務在開啓調度時會自動被系統創建,空閒任務擁有最低優先級

空閒鉤子 Idle Task Hook Functions

空閒鉤子會被空閒任務自動調用,它常應用於:

  • 運行連續處理的功能,後臺功能,比如說狀態指示燈
  • 檢測處理器餘量
  • 低功耗運行

注意:

  1. 空閒鉤子不能被阻塞或掛起
  2. 如果使用vTaskDelete()函數,鉤子函數必須在合理的時間內返回到調用。

示例:
在這裏插入圖片描述

修改任務優先級 Changing the Priority of a Task

設置優先級 vTaskPrioritySet()

在這裏插入圖片描述
在這裏插入圖片描述
如果第一個參數設置爲NULL,表明修改自身優先級

獲取優先級 uxTaskPriorityGet()

在這裏插入圖片描述
在這裏插入圖片描述

示例

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
圖解:
在這裏插入圖片描述

  • Task1提高了Task2優先級,此時Task2搶佔CPU,開始運行
  • Task2運行完降低自己的優先級,此時Task1搶佔CPU,開始運行

刪除任務 Deleting a Task

vTaskDelete()

在這裏插入圖片描述
示例程序:
在這裏插入圖片描述
在這裏插入圖片描述
圖解
在這裏插入圖片描述
Task1創建Task2任務,Task2刪除自己,just it~

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