--- title: image: description: tags: Reading book, FreeRTOS --- # Chapter 3 Task Management ## 3.1 Chapter Introduction and Scope ***唸完這章可以讓很好的了解到:*** * 在一個應用程序下,FreeRTOS 是如何分配各 task 的處理時間。 * 在任意時間,FreeRTOS 如何去選擇哪個 task 應該被執行。 * 每個 task 的相對優先權如何影響整個系統行為。 * task 存在哪些型態。 ***讀者還應該對以下內容有充分的了解:*** * 如何實現 tasks。 * 如何創建一個或多個 task 的實例。 * 如何使用 task 參數。 * 如何對已建立的 task 修改他的優先級。 * 如何殺掉 task。 * 如何利用 task 實現週期性的處理(軟體計時器會在下一章節討論) * idle task 何時會被執行到以及如何使用。 這章節所提出的概念是如何使用 FreeRTOS 的基本觀念以及 FreeRTOS 應用程序的行為。因此這章會是這本書最為詳細的地方。 ## 3.2 Task Functions Tasks 是由 C 語言函數所實現的,唯一特別的是它們的函數原型,必須回傳 void 而且帶有一個 void pointer parameter。這個函數原型定義在 Listing 11. ```c= void ATaskFunction( void *pvParameters ); // Listing 11. The task function prototype ``` 每個 task 都是在自己權限內的小程序,都會有程序入口,通常會跑一個無權窮迴圈,並且不會退出。 Listing 12 是典型的 task 結構。 FreeRTOS tasks 不允許以任何方式從他們的 implementing function 返回(return)---他們不可以包含 ‘return’ 語句並且也不能執行到函數的結尾。如果一個 task 不再被需要,則它應該乾淨的刪除掉。 Listing 12 也有定義。 單一個 task 函數可以被用來創建多個 tasks,每一個被創建出來的 task 均是獨立執行的實例,有自己的 stack 與自己的自動變數(stack 變數,即 task 自己本身定義的變數)。 ```c= void ATaskFunction( void *pvParameters ) { /* 可以像常規函數一樣去定義變數,利用這個範例函數建立的 task 都會有一個屬於自己的 lVariableExample 變數 但是如果將 lVariableExample 變數定義成 static 則前述不會成立,會變成所有被建立 task 共享這個變數。 (The prefixes added to variable names are described in section 1.5, Data Types and Coding Style Guide.) */ int32_t lVariableExample = 0; /* task 中常會被建立在 infinite loop */ for( ;; ) { /* 實現任務功能的代碼將在此處。 */ } /* 如果 task 執行時會跳出(break out) loop, 則必須在函數運行完之前刪除,將 NULL 傳入這個 vTaskDelete() API 表示說要刪除的 task 是當前的任務。*/ /*用於命名API函數的約定在第0節中進行了描述, 使用低於V9.0.0的FreeRTOS版本的項目必須構建一個heap_n.c文件。 從FreeRTOS V9.0.0起,僅在以下情況下才需要heap_n.c文件: 在FreeRTOSConfig.h中, configSUPPORT_DYNAMIC_ALLOCATION未定義 configSUPPORT_DYNAMIC_ALLOCATION設置為1。 有關更多信息,請參考第2章,堆內存管理。 數據類型和編碼樣式指南。*/ vTaskDelete( NULL ); } // Listing 12. The structure of a typical task function ``` ## 3.3 Top Level Task States 一個應用程序可以由多個 task 組成。如果硬體只有一顆 core 則任意時間點觀看都會只有一個 task 在執行。簡單來說只分兩態`Not Running & Running`, `Not Running -> Running` 稱為 `switched in | swapped in`。 `Running ->Not Running` 稱為 `switched out | swapped out`。 ## 3.4 Creating Tasks ```c= BaseType_t xTaskCreate( TaskFunction_t pvTaskCode, const char * const pcName, uint16_t usStackDepth, void *pvParameters, UBaseType_t uxPriority, TaskHandle_t *pxCreatedTask ); ``` * `pvTaskCode` * 他是一個指向 task 實現函數的指針(效果上僅僅只是函數名) * `pcName` * 對 task 的描述名,這個參數不會被 Free RTOS 用到。通常用來輔助 user 更好理解函數用法。 * 應用程序可以通過定義常量 config_MAX_TASK_NAME_LEN 來定 義任務名的最大長度——包括’\0’結束符。如果傳入的字符串長度超 過了這個最大值,字符串將會自動被截斷。 * `usStackDepth` * 當 task 被建立時 kernel 會幫忙建立 task 自己的 unique stack。`usStackDepth` 就是用來告知 kernel 要建立多大的。 * 這個值是以 1 個 word 為單位,假設 1 word = 4 bytes 則並且 `usStackDepth = 100`,則 400 bytes 的 stack 空間會被建立 (100 * 4 bytes)。 * stack depth x stack width 不能超過 `uint16_t` 最大正整數表示範圍($2^{16} - 1$) * 應用程序通過定義常量 configMINIMAL_STACK_SIZE 來決定 Idle task 任用的 stack space 大小。