FreeRTOS(任务管理的创建、删除、挂起、恢复)

目录

一、任务的基本概念

二、任务状态的概念

1、Running—运行态:

2、Ready—就绪态

3、Blocked—阻塞态

4、Suspended—挂起态

三、任务状态的切换

 四、系统启动

1、vTaskStartScheduler()函数

1.1 作用

1.2 启动函数介绍

 2、空闲任务

2.1 空闲任务的作用

五、任务创建

5.1 创建任务的方式

5.2 动态创建任务函数详解

5.3 使用举例

六、任务删除

6.1 删除任务函数详解

6.2 使用举例

七、任务挂起

7.1 挂起任务函数详解

7.2 使用举例

八、任务恢复(普通方式与中断方式)

8.1 普通方式恢复任务函数详解

8.2 中断方式恢复任务函数详解

九、任务管理编程

9. 1 cube配置

 9.2 手动创建任务

9.3 手动删除、挂起任务

9.4 手动创建、恢复任务

资料来源于硬件家园:FreeRTOS实时操作系统第四讲 - 任务管理(创建,删除,挂起,恢复) (qq.com)

一、任务的基本概念

1、从系统的角度看,任务是竞争系统资源的最小运行单元。

2、FreeRTOS是一个支持多任务的操作系统,在FreeRTOS中,任务可以使用或等待CPU、使用内存空间等系统资源,并独立于其他任务运行。

3、每个任务在自己的环境中运行,在任何时刻,只有一个任务得到运行,FreeRTOS调度器决定运行哪个任务。调度器会不断的启动、停止每一个任务,宏观上看,所有的任务都在同时进行。

4、在FreeRTOS中,每个任务都有自己的栈空间(一段连续的内存),用于保存任务运行环境。任务越多,需要的栈空间就越大,而一个系统能运行多少个任务,取决于系统可用的内存。

5、任务通常会运行在一个死循环中,不会退出,如果不需要某个任务,可以调用FreeRTOS中的删除任务API函数将任务删除,释放系统资源。

二、任务状态的概念

FreeRTOS系统中的任务有四种状态:

1、Running—运行态:

当任务处于实际运行时被称之为运行态,即 CPU 的使用权被这个任务占用。

2、Ready—就绪态

处于就绪态的任务是指那些能够运行(没有被阻塞和挂起),但是当前没有运行的任务,因为同优先级或更高优先级的任务正在运行。

3、Blocked—阻塞态

由于等待信号量,消息队列,事件标志组等而处于的状态被称之为阻塞态,另外任务调用延迟函数也会处于阻塞态。

4、Suspended—挂起态

类似阻塞态,通过调用函数 vTaskSuspend()对指定任务进行挂起,挂起后这个任务将不被执行,只有调用函数 xTaskResume()才可以将这个任务从挂起态恢复。

三、任务状态的切换

图片

 四、系统启动

1、vTaskStartScheduler()函数

/*Start scheduler */
osKernelStart();
osStatus osKernelStart (void)l{
vTaskStartScheduler();
return osOK;
}

1.1 作用

启动 FreeRTOS调度

1.2 启动函数介绍

函数原型:void vTaskStartScheduler( void );

函数描述:函数 vTaskStartScheduler 用于启动 FreeRTOS 调度器,即启动 FreeRTOS 的多任务执行。

使用这个函数要注意以下几个问题:

①空闲任务和可选的定时器任务是在调用这个函数后自动创建的。

②正常情况下这个函数是不会返回的。如果有返回,极有可能是用于定时器任务或者空闲任务的内存空间不足造成创建失败,此时需要加大FreeRTOS可管理的内存空间。

图片

 2、空闲任务

空闲任务是FreeRTOS系统中没有其它任务运行时自动进入的系统任务,不需要用户创建,启用调度器时,调度器会自动创建空闲任务。

图片

2.1 空闲任务的作用

① 执行删除任务时,系统并不会立即释放任务的内存空间,只会将任务添加到结束列表中,真正的系统资源回收工作在空闲任务中完成。

②可以在空闲任务中实现低功耗功能。

五、任务创建

5.1 创建任务的方式

① 静态创建任务,xTaskCreateStatic(),需要自行定义任务栈空间与任务控制块,一般不采用,不作介绍。

②动态创建任务,xTaskCreate(),系统动态分配任务栈空间与任务控制块,应用采用此方式。

5.2 动态创建任务函数详解

函数原型:

图片

函数描述:函数 xTaskCreate 用于实现 FreeRTOS 操作系统的任务创建,并且还可以自定义任务栈的大小。

①第 一 个参数填创建任务的函数名

②第 二 个参数是任务名,这个参数主要用于调试的时候方便看是哪个任务

③第 三 个参数是任务栈大小,单位 word,也就是 4 字节

④ 第 四 个参数是创建的任务函数的形参

⑤第 五 个参数是定义任务优先级

⑥第 六 个参数是任务句柄,用于区分不同的任务

5.3 使用举例

图片

STM32cubeMX创建方法:

图片

方法详解:

① 首先利用宏定义定义任务参数结构体变量

图片

图片

#name:将name转化为字符串,等效于"name"

os_thread_def__name:将name以字符串方式拼接,等效于"os_thread_def_name"

① 调用动态创建函数创建任务,形参为上面的结构体地址

图片

图片

图片

六、任务删除

6.1 删除任务函数详解

函数原型:void vTaskDelete( TaskHandle_t xTask ); /* 任务句柄 */ 

函数描述:函数 vTaskDelete 用于实现 FreeRTOS 操作系统的任务删除。 

①第 1 个参数填要删除任务的句柄

使用这个函数要注意以下问题:

① 使用此函数需要在 FreeRTOSConfig.h 配置文件中配置如下宏定义为 1#define INCLUDE_vTaskDelete 1

②  如果用往此函数里面填的任务 ID 是 NULL,即数值 0 的话,那么删除的就是当前正在执行的任务,此任务被删除后,FreeRTOS 会切换到任务就绪列表里面下一个要执行的最高优先级任务。

③ 在 FreeRTOS 中,创建任务所需的内存需要在空闲任务中释放,如果用户在 FreeRTOS 中调用了这个函数的话,一定要让空闲任务有执行的机会,否则这块内存是无法释放的。另外,创建的这个任务在使用中申请了动态内存,这个内存不会因为此任务被删除而删除,这一点要注意,一定要在删除前将此内存释放。

6.2 使用举例

图片

七、任务挂起

7.1 挂起任务函数详解

函数原型:void vTaskSuspend( TaskHandle_t xTaskToSuspend); /* 任务句柄 */ 

函数描述:函数 vTaskSuspend 用于实现 FreeRTOS 操作系统的任务挂起。 

第 1 个参数填要挂起任务的句柄

 使用这个函数要注意以下问题:

① 使用此函数需要在 FreeRTOSConfig.h 配置文件中配置如下宏定义为 1#define INCLUDE_vTaskSuspend 1

如果用往此函数里面填的任务 ID 是 NULL,即数值 0 的话,那么挂起的就是当前正在执行的任务,此任务被挂起后,FreeRTOS 会切换到任务就绪列表里面下一个要执行的高优先级任务。

③ 多次调用此函数的话,只需调用一次 vTaskResume 即可将任务从挂起态恢复。

7.2 使用举例

图片

八、任务恢复(普通方式与中断方式)

8.1 普通方式恢复任务函数详解

函数原型:void vTaskResume( TaskHandle_t xTaskToResume); /* 任务句柄 */ 

函数描述:函数 vTaskResume 用于实现 FreeRTOS 操作系统的任务挂起

①第 1 个参数填要恢复任务的句柄

使用这个函数要注意以下问题:

① 使用此函数需要在 FreeRTOSConfig.h 配置文件中配置如下宏定义为 1#define INCLUDE_vTaskSuspend  1

② 多次调用函数 vTaskSuspend 的话,只需调用一次 vTaskResume 即可将任务从挂起态恢复。

此函数是用于任务代码中调用的,故不可以在中断服务程序中调用此函数,中断服务程序中使用的xTaskResumeFromISR(),以后缀 FromISR 结尾。

使用举例:

图片

8.2 中断方式恢复任务函数详解

函数原型:BaseType_t  vTaskResumeFromISR( TaskHandle_t xTaskToResume); /* 任务句柄 */ 

函数描述:函数 vTaskResumeFromISR 用于实现 FreeRTOS 操作系统的任务恢复。

①第 1 个参数填要恢复任务的句柄

使用这个函数要注意以下问题:

① 使用此函数需要在 FreeRTOSConfig.h 配置文件中配置如下宏定义为 1#define INCLUDE_xResumeFromISR 1

② 多次调用函数 vTaskSuspend 的话,只需调用一次 vTaskResumeFromISR 即可将任务从挂起态恢复。

③ 如果用户打算采用这个函数实现中断与任务的同步,要注意一种情况,如果此函数的调用优先于函数vTaskSuspend 被调用,那么此次同步会丢失,这种情况下建议使用信号量来实现同步。

④此函数是用于中断服务程序中调用的,故不可以在任务中使用此函数,任务中使用的是 vTaskResume。

使用举例:

图片

九、任务管理编程

9. 1 cube配置

修改FreeRTOS_Debug的配置

修改内存分配方式为动态分配

 9.2 手动创建任务

在freertos.c中进行定义

①定义句柄

/* USER CODE BEGIN Variables */
extern volatile uint32_t CPU_RunTime;
osThreadId KEY1Handle;
/* USER CODE END Variables */

②定义入口函数

/* USER CODE BEGIN FunctionPrototypes */
void KEY1_Task(void const * argument);
/* USER CODE END FunctionPrototypes */

③创建任务

  /* USER CODE BEGIN RTOS_THREADS */
  osThreadDef(KEY1, KEY1_Task, osPriorityIdle, 0, 128);
  KEY1Handle = osThreadCreate(osThread(KEY1), NULL);
  /* USER CODE END RTOS_THREADS */

 ④入口函数实现

/* USER CODE BEGIN Application */
void KEY1_Task(void const * argument)
{
  /* USER CODE BEGIN KEY1_Task */
  /* Infinite loop */
  for(;;)
  {
    osDelay(1);
  }
  /* USER CODE END KEY1_Task */
}
/* USER CODE END Application */

9.3 手动删除、挂起任务

void KEY0_Task(void const * argument)
{
  /* USER CODE BEGIN KEY0_Task */
  /* Infinite loop */
  for(;;)
  {
	int KeyState=0;
	//按键检测
	if(HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin)==GPIO_PIN_RESET)
	{
		KeyState=1;
		while(HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin)==GPIO_PIN_RESET)
		{
			osDelay(20);//必须用阻塞延时
		}
	}
	if(KeyState)
	{
		vTaskSuspend(LED1Handle);//挂起LED1_Task
		HAL_UART_Transmit(&huart2,(uint8_t*)"KEY0 depress... \r\n", 20, HAL_MAX_DELAY);
		if(LED0Handle != NULL)
		{
			vTaskDelete(LED0Handle);
			LED0Handle=NULL;
			HAL_UART_Transmit(&huart2,(uint8_t*)"delete LED0_Task... \r\n", 20, HAL_MAX_DELAY);
		}
		else
		{
			HAL_UART_Transmit(&huart2,(uint8_t*)"None LED0_Task... \r\n", 20, HAL_MAX_DELAY);
		}
	}
    osDelay(1);
  }
  /* USER CODE END KEY0_Task */
}

9.4 手动创建、恢复任务

void KEY1_Task(void const * argument)
{
  /* USER CODE BEGIN KEY1_Task */
  /* Infinite loop */
  for(;;)
  {
	int KeyState=0;
	//按键检测
	if(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin)==GPIO_PIN_RESET)
	{
		KeyState=1;
		while(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin)==GPIO_PIN_RESET)
		{
			osDelay(20);//必须用阻塞延时
		}
	}
	if(KeyState)
	{
		vTaskResume(LED1Handle);//恢复LED1_Task
		HAL_UART_Transmit(&huart2,(uint8_t*)"KEY1 depress... \r\n", 20, HAL_MAX_DELAY);
		if(LED0Handle == NULL)
		{
			  osThreadDef(LED0, LED0_Task, osPriorityNormal, 0, 128);
			  LED0Handle = osThreadCreate(osThread(LED0), NULL);
			if(LED0Handle!=NULL)
			HAL_UART_Transmit(&huart2,(uint8_t*)"LED0_Task create success... \r\n", 20, HAL_MAX_DELAY);
		}
		else
		{
			HAL_UART_Transmit(&huart2,(uint8_t*)"exist LED0_Task ... \r\n", 20, HAL_MAX_DELAY);
		}
	}
    osDelay(1);
  }
  /* USER CODE END KEY1_Task */
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java密码学

密码学 1.1 密码学基本概念 密码在我们的生活中有着重要的作用,那么密码究竟来自何方,为何会产生呢? 密码学是网络安全、信息安全、区块链等产品的基础,常见的非对称加密、对称加密、散列函数等,都属于密码学范畴。…

ISC2023奇富科技与360智脑升级战略合作,加速完善金融行业大模型

北京时间8月9日,ISC2023第十一届互联网安全大会上,奇富科技宣布与360智脑达成在大模型方向与落地应用等多个层面的战略合作。通过奇富GPT与360智脑的算法、算力、数据融合,双方将协同优化奇富GPT,扩大其在已有业务中的应用场景&am…

【云原生】Docker中容器管理常用所有命令

1.docker 容器创建流程 2.容器运行本质 docker run [OPTIONS] IMAGE [COMMAND] [ARG...] 创建容器基本选项:--name:为容器命名 -i:交互式创建容器 -d:后台创建容器 -t:为容器分配伪终端 Docker 容器存在的意义就是为…

一种水文水利行业满管非满管双声道流量计安装调试

供电电源 用户应该特别注意:若是交流(AC220V)供电的主机插入直流电源,或者直流(DC24V)供电的主机接入AC220V电源,就会把流量计烧毁。 普通主机(包括固定式主机、盘装式主机&#x…

实现静态资源访问的几种方法

什么是静态资源? 静态资源是指在服务器端存储的不会变化的文件,如HTML、CSS、JavaScript、图片、音频、视频等文件。这些文件一般不包含动态内容,每次请求时返回的内容都是固定的。 为什么要使用静态资源? 提升网站性能&#xf…

Django实现音乐网站 ⑻

使用Python Django框架制作一个音乐网站, 本篇主要是后台对单曲原有功能的基础上进行部分功能实现和显示优化。 目录 新增编辑 歌手下拉显示修改 设置歌曲时长 安装eyed3库 获取mp3时长 歌曲时长字段修改 重写save方法 增加歌手单曲数量 查询歌手单曲数量 …

【Redis】Spring/SpringBoot 操作 Redis Java客户端

目录 操作 Redis Java客户端SpringBoot 操作Redis 步骤 操作 Redis Java客户端 1.Jedis 2.Lettuce(主流) <-Spring Data Redis SpringBoot 操作Redis 步骤 1.添加Redis 驱动依赖 2.设置Redis 连接信息 spring.redis.database0 spring.redis.port6379 spring.redis.host…

springboot工程使用阿里云OSS传输文件

在application.yml文件中引入对应的配置&#xff0c;一个是对应的节点&#xff0c;两个是密钥和账号&#xff0c;还有一个是对应文件的名称&#xff1b; 采用这样方式进行解耦&#xff0c;便于后期修改。 然后需要设置一个properties类&#xff0c;去读对应的配置信息 用到了…

TCP的四次挥手与TCP状态转换

文章目录 四次挥手场景步骤TCP状态转换 四次挥手场景 TCP客户端与服务器断开连接的时候&#xff0c;在程序中使用close()函数&#xff0c;会使用TCP协议四次挥手。 客户端和服务端都可以主动发起。 因TCP连接时候是双向的&#xff0c;所以断开的时候也是双向的。 步骤 三次…

(九)人工智能应用--深度学习原理与实战--前馈神经网络实现MNST手写数字识别

目标: 识别手写体的数字,如图所示: 学习内容: 1、掌握MNIST数据集的加载和查看方法 2、熟练掌握Keras建立前馈神经网络的步骤【重点】 3、掌握模型的编译及拟合方法的使用,理解参数含义【重点】 4、掌握模型的评估方法 5、掌握模型的预测方法 6、掌握自定义图片的处理与预测 …

网络安全【黑客】面试题汇总

前言 一眨眼2023年已经过去一大半&#xff0c;不知道大家有没有找到心仪的工作。作为一个安全老鸟&#xff0c;工作这么多年&#xff0c;面试过很多人也出过很多面试题目&#xff0c;也在网上收集了各类关于渗透面试题目&#xff0c;里面有我对一些问题的见解&#xff0c;希望…

信创麒麟操作系统卸载docker,并分别用在线、yum、rpm三种方式安装信创的docker

备注&#xff1a;操作前建议对机器打快照备份&#xff0c;或者备份好数据&#xff0c;如未使用&#xff0c;第一次部署的情况可直接操作 一、卸载DataEase自带的docker # 停止服务 service dataease stop# 删除 docker 可执行文件 rm -f /usr/bin/containerd-shim-runc-v2 r…

04-5_Qt 5.9 C++开发指南_QComboBox和QPlainTextEdit

文章目录 1. 实例功能概述2. 源码2.1 可视化UI设计2.2 widget.h2.3 widget.cpp 1. 实例功能概述 QComboBox 是下拉列表框组件类&#xff0c;它提供一个下拉列表供用户选择&#xff0c;也可以直接当作一个QLineEdit 用作输入。OComboBox 除了显示可见下拉列表外&#xff0c;每个…

【EI复现】梯级水光互补系统最大化可消纳电量期望短期优化调度模型(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

事件循环原理

事件循环 浏览器的进程模型 何为进程&#xff1f; 程序运行需要有它自己专属的内存空间&#xff0c;可以把这块内存空间简单的理解为进程 每个应用至少有一个进程&#xff0c;进程之间相互独立&#xff0c;即使要通信&#xff0c;也需要双方同意。 何为线程&#xff1f; 有…

【雕爷学编程】 MicroPython动手做(35)——体验小游戏3

知识点&#xff1a;什么是掌控板&#xff1f; 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;可作为物联网节点&#xff0c;实现物联网应用。同时掌控板上集成了OLED…

HDFS中的Trash垃圾桶回收机制

Trash垃圾桶回收机制 文件系统垃圾桶背景功能概述Trash Checkpoint Trash功能开启关闭HDFS集群修改core-site.xml删除文件到trash删除文件跳过从trash中恢复文件清空trash 文件系统垃圾桶背景 回收站&#xff08;垃圾桶&#xff09;是windows操作系统里的一个系统文件夹&#…

sql刷题

文章目录 section A1 各部门工资最高的员工&#xff08;难度&#xff1a;中等&#xff09;2 换座位&#xff08;难度&#xff1a;中等&#xff09;3 分数排名&#xff08;难度&#xff1a;中等&#xff09;4 连续出现的数字&#xff08;难度&#xff1a;中等&#xff09;5 树节…

谈谈对Spring MVC的理解

问题分析&#xff1a; SpringMVC 是一种基于 Java 语言开发&#xff0c;实现了 Web MVC 设计模式&#xff0c;请求驱动类型 的轻量级 Web 框架。 SpringMVC采用了 MVC 架构模式的思想&#xff0c;通过把 Model&#xff0c;View&#xff0c;Controller 分离&#xff0c;将 Web 层…

postgresql|数据库|角色(用户)管理工作---授权和去权以及usage和select两种权限的区别

前言&#xff1a; postgresql做为一个比较复杂的关系型的重型数据库&#xff0c;不管是安装部署&#xff0c;还是后期的运行维护&#xff0c;都还是有比较多的细节问题需要引起关注。 例如&#xff0c;用户权限的合理分配&#xff0c;那么&#xff0c;什么是权限的合理分配呢…