---
# System prepended metadata

title: Chapter 3 Task Management
tags: [' FreeRTOS', Reading book]

---

---
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 ->Ｎot 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 大小。