FreeRTOS的介紹及移植
時間:2023-09-11 來源:華清遠見
一.FreeRTOS簡單概述
1.1 FreeRTOS目錄結構
以Keil工具下STM32F103芯片為例,它的FreeRTOS的目錄如下:

主要涉及2個目錄:
Demo
Demo目錄下是工程文件,以"芯片和編譯器"組合成一個名字
比如:CORTEX_STM32F103_Keil
Source
根目錄下是核心文件,這些文件是通用的
portable目錄下是移植時需要實現的文件
目錄名為:[compiler]/[architecture]
比如:RVDS/ARM_CM3,這表示cortexM3架構在RVDS工具上的移植文件
1.2 核心文件
FreeRTOS的最核心文件只有2個:
FreeRTOS/Source/tasks.c
FreeRTOS/Source/list.c
其他文件的作用也一起列表如下:

1.3 移植時涉及的文件
移植FreeRTOS時涉及的文件放在 FreeRTOS/Source/portable/[compiler]/[architecture] 目錄下,比如:RVDS/ARM_CM3,這表示cortexM3架構在RVDS或Keil工具上的移植文件。
里面有2個文件:
port.c
portmacro.h
1.4頭文件相關
列表如下:

1.5內存管理
文件在 FreeRTOS/Source/portable/MemMang 下,它也是放在 portable 目錄下,表示你可以提供自己的函數。
源碼中默認提供了5個文件,對應內存管理的5種方法。
參考文章:FreeRTOS說明書吐血整理【適合新手+入門】

1.6 Demo
Demo目錄下是預先配置好的、沒有編譯錯誤的工程。目的是讓你可以基于它進行修改,以適配你的單板。
這些Demo還可以繼續精簡:
Demo/Common 中的文件可以完全刪除
main函數中只需要保留2個函數:
prvSetupHardware()
vTaskStartScheduler()
如下圖所示:

1.7數據類型和編程規范
1.7.1數據類型
每個移植的版本都含有自己的 portmacro.h 頭文件,里面定義了2個數據類型:
TickType_t:
FreeRTOS配置了一個周期性的時鐘中斷:Tick Interrupt
每發生一次中斷,中斷次數累加,這被稱為tick count
tick count這個變量的類型就是TickType_t
TickType_t可以是16位的,也可以是32位的
FreeRTOSConfifig.h中定義confifigUSE_16_BIT_TICKS時,TickType_t就是uint16_t
否則TickType_t就是uint32_t
對于32位架構,建議把TickType_t配置為uint32_t
BaseType_t:
這是該架構最高效的數據類型
32位架構中,它就是uint32_t
16位架構中,它就是uint16_t
8位架構中,它就是uint8_t
BaseType_t通常用作簡單的返回值的類型,還有邏輯值,比如 pdTRUE/pdFALSE
1.7.2變量名
變量名有前綴:

1.7.3函數名
函數名的前綴有2部分:返回值類型、在哪個文件定義。

1.7.4宏的名
宏的名字是大小,可以添加小寫的前綴。前綴是用來表示:宏在哪個文件中定義。

1.8安裝keil
略
移植過程
2.1提取源碼
首先在我們的STM32裸機工程模板根目錄下新建一個文件夾,命名為“FreeRTOS”,并且在FreeRTOS文件夾下新建兩個空文件夾,分別命名為“src”與“port”,src文件夾用于保存FreeRTOS中的核心源文件,也就是我們常說的‘.c文件’,port文件夾用于保存內存管理以及處理器架構相關代碼,這些代碼FreeRTOS官方已經提供給我們的,直接使用即可,在前面已經說了,FreeRTOS是軟件,我們的開發版是硬件,軟硬件必須有橋梁來連接,這些與處理器架構相關的代碼,可以稱之為RTOS硬件接口層,它們位于FreeRTOS/Source/Portable文件夾下。
2.1.1
打開FreeRTOS V9.0.0源碼,在“FreeRTOSv9.0.0\FreeRTOS\Source”目錄下找到所有的‘.c文件’,將它們拷貝到我們新建的src文件夾中

2.1.2
打開FreeRTOS V9.0.0源碼,在“FreeRTOSv9.0.0\FreeRTOS\Source\portable”目錄下找到“MemMang”文件夾與“RVDS”文件夾,將它們拷貝到我們新建的port文件夾中

2.1.3
打開FreeRTOS V9.0.0源碼,在“FreeRTOSv9.0.0\ FreeRTOS\Source”目錄下找到“include”文件夾,它是我們需要用到FreeRTOS的一些頭文件,將它直接拷貝到我們新建的FreeRTOS文件夾中,完成這一步之后就可以看到我們新建的FreeRTOS文件夾已經有3個文件夾,這3個文件夾就包含FreeRTOS的核心文件,至此,FreeRTOS的源碼就提取完成。

2.2添加到工程
2.2.1添加FreeRTOSConfig.h文件
FreeRTOSConfig.h文件是FreeRTOS的工程配置文件,因為FreeRTOS是可以裁剪的實時操作內核,應用于不同的處理器平臺,用戶可以通過修改這個FreeRTOS內核的配置頭文件來裁剪FreeRTOS的功能,所以我們把它拷貝一份放在user這個文件夾下面。
打開FreeRTOSv9.0.0源碼,在“FreeRTOSv9.0.0\FreeRTOS\Demo”文件夾下面找到“CORTEX_STM32F103_Keil”這個文件夾,雙擊打開,在其根目錄下找到這個“FreeRTOSConfig.h”文件,然后拷貝到我們工程的user文件夾下即可,等下我們需要對這個文件進行修改。
2.2.2創建工程分組
接下來我們在mdk里面新建FreeRTOS/src和FreeRTOS/port兩個組文件夾,其中FreeRTOS/src用于存放src文件夾的內容,FreeRTOS/port用于存放port\MemMang文件夾 與port\RVDS\ARM_CM3文件夾的內容。
然后我們將工程文件中FreeRTOS的內容添加到工程中去,按照已經新建的分組添加我們的FreeRTOS工程源碼。
在FreeRTOS/port分組中添加MemMang文件夾中的文件只需選擇其中一個即可,我們選擇“heap_4.c”,這是FreeRTOS的一個內存管理源碼文件。
添加完成后:

2.1.3
打開FreeRTOS V9.0.0源碼,在“FreeRTOSv9.0.0\ FreeRTOS\Source”目錄下找到“include”文件夾,它是我們需要用到FreeRTOS的一些頭文件,將它直接拷貝到我們新建的FreeRTOS文件夾中,完成這一步之后就可以看到我們新建的FreeRTOS文件夾已經有3個文件夾,這3個文件夾就包含FreeRTOS的核心文件,至此,FreeRTOS的源碼就提取完成。

2.2.4修改FreeRTOSConfig.h
FreeRTOSConfig.h是直接從demo文件夾下面拷貝過來的,該頭文件對裁剪整個FreeRTOS所需的功能的宏均做了定義,有些宏定義被使能,有些宏定義被失能,一開始我們只需要配置最簡單的功能即可。要想隨心所欲的配置FreeRTOS的功能,我們必須對這些宏定義的功能有所掌握,下面我們先簡單的介紹下這些宏定義的含義,然后再對這些宏定義進行修改。

2.2.5修改stm32f10x_it.c
SysTick中斷服務函數是一個非常重要的函數,FreeRTOS所有跟時間相關的事情都在里面處理,SysTick就是FreeRTOS的一個心跳時鐘,驅動著FreeRTOS的運行,就像人的心跳一樣,假如沒有心跳,我們就相當于“死了”,同樣的,FreeRTOS沒有了心跳,那么它就會卡死在某個地方,不能進行任務調度,不能運行任何的東西,因此我們需要實現一個FreeRTOS的心跳時鐘,FreeRTOS幫我們實現了SysTick的啟動的配置:在port.c文件中已經實現vPortSetupTimerInterrupt()函數,并且FreeRTOS通用的SysTick中斷服務函數也實現了:在port.c文件中已經實現xPortSysTickHandler()函數,所以移植的時候只需要我們在stm32f10x_it.c文件中實現我們對應(STM32)平臺上的SysTick_Handler()函數即可。FreeRTOS為開發者考慮得特別多,PendSV_Handler()與SVC_Handler()這兩個很重要的函數都幫我們實現了,在在port.c文件中已經實現xPortPendSVHandler()與vPortSVCHandler()函數,防止我們自己實現不了,那么在stm32f10x_it.c中就需要我們注釋掉PendSV_Handler()與SVC_Handler()這兩個函數了。

2.2.6創建任務
這里,我們創建一個單任務,任務使用的棧和任務控制塊是在創建任務的時候FreeRTOS動態分配的。
任務必須是一個死循環,否則任務將通過LR返回,如果LR指向了非法的內存就會產生HardFault_Handler,而FreeRTOS指向一個死循環,那么任務返回之后就在死循環中執行,這樣子的任務是不安全的,所以避免這種情況,任務一般都是死循環并且無返回值的。
并且每個任務循環主體中應該有阻塞任務的函數,否則就會餓死比它優先級更低的任務!!!


