八、任务的创建与删除

2023-05-16

文章目录

  • 1、任务的三要素:主体函数、任务栈、任务控制块。
  • 2、与任务相关的部分API函数
    • (1)xTaskCreate
    • (2)void vTaskDelete( TaskHandle_t xTaskToDelete )
  • 3、任务的创建
    • (1)使用静态任务创建函数进行任务创建(使用这个函数创建任务后,会返回一个任务句柄,这个句柄实际上就是一个指针,指向对应任务的任务控制块这个结构体)
      • 1)定义任务函数
      • 2)定义任务栈(这个是静态创建时需要进行的,即静态创建的时候任务控制块和栈空间都需要先定义好)
      • 3)定义任务控制块
      • 4)使用xTaskCreateStatic来创建一个任务
    • (2)使用动态任务创建函数进行任务创建(使用这个函数创建任务时,需要传进去预先定义好的任务句柄)
      • 动态内存空间的堆
      • 1)定义任务函数
      • 2)定义任务句柄(作为任务创建时创进去的实参,创建成功后其指向的是任务控制块)
      • 3)使用xTaskCreate()函数来创建一个任务。
  • 4、任务的删除vTaskDelete(xHandle Taskx)
  • 5、需要注意的几个点
    • (1)任务创建成功后对任务的各种操作都是通过任务句柄来实现的
    • (2)可以使用同一个函数创建两个任务(这时候因为两个函数的栈不一样,所以他们互不影响)
  • 6、动态创建任务函数解析

1、任务的三要素:主体函数、任务栈、任务控制块。

重要:每个任务中所有局部变量占用的空间必须要比其栈空间小,否则可能会出现这个任务内存的溢出而影响其他任务。

2、与任务相关的部分API函数

(1)xTaskCreate

BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, // 函数指针, 任务函数
                       const char * const pcName, // 任务的名字
                       const configSTACK_DEPTH_TYPE usStackDepth, // 栈大小,单位为 word,10 表示40 字节
                       void * const pvParameters, // 调用任务函数时传入的参数
                       UBaseType_t uxPriority, // 优先级
                       TaskHandle_t * const pxCreatedTask ); // 任务句柄, 以后使用它来操作这个任务

在这里插入图片描述

(2)void vTaskDelete( TaskHandle_t xTaskToDelete )

在这里插入图片描述

3、任务的创建

(1)使用静态任务创建函数进行任务创建(使用这个函数创建任务后,会返回一个任务句柄,这个句柄实际上就是一个指针,指向对应任务的任务控制块这个结构体)

即任务使用的栈和任务控制块都事先定义好,即使用的是静态内存。

1)定义任务函数

任务函数实际为一个无限循环且不带返回值的函数。
且在任务函数里面尽量使用局部变量。

2)定义任务栈(这个是静态创建时需要进行的,即静态创建的时候任务控制块和栈空间都需要先定义好)

	 /* 定义LED 任务堆栈 */
	static StackType_t LED_Task_Stack[128];

3)定义任务控制块

	/* AppTaskCreate 任务控制块 */
	static StaticTask_t AppTaskCreate_TCB;
	/* AppTaskCreate 任务控制块 */
	static StaticTask_t LED_Task_TCB;

4)使用xTaskCreateStatic来创建一个任务

int main(void)
{	
  /* 开发板硬件初始化 */
  BSP_Init();
  /* 创建 AppTaskCreate 任务 */
 AppTaskCreate_Handle = xTaskCreateStatic((TaskFunction_t	)AppTaskCreate,		//任务函数
															(const char* 	)"AppTaskCreate",	//任务名称
															(uint32_t 		)128,				//任务堆栈大小
															(void* 		  	)NULL,		//传递给任务函数的参数
															(UBaseType_t 	)3, 			//任务优先级
															(StackType_t*   )AppTaskCreate_Stack,  //任务堆栈
															(StaticTask_t*  )&AppTaskCreate_TCB);//任务控制块   
															
	if(NULL != AppTaskCreate_Handle)/* 创建成功 */
    vTaskStartScheduler();   /* 启动任务,开启调度 */
  
  while(1);   /* 正常不会执行到这里 */    
}



static void AppTaskCreate(void)
{
	taskENTER_CRITICAL();           //进入临界区

	/* 创建LED_Task任务 */
	LED_Task_Handle = xTaskCreateStatic((TaskFunction_t	)LED_Task,		//任务函数
														(const char* 	)"LED_Task",	//任务名称
														(uint32_t 		)128,			//任务堆栈大小
														(void* 		  	)NULL,			//传递给任务函数的参数
														(UBaseType_t 	)4, 				//任务优先级
														(StackType_t*   )LED_Task_Stack,	//任务堆栈
														(StaticTask_t*  )&LED_Task_TCB);	//任务控制块   

if(NULL != LED_Task_Handle)/* 创建成功 */
	printf("LED_Task任务创建成功!\n");
else
	printf("LED_Task任务创建失败!\n");

 vTaskDelete(AppTaskCreate_Handle); //删除AppTaskCreate任务

 taskEXIT_CRITICAL();            //退出临界区
}

任务创建成功后,是处于任务就绪状态,此时任务可以参与操作系统的调度。
若此时还没有开启调度任务就不会被执行。上面在主函数创建任务成功之后开启了调度器。

(2)使用动态任务创建函数进行任务创建(使用这个函数创建任务时,需要传进去预先定义好的任务句柄)

动态内存空间的堆

FreeRTOS在SRAM里面定义一个大数组,即堆内存,供FreeRTOS的动态分配函数使用。
在第一次使用时系统会将堆内存进行初始化。例如

//系统所有总的堆大小
#define configTOTAL_HEAP_SIZE ((size_t)(36*1024))
static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
/* 如果这是第一次调用 malloc 那么堆将需要
初始化,以设置空闲块列表。*/
if ( pxEnd == NULL ){
	prvHeapInit(); 
} 
else
{
	mtCOVERAGE_TEST_MARKER();
}

1)定义任务函数

任务函数实际为一个无限循环且不带返回值的函数。
且在任务函数里面尽量使用局部变量。

2)定义任务句柄(作为任务创建时创进去的实参,创建成功后其指向的是任务控制块)

使用动态任务创建函数的时候,最后一个参数传递的是对应任务的任务句柄的地址,即这个动态任务创建函数的返回值是一个是否成功创建任务的信息,所以需要传进去一个任务句柄,这个任务句柄指向的还是对应任务的任务控制块。

/* 创建任务句柄 */
static TaskHandle_t AppTaskCreate_Handle = NULL;
/* LED 任务句柄 */
static TaskHandle_t LED_Task_Handle = NULL;

3)使用xTaskCreate()函数来创建一个任务。

int main(void)
{
	BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为 pdPASS */
	
	/* 开发板硬件初始化 */
	BSP_Init();
	printf("这是一个[野火]-STM32 全系列开发板-FreeRTOS-工程模板!\r\n");
	/* 创建 AppTaskCreate 任务 */
	xReturn = xTaskCreate((TaskFunction_t )AppTaskCreate, /* 任务入口函数 */
							(const char* )"AppTaskCreate",/* 任务名字 */
							(uint16_t )512, /* 任务栈大小 */
							(void* )NULL,/* 任务入口函数参数 */
							(UBaseType_t )1, /* 任务的优先级 */
							(TaskHandle_t* )&AppTaskCreate_Handle);/* 任务控制块指针 */
	/* 启动任务调度 */
	if (pdPASS == xReturn)
		vTaskStartScheduler(); /* 启动任务,开启调度 */
	else
	return -1;

	while (1); /* 正常不会执行到这里 */
	}


static void AppTaskCreate(void)
{
	BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为 pdPASS */

	taskENTER_CRITICAL(); //进入临界区

	/* 创建 LED_Task 任务 */
	xReturn = xTaskCreate((TaskFunction_t )LED_Task, /* 任务入口函数 */
							(const char* )"LED_Task",/* 任务名字 */
							(uint16_t )512, /* 任务栈的深度,实际栈空间的大小为512*4个字节 */
							(void* )NULL, /* 任务入口函数参数 */
							(UBaseType_t )2, /* 任务的优先级 */
							(TaskHandle_t* )&LED_Task_Handle);/* 任务控制块指针 */
if (pdPASS == xReturn)
	printf("创建 LED_Task 任务成功!\r\n");

vTaskDelete(AppTaskCreate_Handle); //删除 AppTaskCreate 任务

taskEXIT_CRITICAL(); //退出临界区
}

4、任务的删除vTaskDelete(xHandle Taskx)

需要使用到任务创建时的任务句柄。即这个函数需要传递的参数是任务句柄

对于静态创建任务函数来说它的返回值为其任务句柄;而动态创建任务函数是吧定义好的任务句柄作为实参的,也可以为空即NULL。

当这个函数传入的参数为NULL时表示删除自身任务。

5、需要注意的几个点

(1)任务创建成功后对任务的各种操作都是通过任务句柄来实现的

(2)可以使用同一个函数创建两个任务(这时候因为两个函数的栈不一样,所以他们互不影响)

在这里插入图片描述

6、动态创建任务函数解析

(1)创建任务时的入口函数在定义中的形参可以是 void *类型,表示的是可以传递任何类型的参数

(2)任务函数里面的局部变量是存放在对应任务的栈空间里面的

(3)如何大概确定栈的大小:栈的大小取决于局部变量的大小和调用深度(即任务里面的调用函数的关系)传递进来的栈的深度为N,但实际上这个栈具有4N字节空间

(4)栈是从哪里分配出来的:动态创建时每个任务的栈是从一个预先分配好的巨大的数据(堆)中分配的,这个数组的大小可以用户自己设置,具体如下图

(5)使用动态创建任务时,第一个参数为任务函数入口,即任务需要执行函数的地址,当任务执行的时候即让PC寄存器的值等于这个函数地址;
在这里插入图片描述

(6)这个函数为对应若任务分配了TCB结构体、栈,并在栈里写入了函数地址、参数

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

八、任务的创建与删除 的相关文章

  • C++STL剖析(八)—— unordered_set和unordered_multiset的概念和使用

    文章目录 前言1 unordered set的介绍和使用 x1f351 unordered set的构造 x1f351 unordered set的使用 x1f345 insert x1f345 find x1f345 erase x1f3
  • C++STL剖析(九)—— unordered_map和unordered_multimap的概念和使用

    文章目录 1 unordered map的介绍和使用 x1f351 unordered map的构造 x1f351 unordered map的使用 x1f345 insert x1f345 operator x1f345 find x1f
  • C++STL剖析(十)—— 位图(bitset)

    文章目录 1 位图的介绍2 位图的概念3 位图的实现 x1f351 构造函数 x1f351 设置指定位 x1f351 清除指定位 x1f351 获取指定位的状态 x1f351 打印函数 4 总结 1 位图的介绍 在介绍位图之前先来看一道面试
  • C/C++数据结构(十二)—— 红黑树

    文章目录 1 红黑树的概念2 红黑树的性质3 红黑树节点的定义4 红黑树的旋转5 红黑树的插入 x1f351 情况一 x1f351 情况二 x1f351 情况三 x1f345 叔叔结点存在且为红色 x1f345 叔叔结点存在且为黑色 x1f
  • 机器学习数学基础

    文章目录 一 学习任务二 学习内容1 梯度下降法的一般求解步骤2 梯度下降法手工求解极值2 1 计算过程 3 Excel中利用梯度下降求解近似根4 线性回归问题求解4 1 最小二乘法4 2 梯度下降法 三 参考资料 一 学习任务 解释微分
  • 一篇文章吃透算法时间复杂度

    文章目录 前言1 什么是好的算法2 算法的效率度量3 时间复杂度4 大 O 时间复杂度表示法5 算法时间复杂度计算规则 x1f351 规则 1 xff1a 只关注循环中的代码段 x1f351 规则 2 xff1a 加法规则 x1f351 规
  • 2023 年最佳 C++ IDE

    文章目录 前言1 Visual Studio2 Code Blocks3 CLion4 Eclipse CDT xff08 C C 43 43 开发工具 xff09 5 CodeLite6 Apache NetBeans7 Qt Creat
  • 掌握顺序表,成为数据结构和算法的高手

    文章目录 1 线性结构与线性表2 线性表的顺序存储3 顺序表的基础操作 x1f351 顺序表接口总览 x1f351 初始化顺序表 x1f351 销毁链表 x1f351 插入操作 x1f351 删除操作 x1f351 获取元素操作 x1f34
  • 数据结构中常见的哈希表,到底是什么?

    文章目录 1 哈希概念 x1f351 举例说明 2 哈希冲突3 哈希函数 x1f351 常见哈希函数 4 哈希冲突解决 x1f351 闭散列 xff08 开放定址法 xff09 x1f345 线性探测 x1f345 二次探测 x1f351
  • 探索数据结构之精髓:单链表解密

    文章目录 1 前言2 单链表的特点3 单链表的基础操作 x1f351 接口总览 x1f351 初始化操作 x1f351 插入操作 x1f345 优化操作 x1f351 删除操作 x1f345 优化操作 x1f351 获取元素 x1f345
  • 引用与指针:在C++中如何做出正确的选择?

    文章目录 前言1 引用入门2 引用作为函数传参3 引用作为函数返回值4 引用和指针5 其他区别 前言 引用是 C 43 43 的新增内容 xff0c 在实际开发中会经常使用 xff0c 它就如同C语言的指针一样重要 xff0c 但它比指针更
  • C++引用进阶篇:让你的程序更加高效、安全、简洁

    文章目录 前言1 引用和临时数据 x1f351 什么样的临时数据会放到寄存器中 x1f351 关于常量表达式 x1f351 引用也不能指代临时数据 x1f351 引用作为函数参数 2 为const引用创建临时变量3 const引用与转换类型
  • 二叉树基础概念详解

    文章目录 前言1 树的基本概念2 二叉树的基本概念3 特殊二叉树 x1f351 满二叉树 x1f351 完全二叉树 x1f351 斜树 4 二叉树的性质 x1f351 性质一 x1f351 性质二 x1f351 性质三 x1f351 性质四
  • 链队列知识总结及代码实现

    目录 链队的存储方式 链队的优点 链队功能函数 代码实现 链队的存储方式 可以通过 单链表 的方式来实现 xff0c 使用链式队的优点在于它能够克服用数组实现的顺序队空间利用率不高的特点 xff0c 但是需要为每个队元素分配额外的指针空间用
  • 【C语言】全面解析结构体,结构体知识点整理

    文章目录 结构体的概念结构体类型的声明结构体变量的创建typedef关键字结构体的嵌套结构体变量的初始化结构体成员的访问结构体的传参总结 结构体的概念 结构体是由一系列具有相同类型或不同类型的数据构成的数据集合 组成结构型数据的每个数据称为
  • 逻辑回归案例 练习

    文章目录 一 学习任务二 学习内容1 常用评价指标2 实验分析 三 参考资料 一 学习任务 学习理解逻辑回归的基本概念 xff0c 练习python代码的实现 xff0c 在notebook中写入自己的理解注释 准确理解机器学习算法的常用评
  • APM飞控学习笔记——自动模式下一分钟自动降落

    提示 xff1a 文章写完后 xff0c 目录可以自动生成 xff0c 如何生成可参考右边的帮助文档 文章目录 前言一 自动模式简介二 添加自动降落功能 1 飞控主循环调用逻辑2 功能添加总结 前言 APM是一款功能齐全的开源多轴飞行器无人
  • Linux基础入门之常用命令

    1 命令的基本格式 1 1 命令的提示符 root 64 localhost xff1a 这是提示符的分隔符号 xff0c 没有特殊含义 root xff1a 显示的是当前的登录用户 xff0c 目前使用的是root用户登录 64 xff1
  • windows10安装python详细过程

    1 下载与安装Python 首先访问网址 https www python org xff0c 进入Downloads 页面 xff0c 即可下载Python 如下图 这里直接下载的是最新版的Python 如果需要下载其他版本的Python

随机推荐

  • 深度学习笔记(二)

    计算机视觉 xff1a 人类肉眼识别的错误率大概在5 到2016年的时候 xff0c 计算机视觉中 xff0c 用深度学习网络达到的错误率已经远低于人类 卷积神经网络 xff08 CNN xff09 1 应用领域 神经网络和卷积神经网络都是
  • YOLOv4从配置环境到跑通代码的小白教程

    一直以来都只是看论文和网上的一些纯文字的讲解 xff0c 但从来没有实操过 xff0c 非常想自己跑一下代码 xff0c 看一下算法的整个实现过程 xff0c 于是就有了这次尝试 系统环境介绍 windows 10 NVIDIA GeFor
  • YOLO系列算法详解(一)

    一 深度学习经典检测方法 1 检测任务中阶段的意义 对于单阶段 one stage 检测来说 xff0c 输入一张图像 xff0c 经过一个卷积神经网络 xff0c 输出一个边界框 xff0c 只需要得到框的 xff08 x1 y1 xff
  • 简单的Facenet_Pytorch人脸识别教程(windows+cpu)

    本文使用的编译器是Pycharm xff0c 具体的安装教程可参考 xff1a Pycharm安装参考链接 一 新建项目 首先打开Pycharm xff0c 点击 new project 进行新建 xff0c 选择项目的保存位置 xff0c
  • 调频连续波(FMCW)原理

    FMCW xff08 Frequency Modulated Continuous Wave xff09 即调频的连续信号 在许多方面得到应用 xff0c 比如生物雷达 xff0c 车载雷达 xff0c 无人机雷达等等方面都有FMCW波的应
  • TI AWR1843+DAC1000EVM+mmWave Studio实现数据采集

    参考文章 xff1a DCA1000EVM使用指南 嵌入式处理 技术文章 E2E 设计支持 整个实验主要是按照上面文章中的步骤进行操作 xff0c 虽然文章中是以IWR1642BOOST为例 xff0c 但是所有的操作步骤基本完全适用于AW
  • 安装Pytorch时出现ERROR: Could not find a version that satisfies the requirement...的解决方法

    一 问题描述 当我们创建了一个虚拟环境 xff0c 在环境中使用pip命令安装Pytorch时经常会出现以下错误 xff1a 二 解决方法 下面罗列几种有用的解决方法 xff1a 1 切换网络 出现这种问题很可能是因为网络太卡导致无法从该路
  • 使用Rviz完成摄像头(camera)的视频采集

    文章目录 一 准备摄像头二 使用Rviz三 Rviz显示摄像头 一 准备摄像头 1 找到虚拟机设置 xff0c 将USB设置为3 1 2 连接摄像头 3 连接成功如下 4 检查能否使用 使用cheese命令 二 使用Rviz 1 启动Rvi
  • SAM-Segment Anything Model进行单张图片的检测记录

    一 代码和模型下载 下载链接 GitHub facebookresearch segment anything 将代码下载并解压到一个没有中文的路径下 页面往下滑找到需要下载的模型 nbsp 这里提供了三个模型 vit b的大小是358m
  • Segment Anything(SAM)全图分割做mask

    项目的源码和模型下载以及环境配置等可参考我的上一篇文章 xff0c 这里不再赘述 文章链接 xff1a https blog csdn net m0 63604019 article details 130221434 在项目中创建一个名为
  • labelme的使用学习

    windows下图像标注软件labelme安装及使用教程 xff1a https www rstk cn news 12836 html action 61 onClick 问题 xff1a 如何将labelme标注产生的json文件中的某
  • Unet做分割的详细步骤

    参考文章 xff1a https blog csdn net ECHOSON article details 122914826 我是参考上面这个文章来做的 xff0c 但是在做实验的过程中还是出现了很多问题 xff0c 所以这里还是自己写
  • Java语法之多态

    上次给大家分享了Java的继承 xff0c 今天小编给大家分享面向对象三大特性的第三大特性 xff0c 也就是多态 xff0c fighting 目录 x1f388 一 多态 x1f388 1 1多态的概念 x1f388 1 2多态的实现条
  • 实现调度器

    实现调度器 调度器是操作系统的核心 xff0c 其主要功能就是实现任务的切换 xff0c 即从就绪列表里面找到优先级最高的任务 xff0c 然后去执行该任务 1 启动调度器 xff08 1 xff09 void vTaskStartSche
  • 任务相关知识

    任务管理 从系统的角度来看 xff0c 任务是竞争系统资源的最小运行单元 在任何时刻 xff0c 只有一个任务得到运行 xff0c 每个任务都在自己的环境中运行 xff0c 而这个运行的任务由FreeRTOS的调度器决定 FreeRTOS
  • 串口打印中文乱码及注释乱码问题

    1 使用keil5代码注释出现中文乱码问题 在使用keil5中出现如下问题 xff1a 这时候的解决方法是在keil5顶头工具栏上进入 xff1a Edit Configuration xff0c 如下然后进行选择GB2312编码方式 xf
  • keil5中安装Arm Compiler 5.06问题

    keil5 5 7版本中安装Arm Compiler 5 06问题 在最新的keil5 7版本中不再默认安装Arm Compiler 5 06编译器 xff0c 所以此版本需要自己独立下载并进行安装 具体步骤如下 xff1a 1 官网下载A
  • 五、FreeRTOS中任务控制块(TCB)、任务句柄和内核对象句柄

    文章目录 1 什么是任务控制块 xff1f 2 任务控制块的内容3 什么是任务句柄 xff1f 4 什么是内核对象句柄 xff1f 1 什么是任务控制块 xff1f 任务控制块实际上就是一个结构体 在FreeRTOS中 xff0c 系统为了
  • 凸优化基础知识

    文章目录 一 学习任务二 学习内容1 计算几何1 1 计算几何 的定义1 2 直线表达 2 凸集2 1 定义2 2 平面表达2 3 超平面表达 3 凸函数3 1 定义3 2 Hessian Matrix 矩阵3 3 判别 4 凸规划4 1
  • 八、任务的创建与删除

    文章目录 1 任务的三要素 xff1a 主体函数 任务栈 任务控制块 2 与任务相关的部分API函数 xff08 1 xff09 xTaskCreate xff08 2 xff09 void vTaskDelete TaskHandle t