2.创建你的第一个FreeRTOS任务(动态与静态)

经过上一次的移植后,本次开始创建第一个FreeRTOS任务

1.创建一个动态的任务,动态分配内存

cpp 复制代码
 BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,  //函数指针
                        const char * const pcName,   //任务名字
                        const configSTACK_DEPTH_TYPE uxStackDepth, //任务栈大小(深度)
                        void * const pvParameters,   //任务参数
                        UBaseType_t uxPriority,      //任务优先级
                       TaskHandle_t * const pxCreatedTask //任务句柄
 )
//                          函数名            传入参数
//任务函数typedef void (* TaskFunction_t)( void * arg );

上述包含了创建一个任务所需函数以及内部参数注释

1.1初始化硬件

首先初始化你的基础硬件比如LED_init这种确保led可以正常使用。

cpp 复制代码
void system_init()
{
	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	uart_init(115200);	 //串口初始化为115200
 	LED_Init();			     //LED端口初始化
	KEY_Init();          //初始化与按键连接的硬件接口
}

1.2创建任务函数

比如想让一个灯循环闪烁可以这样写

cpp 复制代码
void LED0_TASK(void *param)  //任务函数
{
    while (1)
    {
        LED0 =!LED0;
        vTaskDelay(1000);
    }
    
}

1.3 创建任务

cpp 复制代码
TaskHandle_t xled_task_handle;//首先定义任务句柄(一种结构体)

通过下行命令创建任务

cpp 复制代码
xTaskCreate(LED0_TASK,"open_led",100,NULL,1,&xled_task_handle); //动态分配内存

第一个参数为任务指针,第二个为任务名,第三个为堆栈大小暂时设定为100,传入该任务的参数设为空,最后一个传入刚刚创建的句柄地址。上述就是创建一个动态分配内存任务的过程。

2.创建一个静态分配内存的任务

首先打开FreeRTOSConfig.h,修改如下宏定义

cpp 复制代码
#define configSUPPORT_STATIC_ALLOCATION                 1                       /* 1: 支持静态申请内存, 默认: 0 */  //此时改为1
cpp 复制代码
	//静态分配任务//默认不打开静态分配任务需要去FreeRTOSConfig.h文件中将configSUPPORT_STATIC_ALLOCATION宏定义为1
    TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,//函数指针
                                     const char * const pcName,//任务名字
                                    const configSTACK_DEPTH_TYPE uxStackDepth,//任务栈大小(深度)
                                   void * const pvParameters,//任务参数
                                   UBaseType_t uxPriority,//任务优先级
                                   StackType_t * const puxStackBuffer,//静态栈分配空间
                                   StaticTask_t * const pxTaskBuffer //分配TCB句柄
                               )

首先创建一个任务函数

cpp 复制代码
void LED1_TASK(void *param)  //任务函数
{
    while (1)
    {
        LED1 =!LED1;
        vTaskDelay(500);
    }
    
}

第二步定义一个堆栈数据(一个数组),定义一个任务句柄

cpp 复制代码
StackType_t xTaskLedStack[100] = {0};//注意此时数据堆栈大小需要按照创建的任务堆栈大小的深度一致
StaticTask_t xTaskLedBuffer;

最后创建一个静态任务

cpp 复制代码
  xTaskCreateStatic(LED1_TASK,"LED_Flicker",100,NULL,1,xTaskLedStack,&xTaskLedBuffer);

3.解决错误

通常在静态任务中会出现两个错误,如下

只要按照上面创建任务的方式将这两个函数重定义即可

如下:任务参数含义基本一致

cpp 复制代码
// vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &uxIdleTaskStackSize );//参数1:空闲任务的TCB,参数2:空闲任务的栈,参数3:空闲任务栈大小
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
                                       StackType_t ** ppxIdleTaskStackBuffer,
                                       configSTACK_DEPTH_TYPE * puxIdleTaskStackSize )
   {

       *ppxIdleTaskTCBBuffer = &( xIdleTaskTCBBuffer );
       *ppxIdleTaskStackBuffer = &( xIdleTaskStack[ 0 ] );
       *puxIdleTaskStackSize = 100;
   }

void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
                                        StackType_t ** ppxTimerTaskStackBuffer,
                                        configSTACK_DEPTH_TYPE * puxTimerTaskStackSize )
   {
       *ppxTimerTaskTCBBuffer = &( xTimerTaskTCBBuffer );
       *ppxTimerTaskStackBuffer = &( xTimerTaskStack[ 0 ] );
       *puxTimerTaskStackSize = 100;
   }

总的代码如下:

cpp 复制代码
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "FreeRTOS.h"
#include "task.h"

//  BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,  //函数指针
//                         const char * const pcName,   //任务名字
//                         const configSTACK_DEPTH_TYPE uxStackDepth, //任务栈大小(深度)
//                         void * const pvParameters,   //任务参数
//                         UBaseType_t uxPriority,      //任务优先级
//                         TaskHandle_t * const pxCreatedTask //任务句柄
// )
//                          函数名            传入参数
//任务函数typedef void (* TaskFunction_t)( void * arg );
void system_init()
{
	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
 	LED_Init();			     //LED端口初始化
	KEY_Init();          //初始化与按键连接的硬件接口
}
void LED0_TASK(void *param)  //任务函数
{
    while (1)
    {
        LED0 =!LED0;
        vTaskDelay(1000);
    }
    
}

void LED1_TASK(void *param)  //任务函数
{
    while (1)
    {
        LED1 =!LED1;
        vTaskDelay(500);
    }
    
}
StackType_t xTaskLedStack[100] = {0};//注意此时数据堆栈大小需要按照创建的任务堆栈大小的深度一致
StaticTask_t xTaskLedBuffer;
StaticTask_t xIdleTaskTCBBuffer;
StackType_t xIdleTaskStack[100] = {0};
StaticTask_t xTimerTaskTCBBuffer;
StackType_t xTimerTaskStack[100] = {0};
//如果使用了静态分配内存必须提供如下函数
// vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &uxIdleTaskStackSize );//参数1:空闲任务的TCB,参数2:空闲任务的栈,参数3:空闲任务栈大小
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
                                       StackType_t ** ppxIdleTaskStackBuffer,
                                       configSTACK_DEPTH_TYPE * puxIdleTaskStackSize )
   {

       *ppxIdleTaskTCBBuffer = &( xIdleTaskTCBBuffer );
       *ppxIdleTaskStackBuffer = &( xIdleTaskStack[ 0 ] );
       *puxIdleTaskStackSize = 100;
   }

void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
                                        StackType_t ** ppxTimerTaskStackBuffer,
                                        configSTACK_DEPTH_TYPE * puxTimerTaskStackSize )
   {
       *ppxTimerTaskTCBBuffer = &( xTimerTaskTCBBuffer );
       *ppxTimerTaskStackBuffer = &( xTimerTaskStack[ 0 ] );
       *puxTimerTaskStackSize = 100;
   }
int main(void)
{ 
    TaskHandle_t xled_task_handle;
	system_init();
    //创建任务1
    xTaskCreate(LED0_TASK,"open_led",100,NULL,1,&xled_task_handle); //动态分配内存
	//静态分配任务//默认不打开静态分配任务需要去FreeRTOSConfig.h文件中将configSUPPORT_STATIC_ALLOCATION宏定义为1
    // TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,//函数指针
    //                                 const char * const pcName,//任务名字
    //                                 const configSTACK_DEPTH_TYPE uxStackDepth,//任务栈大小(深度)
    //                                 void * const pvParameters,//任务参数
    //                                 UBaseType_t uxPriority,//任务优先级
    //                                 StackType_t * const puxStackBuffer,//静态栈分配空间
    //                                 StaticTask_t * const pxTaskBuffer 
    //                             )
    xTaskCreateStatic(LED1_TASK,"LED_Flicker",100,NULL,1,xTaskLedStack,&xTaskLedBuffer);
	
    //开启调度器
    vTaskStartScheduler(); 
    while (1)
    {
        ;
    }
//    return 0;
}
相关推荐
芯联智造2 小时前
【stm32简单外设篇】- 震动传感器
c语言·stm32·单片机·嵌入式硬件
Hello_Embed2 小时前
LVGL 入门(八):标签控件 lv_label
前端·笔记·stm32·单片机·嵌入式
海阔天空任鸟飞~12 小时前
蓝汛-BT897-添加按键提示音
c语言·单片机·蓝汛
yrx02030712 小时前
stm32单线串口(空闲中断+DMA接收+阻塞式发送)模式控制舵机
stm32·单片机·嵌入式硬件·单线串口
雾削木12 小时前
STM32HAL输入捕获定时器测量PWM频率和占空比
stm32·单片机·嵌入式硬件
FreakStudio12 小时前
一行命令搞定驱动安装!MicroPython 开发有了自己的 “PyPI”包管理平台!
python·stm32·单片机·嵌入式·arm·电子diy
forAllforMe13 小时前
基于STM32+LAN9252的ether CAT 开发环境搭建
stm32·单片机·嵌入式硬件
半空扫地僧一枚13 小时前
10期:转速模式 (Speed Mode) 和 扭矩模式 (Torque Mode)
单片机·嵌入式硬件·汽车
敬畏_上帝16 小时前
PCtolLCD2002完美版下载以及教程
单片机·嵌入式硬件