本實驗透過 FreeRTOS 建立 LEDTask_App
與 ButtonTask_App
,並使用任務間通訊(Inter-Task Communication, ITC)機制來實現 LED 狀態的切換。透過本實驗,學習 FreeRTOS 任務建立、佇列傳遞(queue communication)、排程機制以及按鍵 debounce handling。
任務(task)是在 FreeRTOS 中執行的基本單位,每個 task 都是由一個 C 函數所組成,意思是你需要先定義一個 C 的函數,然後再用 xTaskCreate()
這個 API 來建立一個 task。
這個 C 函數有幾個特點,它的返回值必須是 void
,其中通常會有一個無限迴圈,所有關於這個 task 的工作都會在迴圈中進行,而且這個函數不會有 return。
FreeRTOS 不允許 task 自行結束(使用 return 或執行到函數的最後一行)。
Task 被建立出來後,它會配置有自己的堆疊空間和 stack variable(就是 function 中定義的變數)。
Blocked vs Suspended
blocked 定義為若有個 task 將要等待某個目前無法取得的資源(被其他 task 佔用中),則會被設為 blocked 狀態,這是被動的,OS 會呼叫 blocking API 來設定 task 進入 blocked queue。
suspended 與 blocked 的差異在於,suspended 是 task 主動呼叫 API 來要求讓自己進入暫停狀態的。
GPIO_Output
,命名為 GREEN_LED
GPIO_Output
,命名為 ORANGE_LED
GPIO_Output
,命名為 RED_LED
GPIO_Input
,命名為 BLUE_BUTTON
LEDTask_App
:
ButtonTask_App
:
Queue
通知 LEDTask_App
切換狀態。因為是透過 FreeRTOS 實作,所以要在 main.c
加上 include,兩者的 include 的順序不能對調,否則會報錯。
判斷開/關燈,開燈 GPIO_PIN_SET
,關燈 GPIO_PIN_RESET
。
透過取得 MsgQueue 的資料,如果 MsgQueue 的內容是空的,則此 task 會進入 block state 等待 2000 個 Tick。若收到資料或是等待超過 2000 Tick, 則此 task 會重新進入到 ready state。
用於檢查 Pin 腳有無訊號傳入。
兩個 task 的 priority 都設成相同,因為沒有要對 task 做其他的操作,所以 task handler 可以設成 NULL
。
pvTaskCode
:就是我們定義好用來建立 task 的 C 函數pcName
:任意給定的 task name,這個名稱只被用來作識別,不會在 task 管理中被採用usStackDepth
:堆疊的大小pvParameters
:要傳給 task 的參數陣列,也就是我們在 C 函數宣告的參數uxPriority
:定義這個任務的優先權,在 FreeRTOS 中,0 最低,(configMAX_PRIORITIES – 1) 最高pxCreatedTask
:handle,是一個被建立出來的 task 可以用到的識別符號vTaskStartScheduler()
來啟動排程器決定讓哪個 task 開始執行,當 vTaskStartScheduler()
被呼叫時,會先建立一個 idle task,這個 task 是為了確保 CPU 在任一時間至少有一個 task 可以執行(取代直接切換回 kernel task)而在 vTaskStartScheduler()
被呼叫時自動建立的 user task,idle task 的 priority 為 0 (lowest),目的是為了確保當有其他 user task 進入 ready list 時可以馬上被執行。
xTaskCreate
創建 LEDTask_App
與 ButtonTask_App
。vTaskDelay
來管理 LED 燈閃爍間隔。透過 message queue 讓 task 之間可以做溝通,所以要在 main.c
加上 include。
xQueueCreate
建立佇列,允許 ButtonTask_App
透過 xQueueSend
傳送訊息給 LEDTask_App
。
xQueueReceive
在 LEDTask_App
內部接收訊息,以切換 LED 狀態。
關於 Bounce
如何 Debounce
HAL_Delay(100)
避免按單次按鈕被多次檢測,並再次讀取 GPIO 確保按鍵確實被按下。while(HAL_GPIO_ReadPin(BLUE_BUTTON_GPIO_Port, GPIO_PIN_0))
檢查按鈕是否長按,長按按鈕的話有可能會傳送一次以上的訊號,與 Lab 要求不合。
本實驗透過 FreeRTOS 實現 LEDTask_App
和 ButtonTask_App
,學習如何建立多任務、使用 Queue
進行通訊、管理任務優先級及處理按鍵 Debounce 等概念。