FreeRTOS+CubeMX系列第二篇——任务的创建与删除


一. 前言

FreeRTOS中,任务是程序执行的最小单位,也是调度器处理的基本单位。本文主要介绍两种任务创建的方式,一种是在CubeMX中创建任务;另一种是在工程中调用FreeRTOS源码来创建任务,两种方式在本质上是一样的。

二. 任务的创建

开发环境:CubeMX   Vesion 5.4.0
     Keil      Vesion 5.28

2.1 CubeMX中创建任务

在这里插入图片描述
在Tasks and Queues中可以点击Add按钮添加新的任务:

名称功能
Task Name任务名称
Priority任务创建时的优先级
Stack Size任务栈的大小,默认单位为字节
Entry Function任务函数的入口(有别于Task Name,第一条为字符串格式)
Code Generation Option任务函数代码生成方式:
As weak: 产生一个用__weak 修饰符修饰的任务函数;
As external: 产生一个外部引用的任务函数,用户需要自己实现该函数;
Default: 产生一个默认格式的任务函数,用户需要在该函数实现功能
Parameter:传入的参数/指针,一般为NULL
Allocation:创建方式(动态或静态,一般使用动态,很少使用静态方式)

这里主讲参数Code Generation Option,其他参数根据自己需要设定即可。

设置完毕之后点击 OK,就可以看到列表中多出了自己创建的任务。

创建三个任务Code Generation Option分别选择Default、As external、As weak 。

1. 使用Default 。可以在main.c下找到其函数的定义,函数内容必须写在main.c的函数定义中。

2. 使用As weak。在main.c中能找到其函数定义。由于选择了通过__weak 修饰符创建一个弱函数,可以再在别处实现该任务函数。程序执行时会自动寻找到这个另外实现的任务函数。

比如:需要实现LED闪烁,则在其他文件中写上:

//程序执行时会自动寻找到这个任务函数。
void red_led_task(void const * argument)
{
 while(1)
 {
	 HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_SET);
	 osDelay(500);
	 HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_RESET);
	 osDelay(500);
	 HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_RESET);
	 osDelay(500);
 }
}

3.使用As external。由于设置为 As external,故而需要再在别处实现任务函数。程序执行时会自动寻找到实现的任务函数。

比如:需要实现LED闪烁

void green_led_task(void const * argument)
{
 while(1)
 {
	 HAL_GPIO_WritePin(LED_G_GPIO_Port, LED_G_Pin, GPIO_PIN_RESET);
	 osDelay(500);
	 HAL_GPIO_WritePin(LED_G_GPIO_Port, LED_G_Pin, GPIO_PIN_SET);
	 osDelay(500);
	 HAL_GPIO_WritePin(LED_G_GPIO_Port, LED_G_Pin, GPIO_PIN_RESET);
	 osDelay(500);
 }
}

和As weak不同,使用As external用户必须写上函数定义,否则会报错。而As weak由于使用了关键字__weak,即使用户不写函数定义,程序也会执行main.c中的弱函数。

2.2 使用FreeRTOS源码创建任务

/*任务创建函数*/
BaseType_t xTaskCreate(
				TaskFunction_tp vTaskCode,   //函数指针
				const char * constpcName,    //任务描述
				unsigned short usStackDepth, //堆栈大小
				void *pvParameters,          //参数指针
				UBaseType_t uxPriority,      //任务优先级
				TaskHandle_t *pvCreatedTask  //回传句柄
				);
  1. pvTaskCode: 函数指针,指向任务函数的入口。任务永远不会返回(位于死循环内)。该参数类型 TaskFunction_t 定义在文件 projdefs.h 中,定义为:typedef void(*TaskFunction_t)( void * ) ,即参数为空指针类型并返回空类型。
  2. pcName: 任务描述。主要用于调试。字符串的最大长度(包括字符串结束字符)由宏 configMAX_TASK_NAME_LEN 指定,该宏位于 FreeRTOSConfig.h 文件中。
  3. usStackDepth: 指定任务堆栈大小,能够支持的堆栈变量数量(堆栈深度),而不是字节数。比如,在 16 位宽度的堆栈下,usStackDepth 定义为 100,则实际使用 200 字节堆栈存储空间。堆栈的宽度乘以深度必须不超过 size_t 类型所能表示的最大值。比如,size_t 为16位,则可以表示堆栈的最大值是 65535 字节。这是因为堆栈在申请时是以字节为单位的,申请的字节数就是堆栈宽度乘以深度,如果这个乘积超出 size_t 所表示的范围,就会溢出。
  4. pvParameters: 指针,当任务创建时,作为一个参数传递给任务。
  5. uxPriority: 任务的优先级。具有 MPU 支持的系统,可以通过置位优先级参数的 portPRIVILEGE_BIT 位,随意的在特权(系统)模式下创建任务。比如,创建一个优先级为 2 的特权任务,参数 uxPriority 可以设置为 2 或者 portPRIVILEGE_BIT
  6. pvCreatedTask: 用于回传一个句柄(ID),创建任务后可以使用这个句柄引用任务。

举个例子,需要创建一个任务

TaskHandle_t Task1_Handle;//1.定义一个句柄

void Task_1(void *arg);//2.对任务函数进行声明

xTaskCreate(Task_1, "Task1", 256, NULL, 6, &Task1_Handle);//3.创建任务

void Task_1(void *arg)
{
  for (;;)
  {
    //3.函数内容
  }
}

三. 任务的删除

 void vTaskDelete( TaskHandle_t xTask );

如何任务是用xTaskCreate()创建的,那么在此任务被删除以后此任务之前申请的堆栈和控制块和控制内存会在空闲任务中被释放掉,因此当调用函数vTaskDelete()删除任务以后必须给空闲任务一定的运行时间。

四. FreeRTOS文档资料

下面列出的是FreeRTOS比较好的学习资料:

1. FreeRTOS官网(可以下到源码与官方配套文档)

2. FreeRTOS相关API函数手册

3. 正点原子 《STM32F407+FreeRTOS开发手册》

4. 野火《FreeRTOS 内核实现与应用开发实战指南——基于Stm32》

4. FreeRTOS任务案例教学


五.同系列博客

  1. FreeRTOS+CubeMX系列第一篇——初识FreeRTOS
  2. FreeRTOS+CubeMX系列第二篇——任务的创建与删除
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冬瓜~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值