0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

FreeRTOS介紹與基礎(chǔ)任務(wù)創(chuàng)建

碼農(nóng)愛學(xué)習(xí) ? 來源:碼農(nóng)愛學(xué)習(xí) ? 作者:碼農(nóng)愛學(xué)習(xí) ? 2022-09-26 09:00 ? 次閱讀

FreeRTOS簡介

FreeRTOS,全稱Free Real Time Operating System,即免費的實時操作系統(tǒng)。相比于計算機(jī)中用到的Windows,MacOS,Linux等操作系統(tǒng),實時操作系統(tǒng)(RTOS)是一種輕量級的操作系統(tǒng),適用于嵌入式硬件中,用于解決單片機(jī)類裸機(jī)輪詢方式在處理多個任務(wù)時的實時性不高的問題。

目前的實時操作系統(tǒng)有好多種,除FreeRTOS外,還有μCOS、RT-Thread、RTX、Alios Things、Huawei LiteOS等。

什么是RTOS?

實時操作系統(tǒng)(RTOS)的主要特點是可以實現(xiàn)多任務(wù),與多任務(wù)系統(tǒng)相對的是裸機(jī)系統(tǒng)。

裸機(jī)系統(tǒng)

裸機(jī)系統(tǒng)就是最初我們學(xué)習(xí)單片機(jī)編程時接觸的那種編程方式,main函數(shù)中一個while大循環(huán)依次處理各個模塊的任務(wù),對于需要及時檢測的事件會使用中斷。這種使用大循環(huán)的程序運行方式也叫輪詢系統(tǒng),加上中斷處理函數(shù)后又稱前后臺系統(tǒng),中斷處理稱作前臺,無限循環(huán)稱作后臺。

多任務(wù)系統(tǒng)

多任務(wù)系統(tǒng)是將各個處理模塊編寫為單獨的任務(wù),每個任務(wù)本身是個無限循環(huán),程序運行初期會創(chuàng)建各個子任務(wù),通過任務(wù)調(diào)度的方式,利用各任務(wù)的阻塞時刻不斷切換運行各個任務(wù),達(dá)到一種看起來是多個任務(wù)在同時運行的一種效果。并且,通過中斷標(biāo)志以及任務(wù)間通信的相關(guān)機(jī)制,可以實現(xiàn)任務(wù)之間的快速響應(yīng)。

FreeRTOS特點

使用免費!

系統(tǒng)簡單小巧、文件數(shù)量少、通常情況下內(nèi)核占用4~9k字節(jié)空間

搶占式內(nèi)核

代碼主要由C編寫,可移植性高,已實現(xiàn)在30多種架構(gòu)的芯片上移植

任務(wù)與任務(wù),任務(wù)與中斷間的通信方式包括:信號量、消息隊列、事件標(biāo)志組、任務(wù)通知

具有優(yōu)先級繼承特性的互斥信號令,避免優(yōu)先級反轉(zhuǎn)問題

高效的軟件定時器

FreeRTOS源碼目錄結(jié)構(gòu)

這里以FreeRTOS v9.0.0版本為例,代碼包含F(xiàn)reeRTOS和FreeRTOS-Plus文件夾,后者是一些補充文件,初學(xué)者用不到,可以先忽略。在FreeRTOS文件夾中主要關(guān)注source文件夾,這里是FreeRTOS的全部源碼,包括6個c文件和include文件夾下的多個h文件。另外,在portable文件夾下,是針對不同硬件平臺的單獨區(qū)分使用的代碼,目前考慮使用Keil開發(fā)STM32F407,所以portable文件夾只需使用RVDS的ARM_CM4F以及MemMang。

關(guān)于各個c文件的主要用途:

port.c : 針對不同硬件平臺的接口

heap_4.c : 內(nèi)存管理相關(guān)

croutine.c : 協(xié)程相關(guān)

event_groups.c : 事件標(biāo)志組相關(guān)

list.c : 列表,F(xiàn)reeRTOS的一種基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)

queue.c : 隊列相關(guān)

tasks.c : 任務(wù)創(chuàng)建、掛起、恢復(fù)、調(diào)度相關(guān)

timers.c : 軟件定時器相關(guān)

另外在Demo文件夾下還需要用到一個FreeRTOSConfig.h,該文件中通過各種宏定義的方式來配置FreeRTOS需要使用哪些資源。

?

poYBAGMwYBWASii5AAHkTVYjmyU506.png

任務(wù)相關(guān)API函數(shù)

任務(wù)創(chuàng)建 xTaskCreate()

函數(shù)原型(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 ) 

參數(shù)

pxTaskCode:自己創(chuàng)建的任務(wù)函數(shù)的函數(shù)名

pcName:任務(wù)的名字,隨意起,字符串型

usStackDepth:任務(wù)堆棧大小(實際上申請到的是這里的4倍),設(shè)的太小任務(wù)可能無法運行!

pvParameters:任務(wù)函數(shù)的參數(shù),不需要傳參設(shè)為NULL即可

uxPriority:任務(wù)優(yōu)先級,0~(configMAX_PRIORITIES-1)

pxCreatedTask:任務(wù)句柄,實際是一個指針,也是任務(wù)的任務(wù)堆棧

返回值:

pdPASS:數(shù)值1,任務(wù)創(chuàng)建成功,且添加到就緒列表

錯誤代碼:負(fù)數(shù),任務(wù)創(chuàng)建識別

這里的返回值是BaseType_t,實際它是long類型,可以在portmacro.h文件中看到其定義:

typedef long BaseType_t;

另外,任務(wù)句柄的類型為TaskHandle_t,實際它是void *類型,可以在task.h文件中看到其定義:

typedef void * TaskHandle_t;

注:xTaskCreate()是一種動態(tài)創(chuàng)建任務(wù)的方式,系統(tǒng)通過heap_4.c的配置為任務(wù)自動分配相關(guān)內(nèi)存,還有一種靜態(tài)創(chuàng)建任務(wù)的方式xTaskCreateStatic(),這里先不介紹。

任務(wù)刪除 vTaskDelete()

函數(shù)原型(tasks.c中):

void vTaskDelete( TaskHandle_t xTaskToDelete )

參數(shù):

xTaskToDelete:要刪除的任務(wù)的任務(wù)句柄

注:通過 xTaskCreate()動態(tài)創(chuàng)建的任務(wù),在使用vTaskDelete()刪除后,該任務(wù)創(chuàng)建時申請的堆棧和內(nèi)存會在系統(tǒng)的空閑任務(wù)中被釋放掉。

任務(wù)調(diào)度 vTaskStartScheduler()

函數(shù)原型(tasks.c中):

void vTaskStartScheduler( void )

不需要參數(shù),開啟后就由FreeRTOS開始任務(wù)調(diào)度工作。

程序設(shè)計

主函數(shù)

主函數(shù)還是我們熟悉的main函數(shù),但FreeRTOS里的main函數(shù)不需要自己設(shè)計成死循環(huán),只需要創(chuàng)建任務(wù)并開啟任務(wù)調(diào)度,即可使系統(tǒng)持續(xù)運行。

任務(wù)的創(chuàng)建一般都是先創(chuàng)建一個開始任務(wù),然后開始任務(wù)再負(fù)責(zé)創(chuàng)建其它子任務(wù)。

int main(void)
{ 
	//設(shè)置系統(tǒng)中斷優(yōu)先級分組4(FreeRTOS中的默認(rèn)方式!)
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
	
	//初始化LED端口
	LED_Init();		        			

	//創(chuàng)建開始任務(wù)
	xTaskCreate((TaskFunction_t )start_task,            //任務(wù)函數(shù)
				(const char*    )"start_task",          //任務(wù)名稱
				(uint16_t       )START_STK_SIZE,        //任務(wù)堆棧大小
				(void*          )NULL,                  //傳遞給任務(wù)函數(shù)的參數(shù)
				(UBaseType_t    )START_TASK_PRIO,       //任務(wù)優(yōu)先級
				(TaskHandle_t*  )&StartTask_Handler);   //任務(wù)句柄  
	//開啟任務(wù)調(diào)度				
	vTaskStartScheduler();          
}

開始任務(wù)函數(shù)

開始任務(wù)函數(shù)的功能就是用來創(chuàng)建其它的子任務(wù),創(chuàng)建完之后會把自己刪除掉。

//開始任務(wù)任務(wù)函數(shù)
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //進(jìn)入臨界區(qū)
	
    //創(chuàng)建TASK1任務(wù)
    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);   
    //創(chuàng)建TASK2任務(wù)
    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); //刪除開始任務(wù)
				
    taskEXIT_CRITICAL();            //退出臨界區(qū)
}

兩個任務(wù)函數(shù)

每個任務(wù)函數(shù)都是一個死循環(huán),注意循環(huán)中必須添加vTaskDelay()延時函數(shù),用于任務(wù)的切換。

//task1任務(wù)函數(shù)
void task1_task(void *pvParameters)
{
	while(1)
	{
		LEDa_Toggle;
        vTaskDelay(500); //延時500ms
	}
}

//task2任務(wù)函數(shù)
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"

//任務(wù)參數(shù)--------------------------
//優(yōu)先級 堆棧大小 任務(wù)句柄 任務(wù)函數(shù)
#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)
{ 
	//設(shè)置系統(tǒng)中斷優(yōu)先級分組4(FreeRTOS中的默認(rèn)方式!)
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
	
	//初始化LED端口
	LED_Init();		        			

	//創(chuàng)建開始任務(wù)
	xTaskCreate((TaskFunction_t )start_task,            //任務(wù)函數(shù)
				(const char*    )"start_task",          //任務(wù)名稱
				(uint16_t       )START_STK_SIZE,        //任務(wù)堆棧大小
				(void*          )NULL,                  //傳遞給任務(wù)函數(shù)的參數(shù)
				(UBaseType_t    )START_TASK_PRIO,       //任務(wù)優(yōu)先級
				(TaskHandle_t*  )&StartTask_Handler);   //任務(wù)句柄  
	//開啟任務(wù)調(diào)度				
	vTaskStartScheduler();          
}

//開始任務(wù)任務(wù)函數(shù)
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //進(jìn)入臨界區(qū)
	
    //創(chuàng)建TASK1任務(wù)
    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);   
    //創(chuàng)建TASK2任務(wù)
    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); //刪除開始任務(wù)
				
    taskEXIT_CRITICAL();            //退出臨界區(qū)
}

//task1任務(wù)函數(shù)
void task1_task(void *pvParameters)
{
	while(1)
	{
		LEDa_Toggle;
        vTaskDelay(500); //延時500ms
	}
}

//task2任務(wù)函數(shù)
void task2_task(void *pvParameters)
{
	while(1)
	{
        LEDb_ON;
        vTaskDelay(200); //延時200ms
		LEDb_OFF;
        vTaskDelay(800); //延時800ms
	}
}

運行結(jié)果

運行效果是板子上的兩個LED按照各自任務(wù)函數(shù)中設(shè)定的亮滅時間不斷閃爍。

使用系統(tǒng)的原因就是可以讓兩個任務(wù)看起來像是同時運行,試想,如果是裸機(jī)系統(tǒng),雖然也可以實現(xiàn)同樣功能(這兩個LED任務(wù)的閃爍規(guī)律比較簡單),但需要將兩個任務(wù)結(jié)合起來管理亮滅時間,兩個任務(wù)就糾纏在一起了,如果是兩個更復(fù)雜的任務(wù),裸機(jī)系統(tǒng)可能就無法實現(xiàn)了。

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • FreeRTOS
    +關(guān)注

    關(guān)注

    12

    文章

    484

    瀏覽量

    62172
  • 實時操作系統(tǒng)
    +關(guān)注

    關(guān)注

    1

    文章

    198

    瀏覽量

    30758
收藏 人收藏

    評論

    相關(guān)推薦

    freeRTOS開發(fā)筆記】關(guān)注創(chuàng)建任務(wù)時傳入優(yōu)先級數(shù)值問題

    freeRTOS開發(fā)筆記】關(guān)注創(chuàng)建任務(wù)時傳入的優(yōu)先級數(shù)值問題
    的頭像 發(fā)表于 07-11 09:13 ?2777次閱讀
    【<b class='flag-5'>freeRTOS</b>開發(fā)筆記】關(guān)注<b class='flag-5'>創(chuàng)建</b><b class='flag-5'>任務(wù)</b>時傳入優(yōu)先級數(shù)值問題

    FreeRTOS中的任務(wù)管理

    任務(wù)FreeRTOS 中最基本的調(diào)度單元,它是一段可執(zhí)行的代碼,可以獨立運行。FreeRTOS 中的任務(wù)是基于優(yōu)先級的搶占式調(diào)度,優(yōu)先級高的任務(wù)
    的頭像 發(fā)表于 11-27 17:03 ?1008次閱讀

    轉(zhuǎn):freeRTOS任務(wù)創(chuàng)建

    我們曾經(jīng)在公眾號里給大家推送過關(guān)于freeRTOS在NXP kinetis KV4x上的移植,得到了猿友大量的反饋,很多猿友還是感覺對基礎(chǔ)的一些東西不懂,今天我們就從基礎(chǔ)的任務(wù)創(chuàng)建講起,任務(wù)
    發(fā)表于 07-14 14:18

    STM32CUBE的freertos任務(wù)創(chuàng)建

    目錄問題說明解決步驟驗證方案總結(jié)問題說明STM32CUBE的freertos任務(wù)創(chuàng)建十分簡單方便,但卻有一個麻煩:需要我們把要跑的任務(wù)具體代碼都寫進(jìn)
    發(fā)表于 08-24 08:26

    FreeRTOS任務(wù)創(chuàng)建過程

    FreeRTOS筆記(四):任務(wù)創(chuàng)建/刪除,掛起/解掛詳解在第二篇筆記中介紹任務(wù)創(chuàng)建的API,
    發(fā)表于 02-08 06:10

    FreeRTOS創(chuàng)建任務(wù)的流程分享

    從零入門 FreeRTOS 操作系統(tǒng)之創(chuàng)建任務(wù)啟動方式在 main() 函數(shù)中將硬件和 RTOS 系統(tǒng)先初始化好,然后創(chuàng)建一個啟動任務(wù)后就啟
    發(fā)表于 02-11 06:59

    FreeRTOS任務(wù)的使用

    FreeRTOS學(xué)習(xí)筆記(二):任務(wù)創(chuàng)建/刪除,掛起/解掛上篇文章介紹任務(wù)相關(guān)的基礎(chǔ)知識,本篇文章對F
    發(fā)表于 02-18 07:14

    FreeRTOS任務(wù)如何創(chuàng)建和刪除?

    FreeRTOS移植到Cortex-M3硬件平臺的文章中,我們已經(jīng)見過任務(wù)創(chuàng)建API,但那篇文章的重點在于如何移植FreeRTOS,本文將重點放在
    的頭像 發(fā)表于 03-11 18:08 ?2932次閱讀

    FreeRTOS筆記(四):任務(wù)創(chuàng)建/刪除,掛起/解掛詳解

    FreeRTOS筆記(四):任務(wù)創(chuàng)建/刪除,掛起/解掛詳解在第二篇筆記中介紹任務(wù)創(chuàng)建的API,
    發(fā)表于 12-04 19:36 ?15次下載
    <b class='flag-5'>FreeRTOS</b>筆記(四):<b class='flag-5'>任務(wù)</b><b class='flag-5'>創(chuàng)建</b>/刪除,掛起/解掛詳解

    #FreeRTOS學(xué)習(xí)筆記(二):任務(wù)創(chuàng)建/刪除,掛起/解掛

    FreeRTOS學(xué)習(xí)筆記(二):任務(wù)創(chuàng)建/刪除,掛起/解掛上篇文章介紹任務(wù)相關(guān)的基礎(chǔ)知識,本篇文章對F
    發(fā)表于 12-23 19:56 ?2次下載
    #<b class='flag-5'>FreeRTOS</b>學(xué)習(xí)筆記(二):<b class='flag-5'>任務(wù)</b><b class='flag-5'>創(chuàng)建</b>/刪除,掛起/解掛

    FreeRTOS高級篇2---FreeRTOS任務(wù)創(chuàng)建分析

    FreeRTOS基礎(chǔ)系列《FreeRTOS系列第10篇---FreeRTOS任務(wù)創(chuàng)建和刪除》中介紹
    發(fā)表于 01-26 17:42 ?23次下載
    <b class='flag-5'>FreeRTOS</b>高級篇2---<b class='flag-5'>FreeRTOS</b><b class='flag-5'>任務(wù)</b><b class='flag-5'>創(chuàng)建</b>分析

    FreeRTOS系列第10篇---FreeRTOS任務(wù)創(chuàng)建和刪除

    FreeRTOS移植到Cortex-M3硬件平臺的文章中,我們已經(jīng)見過任務(wù)創(chuàng)建API,但那篇文章的重點在于如何移植FreeRTOS,本文將重點放在
    發(fā)表于 01-26 17:56 ?13次下載
    <b class='flag-5'>FreeRTOS</b>系列第10篇---<b class='flag-5'>FreeRTOS</b><b class='flag-5'>任務(wù)</b><b class='flag-5'>創(chuàng)建</b>和刪除

    FreeRTOS任務(wù)句柄

    摘要:學(xué)過用過FreeRTOS的人都知道,在創(chuàng)建任務(wù)時候我們都要定義一個任務(wù)句柄,這個任務(wù)句柄有啥含義?書上的解釋是
    的頭像 發(fā)表于 04-13 08:18 ?2721次閱讀

    RA FreeRTOS任務(wù)創(chuàng)建

    ,開發(fā)環(huán)境e 2 studio完美支持FreeRTOS,無需額外手動移植。以下介紹如何用瑞薩e 2 studio創(chuàng)建RA系列MCU的FreeRTOS工程。 對于不熟悉瑞薩的FSP開發(fā)環(huán)
    的頭像 發(fā)表于 03-10 14:35 ?1303次閱讀

    RA FreeRTOS任務(wù)創(chuàng)建

    ,開發(fā)環(huán)境e2 studio完美支持FreeRTOS,無需額外手動移植。以下介紹如何用瑞薩e2 studio創(chuàng)建RA系列MCU的FreeRTOS工程。
    的頭像 發(fā)表于 07-12 10:00 ?704次閱讀
    RA <b class='flag-5'>FreeRTOS</b><b class='flag-5'>任務(wù)</b><b class='flag-5'>創(chuàng)建</b>