1,前言
本章内容在1,STM32CubeMX生成第一个freeRTOS工程基础上完成。
单片机型号:STM32F407
编程环境 :STM32CubeMX + Keil v5
2,Task配置与分类
Task任务是freeRTOS中十分重要的内容,每个Task都是并行完成的,用户需要增加Task任务来完成自己的工程。以下是STMCubeMX默认生成的一个defaultTask(部分内容已修改),不可删除。以此为例,来介绍Task需要配置哪些内容。
Task Name:任务名称。
Priority:任务优先级。
Stack Size(Words):堆栈空间(字节)。
Entry Function:入口函数名。
Code Generation Option:生成代码选项。
Parameter:参数。
Allocation:分配。
了解需要配置哪些内容后,下面我们聊聊Task的分类。
1.根据Allocation(分配)分类。DynamicTask动态任务(默认)和StaticTask静态任务,其区别在于是否分配固定的Buffer块给任务。
对于动态任务(可以理解为局部变量),只有在调用时随机分配存储单元,没有固定的存储单元。对于静态任务(可以理解为全局变量),固定分配存储单元。
2.根据Code Generation Option(生成代码选项)分类。default(默认)、external(外部)和weak(弱定义),其区别在于生成的Task入口代码存放的位置和类型。
对于default(默认)、weak(弱定义)都可以在freertos.c中找到他们,他们俩的区别在于weak(弱定义)可以重定义。而对于external(外部)需要用户自己在.c文件中定义。
3,STM32CubeMX生成Task任务
由于根据Allocation(分配)分类,静态任务和动态任务代码没有什么不同。所以下面介绍据Code Generation Option(生成代码选项)分类,default(默认)、external(外部)和weak(弱定义)这三种不同的任务。
首先打开Middleware(1),进入下方的FREERTOS(2)进行配置,在Configuration(3)配置框中进行配置。点击Tasks and Queues(4)进行任务配置。
点击右下角Add按钮新建一个任务externalTask,并修改Code Genration Option为As external。
点击右下角Add按钮新建一个任务externalTask,并修改Code Genration Option为As external。
这样子加上默认的任务,我们一共有三个不同Code Genration Option的任务了。接下来我们在Keil MDK中查看这些任务,并添加相应的内容。
4,Keil MDK添加Task具体代码
打开工程,打开freertos.c文件,我们来看一下.c文件中包含哪些内容。
首先是头文件,我们需要添加#include<stdio.h>方便使用printf函数。
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
/* USER CODE END Includes */
其次是Task任务的定义,可以看到定义了三个任务,和我们在CubeMX中看到的相同。
/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
.name = "defaultTask",
.stack_size = 128 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for externalTask */
osThreadId_t externalTaskHandle;
const osThreadAttr_t externalTask_attributes = {
.name = "externalTask",
.stack_size = 128 * 4,
.priority = (osPriority_t) osPriorityLow,
};
/* Definitions for weakTask */
osThreadId_t weakTaskHandle;
const osThreadAttr_t weakTask_attributes = {
.name = "weakTask",
.stack_size = 128 * 4,
.priority = (osPriority_t) osPriorityLow,
};
再往下是Task入口函数的定义。
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
/* USER CODE END FunctionPrototypes */
void DefaultTaskFun(void *argument);
extern void externalTaskFun(void *argument);
void weakTaskFun(void *argument);
再往下可以看到Task的Function函数入口。因为external外部类型的Task是没有定义入口函数的,所以在.c文件中找不到。我们在这里修改一下两个Task函数的内容。
/* USER CODE END Header_DefaultTaskFun */
void DefaultTaskFun(void *argument)
{
/* USER CODE BEGIN DefaultTaskFun */
printf("DefaultTask Begin!\r\n");
/* Infinite loop */
for(;;)
{
printf("DefaultTask Running!!!\r\n");
osDelay(1000);
}
/* USER CODE END DefaultTaskFun */
}
/* USER CODE BEGIN Header_weakTaskFun */
/**
* @brief Function implementing the weakTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_weakTaskFun */
__weak void weakTaskFun(void *argument)
{
/* USER CODE BEGIN weakTaskFun */
printf("weakTask Begin!\r\n");
/* Infinite loop */
for(;;)
{
printf("weakTask Running!!!\r\n");
osDelay(1500);
}
/* USER CODE END weakTaskFun */
}
修改完成,我们在新建两个.c文件。分别是externalTask.c和weakTask.c用来存放用户自定义的Task函数。如下。
//weakTaskFun.c
/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"
#include <stdio.h>
void weakTaskFun(void *argument)
{
/* USER CODE BEGIN weakTaskFun */
printf("weakTask APP Begin!\r\n");
/* Infinite loop */
for(;;)
{
printf("weakTask APP Running!!!\r\n");
osDelay(1500);
}
/* USER CODE END weakTaskFun */
}
//externalTask.c
/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"
#include <stdio.h>
void externalTaskFun(void *argument)
{
/* USER CODE BEGIN weakTaskFun */
printf("externalTask Begin!\r\n");
/* Infinite loop */
while(1)
{
printf("externalTask Running!!!\r\n");
osDelay(2000);
}
/* USER CODE END weakTaskFun */
}
5,烧录与测试
完成代码的修改后,我们点击编译并且烧录。打开串口助手查看到一下现象,说明试验成功。其中weak类型的Task的串口输出是我们用户自定义内容。