FreeRTOS簡介
FreeRTOS,全稱Free Real Time Operating System,即免費的實時操作系統。相比于計算機中用到的Windows,MacOS,Linux等操作系統,實時操作系統(RTOS)是一種輕量級的操作系統,適用于嵌入式硬件中,用于解決單片機類裸機輪詢方式在處理多個任務時的實時性不高的問題。
目前的實時操作系統有好多種,除FreeRTOS外,還有μCOS、RT-Thread、RTX、Alios Things、Huawei LiteOS等。
什么是RTOS?
實時操作系統(RTOS)的主要特點是可以實現多任務,與多任務系統相對的是裸機系統。
裸機系統
裸機系統就是最初我們學習單片機編程時接觸的那種編程方式,main函數中一個while大循環依次處理各個模塊的任務,對于需要及時檢測的事件會使用中斷。這種使用大循環的程序運行方式也叫輪詢系統,加上中斷處理函數后又稱前后臺系統,中斷處理稱作前臺,無限循環稱作后臺。
多任務系統
多任務系統是將各個處理模塊編寫為單獨的任務,每個任務本身是個無限循環,程序運行初期會創建各個子任務,通過任務調度的方式,利用各任務的阻塞時刻不斷切換運行各個任務,達到一種看起來是多個任務在同時運行的一種效果。并且,通過中斷標志以及任務間通信的相關機制,可以實現任務之間的快速響應。
FreeRTOS特點
使用免費!
系統簡單小巧、文件數量少、通常情況下內核占用4~9k字節空間
搶占式內核
代碼主要由C編寫,可移植性高,已實現在30多種架構的芯片上移植
任務與任務,任務與中斷間的通信方式包括:信號量、消息隊列、事件標志組、任務通知
具有優先級繼承特性的互斥信號令,避免優先級反轉問題
高效的軟件定時器
FreeRTOS源碼目錄結構
這里以FreeRTOS v9.0.0版本為例,代碼包含FreeRTOS和FreeRTOS-Plus文件夾,后者是一些補充文件,初學者用不到,可以先忽略。在FreeRTOS文件夾中主要關注source文件夾,這里是FreeRTOS的全部源碼,包括6個c文件和include文件夾下的多個h文件。另外,在portable文件夾下,是針對不同硬件平臺的單獨區分使用的代碼,目前考慮使用Keil開發STM32F407,所以portable文件夾只需使用RVDS的ARM_CM4F以及MemMang。
關于各個c文件的主要用途:
port.c : 針對不同硬件平臺的接口
heap_4.c : 內存管理相關
croutine.c : 協程相關
event_groups.c : 事件標志組相關
list.c : 列表,FreeRTOS的一種基礎數據結構
queue.c : 隊列相關
tasks.c : 任務創建、掛起、恢復、調度相關
timers.c : 軟件定時器相關
另外在Demo文件夾下還需要用到一個FreeRTOSConfig.h,該文件中通過各種宏定義的方式來配置FreeRTOS需要使用哪些資源。
?

任務相關API函數
任務創建 xTaskCreate()
函數原型(tasks.c中):
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
const char * const pcName,
const uint16_t usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask )
參數:
pxTaskCode:自己創建的任務函數的函數名
pcName:任務的名字,隨意起,字符串型
usStackDepth:任務堆棧大小(實際上申請到的是這里的4倍),設的太小任務可能無法運行!
pvParameters:任務函數的參數,不需要傳參設為NULL即可
uxPriority:任務優先級,0~(configMAX_PRIORITIES-1)
pxCreatedTask:任務句柄,實際是一個指針,也是任務的任務堆棧
返回值:
pdPASS:數值1,任務創建成功,且添加到就緒列表
錯誤代碼:負數,任務創建識別
這里的返回值是BaseType_t,實際它是long類型,可以在portmacro.h文件中看到其定義:
typedef long BaseType_t;
另外,任務句柄的類型為TaskHandle_t,實際它是void *類型,可以在task.h文件中看到其定義:
typedef void * TaskHandle_t;
注:xTaskCreate()是一種動態創建任務的方式,系統通過heap_4.c的配置為任務自動分配相關內存,還有一種靜態創建任務的方式xTaskCreateStatic(),這里先不介紹。
任務刪除 vTaskDelete()
函數原型(tasks.c中):
void vTaskDelete( TaskHandle_t xTaskToDelete )
參數:
xTaskToDelete:要刪除的任務的任務句柄
注:通過 xTaskCreate()動態創建的任務,在使用vTaskDelete()刪除后,該任務創建時申請的堆棧和內存會在系統的空閑任務中被釋放掉。
任務調度 vTaskStartScheduler()
函數原型(tasks.c中):
void vTaskStartScheduler( void )
不需要參數,開啟后就由FreeRTOS開始任務調度工作。
程序設計
主函數
主函數還是我們熟悉的main函數,但FreeRTOS里的main函數不需要自己設計成死循環,只需要創建任務并開啟任務調度,即可使系統持續運行。
任務的創建一般都是先創建一個開始任務,然后開始任務再負責創建其它子任務。
int main(void)
{
//設置系統中斷優先級分組4(FreeRTOS中的默認方式!)
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
//初始化LED端口
LED_Init();
//創建開始任務
xTaskCreate((TaskFunction_t )start_task, //任務函數
(const char* )"start_task", //任務名稱
(uint16_t )START_STK_SIZE, //任務堆棧大小
(void* )NULL, //傳遞給任務函數的參數
(UBaseType_t )START_TASK_PRIO, //任務優先級
(TaskHandle_t* )&StartTask_Handler); //任務句柄
//開啟任務調度
vTaskStartScheduler();
}
開始任務函數
開始任務函數的功能就是用來創建其它的子任務,創建完之后會把自己刪除掉。
//開始任務任務函數
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //進入臨界區
//創建TASK1任務
xTaskCreate((TaskFunction_t )task1_task,
(const char* )"task1_task",
(uint16_t )TASK1_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK1_TASK_PRIO,
(TaskHandle_t* )&Task1Task_Handler);
//創建TASK2任務
xTaskCreate((TaskFunction_t )task2_task,
(const char* )"task2_task",
(uint16_t )TASK2_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK2_TASK_PRIO,
(TaskHandle_t* )&Task2Task_Handler);
vTaskDelete(StartTask_Handler); //刪除開始任務
taskEXIT_CRITICAL(); //退出臨界區
}
兩個任務函數
每個任務函數都是一個死循環,注意循環中必須添加vTaskDelay()延時函數,用于任務的切換。
//task1任務函數
void task1_task(void *pvParameters)
{
while(1)
{
LEDa_Toggle;
vTaskDelay(500); //延時500ms
}
}
//task2任務函數
void task2_task(void *pvParameters)
{
while(1)
{
LEDb_ON;
vTaskDelay(200); //延時200ms
LEDb_OFF;
vTaskDelay(800); //延時800ms
}
}
main.c所有程序
#include "stm32f4xx.h"
#include "led.h"
#include "FreeRTOS.h"
#include "task.h"
//任務參數--------------------------
//優先級 堆棧大小 任務句柄 任務函數
#define START_TASK_PRIO 1
#define START_STK_SIZE 128
TaskHandle_t StartTask_Handler;
void start_task(void *pvParameters);
#define TASK1_TASK_PRIO 2
#define TASK1_STK_SIZE 128
TaskHandle_t Task1Task_Handler;
void task1_task(void *pvParameters);
#define TASK2_TASK_PRIO 3
#define TASK2_STK_SIZE 128
TaskHandle_t Task2Task_Handler;
void task2_task(void *pvParameters);
int main(void)
{
//設置系統中斷優先級分組4(FreeRTOS中的默認方式!)
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
//初始化LED端口
LED_Init();
//創建開始任務
xTaskCreate((TaskFunction_t )start_task, //任務函數
(const char* )"start_task", //任務名稱
(uint16_t )START_STK_SIZE, //任務堆棧大小
(void* )NULL, //傳遞給任務函數的參數
(UBaseType_t )START_TASK_PRIO, //任務優先級
(TaskHandle_t* )&StartTask_Handler); //任務句柄
//開啟任務調度
vTaskStartScheduler();
}
//開始任務任務函數
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //進入臨界區
//創建TASK1任務
xTaskCreate((TaskFunction_t )task1_task,
(const char* )"task1_task",
(uint16_t )TASK1_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK1_TASK_PRIO,
(TaskHandle_t* )&Task1Task_Handler);
//創建TASK2任務
xTaskCreate((TaskFunction_t )task2_task,
(const char* )"task2_task",
(uint16_t )TASK2_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK2_TASK_PRIO,
(TaskHandle_t* )&Task2Task_Handler);
vTaskDelete(StartTask_Handler); //刪除開始任務
taskEXIT_CRITICAL(); //退出臨界區
}
//task1任務函數
void task1_task(void *pvParameters)
{
while(1)
{
LEDa_Toggle;
vTaskDelay(500); //延時500ms
}
}
//task2任務函數
void task2_task(void *pvParameters)
{
while(1)
{
LEDb_ON;
vTaskDelay(200); //延時200ms
LEDb_OFF;
vTaskDelay(800); //延時800ms
}
}
運行結果
運行效果是板子上的兩個LED按照各自任務函數中設定的亮滅時間不斷閃爍。
使用系統的原因就是可以讓兩個任務看起來像是同時運行,試想,如果是裸機系統,雖然也可以實現同樣功能(這兩個LED任務的閃爍規律比較簡單),但需要將兩個任務結合起來管理亮滅時間,兩個任務就糾纏在一起了,如果是兩個更復雜的任務,裸機系統可能就無法實現了。
審核編輯:湯梓紅
-
FreeRTOS
+關注
關注
12文章
485瀏覽量
63410 -
實時操作系統
+關注
關注
1文章
202瀏覽量
31140
發布評論請先 登錄
相關推薦
FreeRTOS中的任務管理
轉:freeRTOS任務創建
STM32CUBE的freertos的任務創建
FreeRTOS創建任務的流程分享
FreeRTOS任務如何創建和刪除?
FreeRTOS筆記(四):任務創建/刪除,掛起/解掛詳解

#FreeRTOS學習筆記(二):任務創建/刪除,掛起/解掛

FreeRTOS高級篇2---FreeRTOS任務創建分析

FreeRTOS系列第10篇---FreeRTOS任務創建和刪除

評論