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

news2024/10/7 12:18:55

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执行串口打印,每一秒打一次信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1886991.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RK3568平台(USB篇)USB HID设备

一.USB HID设备简介 USB HID设备主要用于和计算机进行交互通信,典型的USB HID类设备包括USB键盘、USB鼠标、USB游戏手柄等等,这些都是日常生活中常见的设备。以USB接口的鼠标为例,打开计算机的“设备管理器”,可以在“鼠标和其他…

mac上使用finder时候,显示隐藏的文件或者文件夹

默认在finder中是不显示隐藏的文件和文件夹的,但是想创建.gitignore文件,并向里面写入内容,即便是打开xcode也是不显示这几个隐藏文件的,那有什么办法呢? 使用快捷键: 使用finder打开包含隐藏文件的文件夹…

Web缓存代理和CDN 内容分发网络

目录 1.WEB缓存代理 1.1 WEB缓存代理作用 1.2 常见WEB缓存代理 1.3 Nginx 配置 缓存代理 2. CDN内容分发网络 1.WEB缓存代理 1.1 WEB缓存代理作用 存储一些之前给访问过的,且可能要被再次访问的静态网页资源对象,使客户端可以直接从缓存代理服务器…

NSSCTF-Web题目19(数据库注入、文件上传、php非法传参)

目录 [LitCTF 2023]这是什么?SQL !注一下 ! 1、题目 2、知识点 3、思路 [SWPUCTF 2023 秋季新生赛]Pingpingping 4、题目 5、知识点 6、思路 [LitCTF 2023]这是什么?SQL !注一下 ! 1、题目 2、知识…

【数值计算库-超长笔记】Python-Mpmath库:高精度数值计算

原文链接:https://www.cnblogs.com/aksoam/p/18279394 更多精彩,关注博客园主页,不断学习!不断进步! 我的主页 csdn很少看私信,有事请b站私信 博客园主页-发文字笔记-常用 有限元鹰的主页 内容&#xf…

RTSP协议在视频监控系统中的典型应用、以及视频监控设备的rtsp地址格式介绍

目录 一、协议概述 1、定义 2、提交者 3、位置 二、主要特点 1、实时性 2、可扩展性 3、控制功能 4、回放支持 5、网络适应性 三、RTSP的工作原理 1、会话准备 2、会话建立 3、媒体流控制 4、会话终止 5、媒体数据传输 四、协议功能 1、双向性 2、带外协议 …

已解决java.awt.geom.NoninvertibleTransformException:在Java2D中无法逆转的转换的正确解决方法,亲测有效!!!

已解决java.awt.geom.NoninvertibleTransformException:在Java2D中无法逆转的转换的正确解决方法,亲测有效!!! 目录 问题分析 出现问题的场景 报错原因 解决思路 解决方法 1. 检查缩放因子 修改后的缩放变换 …

《昇思25天学习打卡营第9天|onereal》

继续学习昨天的 基于MindNLPMusicGen生成自己的个性化音乐 生成音乐 MusicGen支持两种生成模式:贪心(greedy)和采样(sampling)。在实际执行过程中,采样模式得到的结果要显著优于贪心模式。因此我们默认启…

实用软件分享-----一款免费的投屏软件(支持手机投屏到电脑)Aiseesoft Phone Mirror 2.2.36 x64

专栏介绍:本专栏主要分享一些实用的软件(Po Jie版); 声明1:软件不保证时效性;只能保证在写本文时,该软件是可用的;不保证后续时间该软件能一直正常运行;不保证没有bug;如果软件不可用了,我知道后会第一时间在题目上注明(已失效)。介意者请勿订阅。 声明2:本专栏的…

JDeveloper 12C 官网下载教程

首先、我们要登录Oracle官网 Oracle 甲骨文中国 | 云应用和云平台 登录进去如果不是中文可以点击右上角带有国旗的图标就行更改,选择一个你能看懂的文字。 然后,点击“资源”—点击“开发人员下载” 然后,点击“开发工具” 这里有很多工具可…

Codeforces Round 954 (Div. 3)(A~E)

目录 A. X Axis B. Matrix Stabilization C. Update Queries D. Mathematical Problem A. X Axis Problem - A - Codeforces 直接找到第二大的数&#xff0c;答案就是这个数与其他两个数的差值的和。 void solve() {vector<ll>a;for (int i 1; i < 3; i){int x;…

美团实习—后端开发凉经

面试经历分享 日期&#xff1a; 4月22日时长&#xff1a; 50分钟 意外之喜 没想到在面试过程中&#xff0c;我再次被选中进行下一轮&#xff0c;这确实让我感到有些意外和欣喜。这次面试经历对我而言&#xff0c;不仅是一次技能的检验&#xff0c;更是一次知…

【LeetCode】九、双指针算法:环形链表检测 + 救生艇

文章目录 1、双指针算法1.1 对撞双指针1.2 快慢双指针 2、leetcode141&#xff1a;环形链表3、leetcode881&#xff1a;救生艇 1、双指针算法 用两个指针来共同解决一个问题&#xff1a; 1.1 对撞双指针 比如先有一个有序的数组array int[] array {1, 4, 5, 7, 9}先要找两个…

MM-LLM:使用Llava类构建图文多模态大模型实践

多模态大模型的结构如上&#xff0c;llava是用两层MLP作为连接器。该模式也是后续很多工作的基础。 本文主要参考了https://github.com/yuanzhoulvpi2017/zero_nlp/tree/main/train_llava的工作&#xff0c;最初是在b站看到的&#xff0c;讲解的很细致。 基础模型 大语言模型…

【BES2500x系列 -- RTX5操作系统】深入探索CMSIS-RTOS RTX -- 同步与通信篇 -- 消息队列和邮箱处理 --(四)

&#x1f48c; 所属专栏&#xff1a;【BES2500x系列】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f49…

容器内存

一、容器内存概述 容器本质上还是一个进程&#xff0c;是一个被隔离和限制的进程。因此容器内存和进程内存在表现形式上其实是一样的&#xff0c;这块主要涉及三部分内容&#xff1a;RSS&#xff0c;page cache和swap这三部分&#xff0c;容器基于memory Cgroup对内存进行限制…

k8s部署单机版mysql8

一、创建命名空间 # cat mysql8-namespace.yaml apiVersion: v1 kind: Namespace metadata:name: mysql8labels:name: mysql8# kubectl apply -f mysql8-namespace.yaml namespace/mysql8 created# kubectl get ns|grep mysql8 mysql8 Active 8s二、创建mysql配…

某网页gpt的JS逆向

原网页网址 (base64) 在线解码 aHR0cHM6Ly9jbGF1ZGUzLmZyZWUyZ3B0Lnh5ei8 逆向效果图 调用代码&#xff08;复制即用&#xff09; 把倒数第三行换成下面的base64解码 aHR0cHM6Ly9jbGF1ZGUzLmZyZWUyZ3B0Lnh5ei9hcGkvZ2VuZXJhdGU import hashlib import time import reques…

Python学习篇:PyCharm的基本使用教程(二)

目录 1 前言 2 创建Python项目 3 创建Python文件 4 编写 Hello World 并运行 5 PyCharm界面简介 1 前言 PyCharm的使用贯穿整个Python的学习&#xff0c;所以单独拿出来出教程不合适&#xff0c;说多了对于新手来说也还是不明白&#xff0c;这里我们先从学习开始前大家需…

【仪器仪表】 矢量网络分析仪 Vector Network Analyzer

主要功能&#xff1a; 测量S参数&#xff1a; S11&#xff08;输入反射系数&#xff09;&#xff1a;测量输入端口的反射。S21&#xff08;正向传输系数&#xff09;&#xff1a;测量从输入端口到输出端口的传输。S12&#xff08;反向传输系数&#xff09;&#xff1a;测量从输…