欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 养生 > STM32F1+HAL库+FreeTOTS学习3——任务创建(动态和静态两种)

STM32F1+HAL库+FreeTOTS学习3——任务创建(动态和静态两种)

2024/10/24 2:01:55 来源:https://blog.csdn.net/weixin_67907028/article/details/140136079  浏览:    关键词:STM32F1+HAL库+FreeTOTS学习3——任务创建(动态和静态两种)

STM32F1+HAL库+FreeTOTS学习3——任务创建(动态和静态两种)

  • 任务创建API函数
  • 任务创建流程
  • 代码实现
    • 1. 动态任务创建和删除
    • 2. 静态任务创建和删除

上期我们学习了STM32移植FreeRTOS搭建基准工程,现在我们来学习任务创建

任务创建API函数

前面我们了解到,FreeRTOS相对于裸机开发,最大的不同在与支持多任务同时运行,那么FreeRTOS上运行多少个任务,任务运行的优先级、堆栈大小,这些都是怎么确定?当然是我们自己去创建任务,自己确定。。。。。。。

FreeRTOS的任务创建删除本质就是调用FreeRTOS的API函数,分为动态创建和静态创建两种:

  • 动态创建的任务,由FreeRTOS自己从管理的堆栈中分配,用户只需要确定堆栈大小即可。
  • 静态创建的任务,由用户自己定义堆栈,将定义好的堆栈分配给任务。这部分堆栈由用户控制和管理,不受FreeRTOS的管控。

具体API函数如下:

  1. 动态创建任务函数
BaseType_t xTaskCreate
( 	TaskFunction_t 				pxTaskCode,		/* 指向任务函数的指针 */					const char * const 				pcName, 		/* 任务名字,最大长度configMAX_TASK_NAME_LEN */const 	configSTACK_DEPTH_TYPE 		usStackDepth, 	/* 任务堆栈大小,注意字为单位 */void * const 					pvParameters,	/* 传递给任务函数的参数 */UBaseType_t 					uxPriority,		/* 任务优先级,范围:0 ~ configMAX_PRIORITIES - 1 */TaskHandle_t * const 			pxCreatedTask 	/* 任务句柄,就是任务的任务控制块 */
);/*
返回值为:pdPASS ,表示创建成功
返回值为:errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY,表示创建失败
*/
  1. 静态创建任务
TaskHandle_t xTaskCreateStatic
(TaskFunction_t		pxTaskCode,				/* 指向任务函数的指针 */const char * const		pcName,				/* 任务函数名 */const uint32_t			ulStackDepth, 			/* 任务堆栈大小注意字为单位 */void * const			pvParameters, 			/* 传递的任务函数参数 */UBaseType_t			uxPriority, 				/* 任务优先级 */StackType_t * const		puxStackBuffer, 			/* 任务堆栈,一般为数组,由用户分配 */StaticTask_t * const		pxTaskBuffer				/* 任务控制块指针,由用户分配 */
); /*
返回值为NULL:表示任务创建失败
返回值为其他值:任务句柄,任务创建成功
*/
  1. 任务删除函数
  • 被删除的任务将从就绪态任务列表、阻塞态任务列表、挂起态任务列表和事件列表中移除。
  • 当传入的参数为NULL,则代表删除任务自身(当前正在运行的任务)
  • 空闲任务会负责释放被删除任务中由系统分配的内存,但是由用户在任务删除前申请的内存, 则需要由用户在任务被删除前提前释放,否则将导致内存泄露
void vTaskDelete(TaskHandle_t xTaskToDelete);/*
参数为待删除任务的句柄,用于删除已
*/

任务创建流程

动态创建任务函数创建流程:

  1. 将宏configSUPPORT_DYNAMIC_ALLOCATION 配置为 1
  2. 定义函数入口参数
  3. 编写任务函数
  4. 完成以上三个步骤即可完成一个任务的动态创建,任务创建完毕后任务会立刻进入就绪状态,由任务调度器控制并运行,内部实现方法如下:

在这里插入图片描述
在这里插入图片描述

静态创建任务使用流程

  1. 需将宏configSUPPORT_STATIC_ALLOCATION 配置为 1
  2. 定义空闲任务&定时器任务的任务堆栈及TCB
  3. 实现两个接口函数:vApplicationGetIdleTaskMemory( ) 和vApplicationGetTimerTaskMemory ( )
  4. 定义函数入口参数
  5. 编写任务函数
  6. 任务创建完毕后任务会立刻进入就绪状态,由任务调度器控制并运行,内部实现方法如下:
    在这里插入图片描述

删除任务流程

  1. 使用删除任务函数,需将宏INCLUDE_vTaskDelete 配置为 1
  2. 入口参数输入需要删除的任务句柄(NULL代表删除本身)
  3. 内部实现方式如下:
    在这里插入图片描述

代码实现

1. 动态任务创建和删除

  1. 在main.c中调用如下函数,进入FreeRTOS操作系统。
	freertos_demo();
  1. 在freertos_demo.c里面编写动态任务创建,并编写任务功能函数
#include "freertos_demo.h"
#include "main.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"/******************************************************************************************************/
/*FreeRTOS配置*//* START_TASK 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define START_TASK_PRIO 1                   /* 任务优先级 */
#define START_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            StartTask_Handler;  /* 任务句柄 */
void start_task(void *pvParameters);        /* 任务函数 *//* TASK1 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK1_PRIO      2                   /* 任务优先级 */
#define TASK1_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task1Task_Handler;  /* 任务句柄 */
void task1(void *pvParameters);             /* 任务函数 *//* TASK2 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK2_PRIO      3                   /* 任务优先级 */
#define TASK2_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task2Task_Handler;  /* 任务句柄 */
void task2(void *pvParameters);             /* 任务函数 *//******************************************************************************************************//* LCD刷屏时使用的颜色 *//*** @brief       FreeRTOS例程入口函数* @param       无* @retval      无*/
void freertos_demo(void)
{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();		//开启任务调度
}/*** @brief       start_task* @param       pvParameters : 传入参数(未用到)* @retval      无*/
void start_task(void *pvParameters)
{taskENTER_CRITICAL();           /* 进入临界区,关闭中断,此时停止任务调度*//* 创建任务1 */xTaskCreate((TaskFunction_t )task1,(const char*    )"task1",(uint16_t       )TASK1_STK_SIZE,(void*          )NULL,(UBaseType_t    )TASK1_PRIO,(TaskHandle_t*  )&Task1Task_Handler);/* 创建任务2 */xTaskCreate((TaskFunction_t )task2,(const char*    )"task2",(uint16_t       )TASK2_STK_SIZE,(void*          )NULL,(UBaseType_t    )TASK2_PRIO,(TaskHandle_t*  )&Task2Task_Handler);vTaskDelete(StartTask_Handler); /* 删除开始任务 */taskEXIT_CRITICAL();            /* 退出临界区,重新开启中断,开启任务调度 */
}/*** @brief       task1* @param       pvParameters : 传入参数(未用到)* @retval      无*/
void task1(void *pvParameters)
{while(1){HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);  printf("task1 start\r\n");/* LED0闪烁 */vTaskDelay(1000);                                               /* 延时1000ticks */}
}/*** @brief       task2* @param       pvParameters : 传入参数(未用到)* @retval      无*/
void task2(void *pvParameters)
{float float_num = 0.0;while(1){float_num += 0.01f;                         /* 更新数值 */printf("float_num: %0.4f\r\n", float_num);  /* 打印数值 */printf("task2 start\r\n");vTaskDelay(1000);                           /* 延时1000ticks */}
}

2. 静态任务创建和删除

  1. 动态任务创建
    在main.c中调用如下函数,进入FreeRTOS操作系统。
	freertos_demo();
  1. 在freertos_demo.c里面编写静态任务创建,并编写任务功能函数
#include "freertos_demo.h"
#include "main.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"/******************************************************************************************************/
/*FreeRTOS配置*//* START_TASK 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define START_TASK_PRIO 1                  				 /* 任务优先级 */
#define START_STK_SIZE  128                				 /* 任务堆栈大小 */
TaskHandle_t            StartTask_Handler; 				 /* 任务句柄 */
StackType_t   StartTask_Stack[START_STK_SIZE];	 /*任务堆栈*/
StaticTask_t   StartTask_TCB;  						/*任务控制块*/
void start_task(void *pvParameters);       				 /* 任务函数 *//* TASK1 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK1_PRIO      2                   /* 任务优先级 */
#define TASK1_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task1Task_Handler;  /* 任务句柄 */
StackType_t   Task1_Stack[TASK1_STK_SIZE];	 /*任务堆栈*/
StaticTask_t   Task1_TCB;  						/*任务控制块*/
void task1(void *pvParameters);             /* 任务函数 *//* TASK2 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK2_PRIO      3                   /* 任务优先级 */
#define TASK2_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task2Task_Handler;  /* 任务句柄 */
StackType_t   Task2_Stack[TASK2_STK_SIZE];	 /*任务堆栈*/
StaticTask_t   Task2_TCB;  						/*任务控制块*/
void task2(void *pvParameters);             /* 任务函数 *//******************************************************************************************************//* 空闲任务内存分配*/
StaticTask_t idle_task_tcb;
StackType_t  idle_task_stack[configMINIMAL_STACK_SIZE];void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,  //任务控制块内存StackType_t  ** ppxIdleTaskStackBuffer,uint32_t * pulIdleTaskStackSize ) /*lint !e526 Symbol not defined as it is an application callback. */
{* ppxIdleTaskTCBBuffer = &idle_task_tcb;* ppxIdleTaskStackBuffer = idle_task_stack;* pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}/* 软件定时器内存分配*/
StaticTask_t timer_task_tcb;
StackType_t  timer_task_stack[configTIMER_TASK_STACK_DEPTH];
void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,StackType_t ** ppxTimerTaskStackBuffer,uint32_t * pulTimerTaskStackSize )
{* ppxTimerTaskTCBBuffer = &timer_task_tcb;* ppxTimerTaskStackBuffer = timer_task_stack;* pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}/*** @brief       FreeRTOS例程入口函数* @param       无* @retval      无*/void freertos_demo(void)
{//静态创建任务函数,返回值为任务句柄StartTask_Handler = xTaskCreateStatic( (TaskFunction_t) start_task,	//指向任务函数的指针(const char * const)"start_task", 			//任务函数名(const uint32_t) START_STK_SIZE,		//任务堆栈大小,单位为字节(void * const) NULL,					//传递的任务函数参数(UBaseType_t) START_TASK_PRIO,		//任务优先级(StackType_t * const) StartTask_Stack,		//任务堆栈,一般为数组,用户自己分配(StaticTask_t * const) &StartTask_TCB );		//任务控制块指针,由用户分配				vTaskStartScheduler();		//开启任务调度}/*** @brief       start_task* @param       pvParameters : 传入参数(未用到)* @retval      无*/
void start_task(void *pvParameters)
{taskENTER_CRITICAL();           /* 进入临界区,关闭中断,此时停止任务调度*//* 创建任务1,静态的方式 */Task1Task_Handler = xTaskCreateStatic( (TaskFunction_t			) task1,		//指向任务函数的指针( char * 	) "task1", 	//任务函数名( uint32_t		) TASK1_STK_SIZE,	//任务堆栈大小,单位为字节(void * 			) NULL,	//传递的任务函数参数(UBaseType_t			) TASK1_PRIO,			//任务优先级(StackType_t * 	) Task1_Stack,	//任务堆栈,一般为数组,用户自己分配(StaticTask_t * ) &Task1_TCB );	//任务控制块指针,由用户分配/* 创建任务2,静态的方式 */Task2Task_Handler = xTaskCreateStatic( (TaskFunction_t			) task2,		//指向任务函数的指针( char * 	) "task2", 	//任务函数名( uint32_t		) TASK2_STK_SIZE,	//任务堆栈大小,单位为字节(void * 			) NULL,	//传递的任务函数参数(UBaseType_t			) TASK2_PRIO,			//任务优先级(StackType_t * 	) Task2_Stack,	//任务堆栈,一般为数组,用户自己分配(StaticTask_t * ) &Task2_TCB );	//任务控制块指针,由用户分配vTaskDelete(StartTask_Handler); /* 删除开始任务 */taskEXIT_CRITICAL();            /* 退出临界区,重新开启中断,开启任务调度 */
}/*** @brief       task1* @param       pvParameters : 传入参数(未用到)* @retval      无*/
void task1(void *pvParameters)
{while(1){HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);  printf("task1 start\r\n");/* LED0闪烁 */vTaskDelay(1000);                                               /* 延时1000ticks */}
}/*** @brief       task2* @param       pvParameters : 传入参数(未用到)* @retval      无*/
void task2(void *pvParameters)
{float float_num = 0.0;while(1){float_num += 0.01f;                         /* 更新数值 */printf("float_num: %0.4f\r\n", float_num);  /* 打印数值 */printf("task2 start\r\n");vTaskDelay(1000);                           /* 延时1000ticks */}
}

静态实现和动态实现的代码作用是一样的,这里统一解释以下:

  1. 创建了一个开始任务,在开始任务中创建任务1和任务2,创建完成后删除开始任务。
  2. 任务1执行LED闪烁,周期为1S
  3. 任务2执行串口打印,每一秒打一次信息。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com