STM32 FreeRTOS
FreeRTOS 架構
官方網站:http://www.freertos.org/
FreeRTOS 是一個相對其他作業系統而言較小的作業系統。最小化的 FreeRTOS 核心僅包括 3 個 .c 文件(tasks.c、queue.c、list.c)和少數標頭檔,總共不到 9000 行程式碼,還包括了註解和空行。一個典型的編譯後 binary(二進位碼)小於 10 KB。
FreeRTOS 的程式碼可以分為三個主要區塊:任務、通訊和硬體界面。
- 任務 (Task): FreeRTOS 的核心程式碼約有一半是用來處理多數作業系統首要關注的問題:任務,任務是擁有優先權的用戶所定義的 C 函數。task.c 和 task.h 負責所有關於建立、排程和維護任務的繁重工作。
- 通訊 (Communication): 任務很重要,不過任務間可以互相通訊則更為重要!它帶出了 FreeRTOS 的第二項議題:通訊。FreeRTOS 核心程式碼大約有 40% 是用來處理通訊的。queue.c 和 queue.h 負責處理 FreeRTOS 的通訊,任務和中斷(interrupt)使用佇列(佇列,queue)互相發送數據,並且使用 semaphore 和 mutex 來派發 critical section 的使用信號。
- 硬體界面:有近 9000 行的程式碼組成基本的 FreeRTOS,這部份是與硬體無關的(hardware-independent),同一份程式碼在不同硬體平台上的 FreeRTOS 都可以運行。大約有 6% 的 FreeRTOS 核心代碼,在與硬體無關的 FreeRTOS 核心和與硬體相關的程式碼間扮演著墊片(shim)的角色。我們將在下個部分討論與硬體相關的程式碼。[#]_
用 cloc統計 FreeRTOS 8.0.0 的 include/ *.c portable/GCC/ARM_CM4F/ 等目錄,可得不含註解、空白行的行數為 6566,而統計與平台有關的部份 (portable/GCC/ARM_CM4F/ 目錄),則是 435 行。計算可得: 435 / 6566 = 0.06625 = 6%,與描述相符,但原本的 9000 行是指含註解的說法 (實際為 8759 行)
原始碼載點
官方下載:https://sourceforge.net/projects/freertos
- tasks.c:主要掌管 task 的檔案
- queue.c:管理 task 間 communication (message queue 的概念)
- list.c:提供系統與應用實作會用到的 list 資料結構
- portmacro.h:定義了與硬體相關的變數,如資料型態定義,以及與硬體相關的函式呼叫名稱定義(以 portXXXXX 命名)等,統一各平臺的函式呼叫
- port.c:定義了包含與硬體相關的程式碼實作
- FreeRTOSConfig.h:包含 clock speed, heap size, mutexes 等等都在此定義(需自行建立)
FreeRTOS 移植
這邊可以參考影片FreeRTOS–第2.2讲 FreeRTOS在STM32F4上的移植STM32F429
主要是把FreeRTOS的結構移植到所要開發的板子上內部支援的很多但沒看到是CubeIDE版本的
- 匯入.h檔
- <FreeRTOS>/Source/include
- <FreeRTOS>/Demo/CORTEX_M4F_STM32F407ZG-SK(這步主要是因為範例移植F4須比照自己需求移植)
- <FreeRTOS>/Source/portable/RVDS/ARM_CM4F(這步看主要核心是用哪種F4為 M4核心)
中的 *.h 匯入
- 將 *.c 檔案加入至專案中
- <FreeRTOS>/Source/(全部匯入)
- <FreeRTOS>/Source/portable/MemMang/heap_1.c
- <FreeRTOS>/Source/portable/RVDS/ARM_CM4F/port.c (這步看主要核心是用哪種F4為 M4核心)
- 打開 <FreeRTOS>/Demo/CORTEX_M4F_STM32F407ZG-SK/FreeRTOSConfig.h
並將 #include “stm32f4xx.h” 標頭檔加入到文件中,且將
#define configCHECK_FOR_STACK_OVERFLOW 2 改成
#define configCHECK_FOR_STACK_OVERFLOW 0 ,存檔並關閉。 - 打開 <FreeRTOS>/Source/portable/RVDS/ARM_CM4F/port.c
並將 #include “stm32f4xx.h” 標頭檔加入到文件中。
注意要點
- 修改 FreeRTOSConfig.h 移除 #ifdef ICCARM 和相對應的 #endif
- 修改 src/stm32f4xxit.c ,將 SVCHandler(), PendSV_Handler(),SysTick_Handler() 三個函式前面加上 __attribute((weak))
- 修改 src/main.c 在前面增加 #include “FreeRTOS.h” 和 #include “task.h”
- 修改 src/main.c 增加 vApplicationMallocFailedHook() , vApplicationIdleHook() 和 vApplicationStackOverflowHook() 三個函式,可從 FreeRTOS/Demo/CORTEX_M4F_STM32F407ZG-SK/main.c 中複製
- 修改 src/main.c 增加 vApplicationTickHook() 函式,內容為空即可。
- 將 lib/FreeRTOS/src 中的 .c 檔加入專案中編譯。注意:heap_x.c 只需選擇一個即可,可以先使用 heap_1.c
- 修改 main() ,加入一行 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
步驟 16 中 heap_x.c 是 FreeRTOS 提供的多種記憶體管理方式。如果系統中配置的記憶體不會釋放,可以使用 head_1.c 。否則就要選擇其他的管理方式。FreeRTOS Memory Management – 步驟 17 是為了配合 FreeRTOS ,將 NVIC 的優先權設定成 NVIC_PriorityGroup_4
LED 閃爍測試程式
用這個簡單程式去驗證是否移植成功
void LED_Init(void)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
__INLINE void LED_On(void)
{
GPIO_SetBits(GPIOA, GPIO_Pin_5);
}
__INLINE void LED_Off(void)
{
GPIO_ResetBits(GPIOA, GPIO_Pin_5);
}
static void Blink_Task(void* pvParameters)
{
TickType_t xLastFlashTime;
LED_Init();
xLastFlashTime = xTaskGetTickCount();
while (1) {
LED_On();
vTaskDelayUntil(&xLastFlashTime, 500);
LED_Off();
vTaskDelayUntil(&xLastFlashTime, 4500);
}
}
int main(void)
{
// Initialize system
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
xTaskCreate(Blink_Task, "LED", configMINIMAL_STACK_SIZE, NULL,
BLINK_TASK_PRIORITY, NULL);
vTaskStartScheduler();
while (1) {
}
}