函數流程
int main(void) { /* 第一步:開發板硬件初始化 */ BSP_Init(); /* 第二步:創建APP應用任務,所有的應用任務都可以放在這個函數里面 */ AppTaskCreate(); /* 第三步:啟動FreeRTOS,開始多任務調度,啟動成功則不返回 */ vTaskStartScheduler(); while (1) { } }
創建APP應用任務,
static void AppTaskCreate(void) { xTaskCreate(vTaskLed1, /* 任務函數名 */ "Task Led1", /* 任務名,字符串形式,方便調試 */ 512, /* 棧大小,單位為字,即4個字節 */ NULL, /* 任務形參 */ 0, /* 優先級,數值越大,優先級越高 */ &xHandleTaskLED1); /* 任務句柄 */ xTaskCreate(vTaskBeep,"Task Beep",512,NULL,2,&xHandleTaskBeep); }
pvTaskCode 任務只是永不退出的 C 函數,實現通常是一個死循環。參數pvTaskCode 只是一個指向任務的實現函數的指針(效果上僅僅是函數名)。
pcName 具有描述性的任務名。這個參數不會被 FreeRTOS 使用。其只是單純地用於輔助調試。識別一個具有可讀性的名字總是比通過句柄來識別容易得多。
應用程序可以通過定義常量 config_MAX_TASK_NAME_LEN 來定義任務名的最大長度——包括’\0’結束符。如果傳入的字符串長度超過了這個最大值,字符串將會自動被截斷。
usStackDepth 當任務創建時,內核會分為每個任務分配屬於任務自己的唯一狀態。
usStackDepth 值用於告訴內核為它分配多大的棧空間。這個值指定的是棧空間可以保存多少個字(word),
而不是多少個字節(byte)。比如說,如果是 32 位寬的棧空間,傳入的 usStackDepth值為 100,
則將會分配 400 字節的棧空間(100 * 4bytes)。棧深度乘以棧寬度的結果千萬不能超過一個 size_t 類型變量所能表達的最大值。
應用程序通過定義常量 configMINIMAL_STACK_SIZE 來決定空閑任務任用的棧空間大小。
在 FreeRTOS 為微控制器架構提供的Demo 應用程序中,賦予此常量的值是對所有任務的最小建議值。
如果你的任務會使用大量棧空間,那么你應當賦予一個更大的值。
沒有任何簡單的方法可以決定一個任務到底需要多大的棧空間。
計算出來雖然是可能的,但大多數用戶會先簡單地賦予一個自認為合理的值,
然后利用 FreeRTOS 提供的特性來確證分配的空間既不欠缺也不浪費。
pvParameters 任務函數接受一個指向 void 的指針(void*)。pvParameters 的值即是傳遞到任務中的值。
uxPriority 指定任務執行的優先級。優先級的取值范圍可以從最低優先級 0 到最高優先級(configMAX_PRIORITIES – 1)。
configMAX_PRIORITIES 是一個由用戶定義的常量。優先級號並沒有上限(除了受限於采用的數據類型和系統的有效內存空間),
但最好使用實際需要的最小數值以避免內存浪費。如果 uxPriority 的值超過了(configMAX_PRIORITIES – 1),
將會導致實際賦給任務的優先級被自動封頂到最大合法值。
void vTaskLed1(void *pvParameters) { /* 任務都是一個無限,不能返回 */ while(1) { LED1_ON; /* 阻塞延時,單位ms */ vTaskDelay( 500 ); LED1_OFF; vTaskDelay( 500 ); } } void vTaskBeep(void *pvParameters) { /* 任務都是一個無限,不能返回 */ while(1) { BEEP_ON; /* 阻塞延時,單位ms */ vTaskDelay( 500 ); BEEP_OFF; vTaskDelay( 500 ); }
調度器保證總是在所有可運行的任務中選擇具有最高優先級的任務,並使其進入運行態。
如果被選中的優先級上具有不止一個任務,調度器會讓這些任務輪流執行。這種行為方式在本例中可以明顯看出來。
兩個測試任務被創建在同一個優先級上,並且一直是可運行的。所以每個任務都執行一個”時間片”,
任務在時間片起始時刻進入運行態,在時間片結束時刻又退出運行態。
圖 中 t1 與 t2 之間的時段就等於一個時間片。