STM32CubeMX学习笔记23---FreeRTOS(任务的挂起与恢复)

1、硬件设置

本实验通过freertos创建两个任务来分别控制LED2和LED3的亮灭,需要用到的硬件资源

  • LED2和LED3指示灯
  • 串口

2、STM32CubeMX设置

根据上一章的步骤创建两个任务:STM32CubeMX学习笔记22---FreeRTOS(任务创建和删除)-CSDN博客

在 Include parameters 中把 vTaskSuspend 和 vTaskResumeFromISR 选择 Enabled 使能。

 生成代码。

3、程序编程

(1)、单个任务挂起

osThreadSuspend

挂起指定任务。被挂起的任务绝不会得到 CPU 的使用权,不管该任务具有什么优先级。

函数osThreadSuspend (osThreadId thread_id)
参数thread_id: 挂起指定任务的任务ID
返回值错误码(osStatus )

 要想使用该函数必须在 Include parameters 中把 vTaskSuspend 选择 Enabled 来使能。

 例:

/*
* 任务句柄是一个指针,用于指向一个任务,当任务创建好之后,它就具有了一个任务句柄
* 以后我们要想操作这个任务都需要通过这个任务句柄,如果是自身的任务操作自己,那么
* 这个句柄可以为 NULL。
*/
osThreadSuspend (LED2Handle);//挂起LED2
(2)、挂起全部任务

osThreadSuspendAll

函数osThreadSuspendAll (void)
参数
返回值错误码(osStatus )
(3)、单个任务恢复

osThreadResume

让挂起的任务重新进入就绪状态,恢复的任务会保留挂起前的状态信息,在恢复的时候根据挂起时的状态继续运行。如果被恢复任务在所有就绪态任务中,处于最高优先级列表的第一位,那么系统将进行任务上下文的切换。可用在中断服务程序中。

函数osThreadResume (osThreadId thread_id)
参数thread_id: 挂起指定任务的任务ID
返回值错误码(osStatus )

 要想在中断服务程序中使用该函数必须在 Include parameters 中把 vTaskResumeFromISR 选择 Enabled 来使能。

例:

osThreadResume (LED2Handle);//恢复LED2
(4)、全部任务恢复

osThreadResumeAll,将所有的任务都恢复。

函数osStatus osThreadResumeAll (void)
参数
返回值错误码

 osThreadResumeAll 函数的使用方法很简单,但是要注意,调用了多少次 osThreadSuspendAll() 函数就必须同样调用多少次 osThreadResumeAll() 函数。

void vDemoFunction( void )
{osThreadSuspendAll();/* 处理 xxx 代码 */osThreadSuspendAll();/* 处理 xxx 代码 */osThreadSuspendAll();/* 处理 xxx 代码 */osThreadResumeAll(); osThreadResumeAll(); osThreadResumeAll(); 
}
(5)、中断服务中恢复

使用 xTaskResumeFromISR()的时候有几个需要注意的地方:

  • 当函数的返回值为 pdTRUE 时:恢复运行的任务的优先级等于或高于正在运行的任务,表明在中断服务函数退出后必 须进行一次上下文切换 , 使用 portYIELD_FROM_ISR() 进行上下文切换。当函数的返回值为 pdFALSE 时:恢复运行的任务的优先级低于当前正在运行的任务,表明在中断服务函数退出后不需 要进行上下文切换。
  • xTaskResumeFromISR() 通常被认为是一个危险的函数,因为它的调用并非是固定的,中断可能随时来来临。所以 xTaskResumeFromISR()不能用于任务和中断间的同步,如果中断恰巧在任务被挂起之前到达,这就会导致一次中断丢失(任务还没有挂起,调用 xTaskResumeFromISR()函数是没有意义的,只能等下一次中断)。这种情况下,可以使用信号量或者任务通知来同步就可以避免这种情况。
void vAnExampleISR( void )
{BaseType_t xYieldRequired;/* 恢复被挂起的任务 */ xYieldRequired = xTaskResumeFromISR( xHandle ); if ( xYieldRequired == pdTRUE ) { /* 执行上下文切换, ISR 返回的时候将运行另外一个任务 */ portYIELD_FROM_ISR(xYieldRequired ); } 
}
(6)、获取任务状态

osThreadGetState,获取任务当前状态。

函数osThreadGetState(osThreadId thread_id)
参数thread_id: 任务ID
返回值以下值(osThreadState )
/* Thread state returned by osThreadGetState */
typedef enum {osThreadRunning   = 0x0,	      /*线程正在查询自身的状态,因此必须正在运行。*/osThreadReady     = 0x1 ,		  /* 正在查询的线程位于已读或挂起的就绪列表中。 */osThreadBlocked   = 0x2,		  /* 正在查询的线程处于阻止状态。 */osThreadSuspended = 0x3,	      /*被查询的线程处于“挂起”状态,或者处于“阻止”状态,超时时间无限长。 */osThreadDeleted   = 0x4,		  /* 正在查询的线程已被删除,但其TCB尚未释放。 */   osThreadError     = 0x7FFFFFFF
} osThreadState;
(7)、编写程序

在任务函数中编写程序,让LED1计数到10时挂起LED2,当计数到15时恢复LED2.

void LED1_Task1(void const * argument)
{/* USER CODE BEGIN LED1_Task1 *//* Infinite loop */int i=0;for(;;){HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_5);   //LED1状态每500s翻转一次printf("this LED1 run %d\r\n",i);if(i++==10){osThreadSuspend (LED2Handle);//挂起LED2printf("挂起LED2 \r\n");}if(i==15) {printf("恢复LED2 \r\n");osThreadResume (LED2Handle);//恢复LED2}osDelay(1001);}/* USER CODE END LED1_Task1 */
}/* USER CODE END Header_LED2_Task03 */
void LED2_Task03(void const * argument)
{/* USER CODE BEGIN LED2_Task03 *//* Infinite loop *//* 用于保存上次时间。调用后系统自动更新 */ static portTickType PreviousWakeTime; /* 设置延时时间,将时间转为节拍数 */ const portTickType TimeIncrement = pdMS_TO_TICKS(1000); /* 获取当前系统时间 */ PreviousWakeTime = osKernelSysTick();int i=0;for(;;){/* 调用绝对延时函数,任务时间间隔为 1000 个 tick */ osDelayUntil( &PreviousWakeTime,TimeIncrement ); HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_5);   //LED1状态每500s翻转一次printf("this LED2 run %d \r\n",i++);// osDelay(900);}/* USER CODE END LED2_Task03 */
}

4、下载验证

程序编译无误后下载到板子上,可以看到LED1计数到10时挂起LED2,当计数到15时恢复LED2。

注:在不同任务(任务优先级相同)中同时使用同一个中断会导致任务轮流使用该中断,如LED1和LED2都延时1000ms后同时使用printf,则会出现以下情况,即两个任务轮流使用printf,就导致了中间的遗漏了。(优先级不同则不会出现该情况)

5、参考文献

STM32CubeMX学习笔记(28)——FreeRTOS实时操作系统使用(任务管理)_stm32 rtos 任务固定时间运行-CSDN博客

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

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

相关文章

vue01

一、什么是vue.js(单页面应用程序) 用于构建用户界面的渐进式框架,采用自底向上增量开发的设计。核心理念:数据驱动视图,组件化开发前端三大主流框架:Vue.js Angular.js React.js 二、为什么学习流行框架…

1060:均值

【题目描述】 给出一组样本数据,包含n个浮点数,计算其均值,精确到小数点后4位。 【输入】 输入有两行,第一行包含一个整数n(n小于100),代表样本容量;第二行包含n个绝对值不超过10…

FPGA - SPI总线介绍以及通用接口模块设计

一,SPI总线 1,SPI总线概述 SPI,是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。串行外设接口总线(SPI),是一种高速的,全双工,同步的通信总线,并且在芯片的…

Debian时间和时区配置

1. 时区 1.1. 查看时区 timedatectl输出 Local time: Thu 2024-03-07 13:46:06 CSTUniversal time: Thu 2024-03-07 05:46:06 UTCRTC time: Thu 2024-03-07 05:46:06Time zone: Asia/Shanghai (CST, 0800) System clock synchronized: yesNTP service: activeRTC in local TZ…

面试十一、代理模式

代理模式是一种结构型设计模式,旨在为其他对象提供一种代理或替代方法,以控制对这些对象的访问。在代理模式中,代理对象充当了客户端和目标对象之间的中间人,客户端通过代理访问目标对象,而不直接访问目标对象。 代理模…

【C++】为什么vector的地址与首元素地址不同?

文章目录 一、问题发现:二、结果分析三、问题解析 一、问题发现: &vector和&vector[0]得到的两个地址居然不相同,对数组array取变量名地址和取首元素地址的结果是相同的。这是为啥呢? 使用下面代码进行验证:…

Oracle中全表扫描优化方法

在Oracle数据库中,全表扫描(Full Table Scan, FTS)是指查询执行时扫描表的所有数据块来获取结果集。虽然在某些场景下全表扫描可能是最优选择(例如:当需要访问大部分或全部数据、表很小或者索引访问成本高于全表扫描时…

MKdocs博客中文教程 - 已经整理到知乎专栏

MKdocs博客中文教程 - 知乎 Mkdocs-Wcowin中文主题 通过主题和目录以打开文章 基于Material for MkDocs美化简洁美观,功能多元化简单易上手,小白配置教程详细,清晰易懂

html5cssjs代码 035 课程表

html5&css&js代码 035 课程表 一、代码二、解释基本结构示例代码常用属性样式和装饰响应式表格辅助技术 一个具有亮蓝色背景的网页,其中包含一个样式化的表格用于展示一周课程安排。表格设计了交替行颜色、鼠标悬停效果以及亮色表头,并对单元格设…

C++基础之运算符重载续(十三)

一.函数调用运算符 我们知道,普通函数执行时,有一个特点就是无记忆性,一个普通函数执行完毕,它所在的函数栈空间就会被销毁,所以普通函数执行时的状态信息,是无法保存下来的,这就让它无法应用在…

python实现 linux 执行命令./test启动进程,进程运行中,输入参数s, 再输入参数1, 再输入参数exit, 获取进程运行结果重定向写入到文件

要在 Python 中实现执行 ./test 启动进程,并在进程运行中依次输入参数 s、1,最后输入参数 exit,并将进程的输出结果重定向写入到文件,你可以使用 subprocess 模块。以下是一个示例代码: import subprocess# 启动 test…

MoonBit 首场 MeetUp 活动火热报名中!更多活动惊喜等你来探索!

首场线下MeetUp来啦! 在数字化浪潮中,基础软件构筑了信息产业发展的根基,不仅是技术进步的支柱,也是推动经济增长的重要力量。基础软件的发展不仅关乎硬件的完善与应用软件的创新,更是连接过去与未来的桥梁。 尽管中国…

Docker容器化技术(docker-compose安装部署案例)

docker-compose编排工具 安装docker-compose [rootservice ~]# systemctl stop firewalld [rootservice ~]# setenforce 0 [rootservice ~]# systemctl start docker[rootservice ~]# wget https://github.com/docker/compose/releases/download/v2.5.0/docker-compose-linux-…

anaconda迁移深度学习虚拟环境 在云服务器上配置

1 anaconda 虚拟环境操作 1、 查看虚拟环境 conda info -e2、 创建新的虚拟环境 conda create -n deeplearning_all pip python3.63、 激活新建的虚拟环境 Conda activate deeplearning_all2 环境中相关库的版本即安装说明(这些库都是对应匹配的) …

Lenze伦茨8400变频器E84A L-force Drives 操作使用说明

Lenze伦茨8400变频器E84A L-force Drives 操作使用说明

跟selenium并肩的自动化神器 Playwright 的 Web 自动化测试解决方案

1. 主流框架的认识 总结: 由于Selenium在3.x和4.x两个版本的迭代中并没有发生多大的变化,因此Selenium一统天下的地位可能因新框架的出现而变得不那么稳固。后续的Cypress、TestCafe、Puppeteer被誉为后Selenium时代Web UI自动化的三驾马车。但是由于这三…

JavaEE 初阶篇-深入了解操作系统中的进程与 PCB

🔥博客主页: 【小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 1.0 关于计算机是如何进行工作的 “常识” 1.1 关于寄存器、缓存与内存是如何配合 CPU “工作” 2.0 操作系统概述 2.1 操作系统内核 2.2 进程 2.3 PCB 2.3.1 PCB 属性…

Centos7没有可用软件包 ifconfig问题解决

问题描述 在Centos7中查看ip没有ifconfig,使用yum安装ifconfig报错没有可用软件包 ifconfig问题解决 [rootlocalhost etc]# yum -y install ifconfig 已加载插件:fastestmirror base …

动手做简易版俄罗斯方块

导读:让我们了解如何处理形状的旋转、行的消除以及游戏结束条件等控制因素。 目录 准备工作 游戏设计概述 构建游戏窗口 游戏方块设计 游戏板面设计 游戏控制与逻辑 行消除和计分 判断游戏结束 界面美化和增强体验 看看游戏效果 准备工作 在开始编码之前…

火灾自动报警及消防联动控制系统主机的九个主要组成部分

关于火灾报警联动系统的主机组成,一般有两种不同的概括,下面分别讨论。 一: 火灾报警主机的组成部分较多,主要包括以下消防设备:主电源、联动电源、打印机、驱动器、直接控制板、总线控制板、消防广播、消防电话主机…