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;
}
相关推荐
bubiyoushang8886 小时前
51单片机MPU6050 DMP驱动实现
单片机·嵌入式硬件·51单片机
BT-BOX6 小时前
STM32的温湿度防盗安防报警器仿真_LCD1602显示
stm32·安防·烟雾·防盗·lcd1602显示·dht11温湿度·火焰
Deitymoon6 小时前
STM32——继电器
stm32·单片机·嵌入式硬件
恶魔泡泡糖7 小时前
stm32F103C8T6标准库外部中断的概念
stm32·单片机·嵌入式硬件
VBsemi-专注于MOSFET研发定制7 小时前
高端LED封装自动化产线功率MOSFET选型方案——精密、高效与可靠驱动系统设计指南
运维·单片机·自动化
LCG元9 小时前
STM32项目实战:基于STM32F103的智能台灯控制
stm32·单片机·嵌入式硬件
rjszcb10 小时前
mcu.之armv7 contex-M3/M4系列,时钟树,中断, cpu架构,上电启动过程(二)
单片机
姓刘的哦10 小时前
RK3568之I2C子系统(协议)
单片机·嵌入式硬件
咕噜咕噜啦啦10 小时前
一些单片机学习相关名词
单片机·嵌入式硬件
芋头莎莎10 小时前
ESP32 +VSCode与搭建开发环境教程
vscode·单片机