FreeRTOS基础(五):任务挂起与恢复

       今天我们将探讨FreeRTOS中的两个非常重要的函数:任务挂起和恢复函数。在实际的嵌入式系统开发中,我们常常需要在特定条件下暂停某些任务的执行,而在满足某些条件后再恢复这些任务的执行。这就像我们日常生活中的“暂停”和“继续”按钮。无论是为了节省资源,还是为了确保系统的稳定性,这两个操作都是至关重要的。通过理解和掌握任务的挂起与恢复,我们可以更灵活和高效地管理系统中的任务,确保各个任务能够协调运作,从而实现更稳定、更高效的系统表现。接下来,我们将深入了解如何使用这两个函数,以及它们在实际应用中的场景和注意事项。

目录

一、任务挂起与恢复函数

二、任务挂起函数

三、任务恢复函数(任务中恢复)

四、FreeRTOS 中断优先级概述

五、任务恢复函数(中断中恢复)

六、任务挂起与恢复API函数解析(选学)

6.1 任务挂起函数vTaskSuspend( )

6.2 (任务中调用)任务恢复函数vTaskResume( )

6.3(中断中调用)任务恢复函数xTaskResumeFromISR( )

七、任务挂起与恢复实验

八、任务挂起与任务恢复函数的使用场景

8.1 .临界区保护

8.2 资源管理

8.3 任务间同步


一、任务挂起与恢复函数

二、任务挂起函数

使用前先使能API函数

三、任务恢复函数(任务中恢复)

使用前先使能API函数

四、FreeRTOS 中断优先级概述

         FreeRTOS 的配置文件 FreeRTOSConfig.h 中有两个关键宏定义:

configMAX_SYSCALL_INTERRUPT_PRIORITY  //定义了可以使用 FreeRTOS API 的最高中断优先级。
configKERNEL_INTERRUPT_PRIORITY      //定义了 FreeRTOS 内核的优先级

       我们知道,Stm32一共有10个系统中断(内核中断),FreeRTOS便可以对这些系统中断进行管理;

       第一个宏其实代表的是FreeRTOS可以管理的中断的最高的优先级;在 ARM Cortex-M 微控制器上,优先级数值越低,优先级越高。configMAX_SYSCALL_INTERRUPT_PRIORITY 通常设置为一个中等优先级数值。例如,如果 FreeRTOS 管理的最高优先级为 5,则 configMAX_SYSCALL_INTERRUPT_PRIORITY 可以设置为 5。

解释:中断优先级与 FreeRTOS API

        如果在中断服务程序(ISR)中调用 FreeRTOS 的 API 函数,该 ISR 的优先级必须小于或者等于 configMAX_SYSCALL_INTERRUPT_PRIORITY。这意味着中断优先级数值必须大于等于 configMAX_SYSCALL_INTERRUPT_PRIORITY 的值。

         如果 ISR 的优先级高于 configMAX_SYSCALL_INTERRUPT_PRIORITY(即数值低于 configMAX_SYSCALL_INTERRUPT_PRIORITY),在该 ISR 中调用 FreeRTOS API 函数可能会导致不可预期的行为,例如任务切换不正确或系统崩溃。这是因为 FreeRTOS 的调度器和其他 API 函数不是为在高优先级中断上下文中执行而设计的,即该中断不受FreeRTOS的管理。

#define configMAX_SYSCALL_INTERRUPT_PRIORITY 5// 假设这是一个中断服务程序,优先级为6
void MyISR(void) {BaseType_t xHigherPriorityTaskWoken = pdFALSE;// 恢复任务,只有优先级为6或更低的中断才能调用该函数vTaskResumeFromISR(xTaskHandle);// 如果恢复的任务优先级较高,可以请求上下文切换portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

五、任务恢复函数(中断中恢复)

使用前先使能API函数

六、任务挂起与恢复API函数解析(选学)

6.1 任务挂起函数vTaskSuspend( )

6.2 (任务中调用)任务恢复函数vTaskResume( )

6.3(中断中调用)任务恢复函数xTaskResumeFromISR( )

七、任务挂起与恢复实验

创建任务及实现任务函数:

#include "stm32f4xx.h"                  // Device header
#include "stdio.h"
#include "FreeRTOS.h"
#include "task.h"
#include "dynamic.h"/**********************START_TASK任务配置******************************/
/***********包括任务堆栈大小、任务优先级、任务句柄、创建任务***********/#define        START_TASK_STACK_SIZE  128   //定义堆栈大小为128字(1字等于4字节)
#define        START_TASK_PRIO         1    //定义任务优先级,0-31根据任务需求
TaskHandle_t   start_task_handler;    //定义任务句柄(结构体指针)
void start_task(void* args);/**********************TASK1任务配置******************************/
/***********包括任务堆栈大小、任务优先级、任务句柄、创建任务***********/
#define  TASK1_STACK_SIZE  128            //定义堆栈大小为128字(1字等于4字节)
#define  TASK1_PRIO         2             //定义任务优先级,0-31根据任务需求
TaskHandle_t   task1_handler;           //定义任务句柄(结构体指针)
void task1(void* args);/**********************TASK2任务配置******************************/
/***********包括任务堆栈大小、任务优先级、任务句柄、创建任务***********/
#define  TASK2_STACK_SIZE  128            //定义堆栈大小为128字(1字等于4字节)
#define  TASK2_PRIO         3             //定义任务优先级,0-31根据任务需求
TaskHandle_t   task2_handler;           //定义任务句柄(结构体指针)
void task2(void* args);/**********************TASK3任务配置******************************/
/***********包括任务堆栈大小、任务优先级、任务句柄、创建任务***********/
#define  TASK3_STACK_SIZE  128            //定义堆栈大小为128字(1字等于4字节)
#define  TASK3_PRIO         4            //定义任务优先级,0-31根据任务需求
TaskHandle_t   task3_handler;           //定义任务句柄(结构体指针)
void task3(void* args);/*********开始任务用来创建其他三个任务,只创建一次,不能是死循环,同时创建完3个任务后删除任务1本身***********/
void start_task(void* args)
{taskENTER_CRITICAL();        /*进入临界区*/xTaskCreate( (TaskFunction_t)         task1,(char *)     "task1",  ( configSTACK_DEPTH_TYPE)   TASK1_STACK_SIZE,(void *)      NULL,(UBaseType_t) TASK1_PRIO ,(TaskHandle_t *)  &task1_handler );xTaskCreate( (TaskFunction_t)         task2,(char *)     "task2",  ( configSTACK_DEPTH_TYPE)   TASK2_STACK_SIZE,(void *)      NULL,(UBaseType_t) TASK2_PRIO ,(TaskHandle_t *)  &task2_handler );	xTaskCreate( (TaskFunction_t)         task3,(char *)     "task3",  ( configSTACK_DEPTH_TYPE)   TASK3_STACK_SIZE,(void *)      NULL,(UBaseType_t) TASK3_PRIO ,(TaskHandle_t *)  &task3_handler );	vTaskDelete(NULL);    //删除开始任务自身,传参NULLtaskEXIT_CRITICAL();   /*退出临界区*///临界区内不会进行任务的调度切换,出了临界区才会进行任务调度,抢占式						
}/********其余三个任务的任务函数,无返回值且是死循环***********//***任务1:实现LED0每500ms翻转一次*******/
void task1(void* args)
{uint32_t task1_num=0;while(1){printf("task1_num:%d\n",++task1_num);GPIO_ToggleBits(GPIOF,GPIO_Pin_9 );vTaskDelay(500);       //FreeRTOS自带的延时函数}}/***任务2:实现LED1每500ms翻转一次*******/
void task2(void* args)
{uint32_t task2_num=0;while(1){printf("task2_num:%d\n",++task2_num);GPIO_ToggleBits(GPIOF,GPIO_Pin_10 );vTaskDelay(500);       //FreeRTOS自带的延时函数}}/***任务3:判断按键KEY0,按下KEY0,任务1删除*******/
void task3(void* args)
{while(1){if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)==0)  //表示按键Key0按下{vTaskSuspend(task1_handler);                         //挂起任务1}	else if (GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)==0)		//表示按键Key1按下{vTaskResume(task1_handler);                           //恢复任务1}vTaskDelay(10); }}//FreeRTO入口例程函数,无参数,无返回值
void freertos_demo(void)
{xTaskCreate( (TaskFunction_t)     start_task,(char *)     "start_task",  ( configSTACK_DEPTH_TYPE)   START_TASK_STACK_SIZE,(void *)      NULL,(UBaseType_t) START_TASK_PRIO ,(TaskHandle_t *)  &start_task_handler );vTaskStartScheduler();  //开启任务调度器}

主函数调用入口函数,操作系统开始进行任务的切换和调度

#include "stm32f4xx.h"                  // Device header
#include "stdio.h"
#include "myled.h"
#include "mykey.h"
#include "myusart.h"#include "FreeRTOS.h"
#include "task.h"
#include "dynamic.h"int main(void)
{//硬件初始化My_UsartInit();LED_Init();KEY_Init();//调用入口函数freertos_demo();}

八、任务挂起与任务恢复函数的使用场景

8.1 .临界区保护

        在某些情况下,需要确保一段代码不被中断或其他任务打断。例如,在对共享资源进行操作时,可以使用任务挂起和恢复函数来实现临界区保护。

void vTaskSuspendAll( void )

可将所有任务挂起,实质是将任务调度器锁定。

// 共享资源操作示例
void critical_section(void) {// 挂起其他任务vTaskSuspendAll();// 临界区代码shared_resource++;// 恢复任务调度xTaskResumeAll();
}

8.2 资源管理

         在访问某些硬件资源(如SPI总线、I2C总线等)时,需要确保在使用资源期间不会被其他任务干扰。这时可以挂起其他可能访问该资源的任务,使用完毕后再恢复它们.

void access_resource_task(void *pvParameters) {// 挂起可能使用相同资源的任务vTaskSuspend(task_handle);// 操作硬件资源use_hardware_resource();// 恢复任务vTaskResume(task_handle);
}

8.3 任务间同步

       在某些场景下,可能需要一个任务等待另一个任务完成特定操作后再继续执行。可以通过挂起和恢复任务实现这种同步机制。

// 任务A
void taskA(void *pvParameters) {// 执行某些操作// 挂起任务A自己vTaskSuspend(NULL);// 当任务B完成操作后任务A将被恢复
}// 任务B
void taskB(void *pvParameters) {// 执行任务A需要等待的操作// 恢复任务AvTaskResume(task_handleA);
}

        需要注意的是,滥用任务挂起和恢复函数可能导致系统响应变慢或引入难以调试的错误。在实际应用中,应尽量通过其他FreeRTOS提供的同步机制(如信号量、消息队列等)来实现任务间的协调和同步。

 至此,任务挂起与恢复函数就已经讲解完毕!初次学习,循序渐进,一步步掌握即可!以上就是全部内容!请务必掌握,创作不易,欢迎大家点赞加关注评论,您的支持是我前进最大的动力!下期再见!

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

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

相关文章

【Kubernetes】Pod理论详解

一、Pod基础概念: Pod是kubernetes中最小的资源管理组件,Pod也是最小化运行容器化应用的资源对象。一个Pod代表着集群中运行的一个进程。kubernetes中其他大多数组件都是围绕着Pod来进行支撑和扩展Pod功能的,例如,用于管理Pod运行…

Unix、Linux 软件包管理快速入门对照

Linux(RHEL、Ubuntu)或者 Unix(macOS、FreeBSD)可以参看下表快速入门: 命令功能/系统Darwin (macOS)FreeBSDDebian/UbuntuRHEL(dnf yum)搜索和查找软件包brew searchpkg searchapt listyum list查看软件包…

生态系统服务功能之碳储量

大家好,这期开始新生态系统服务功能即碳储量的计算,这部分较简单,下面让我们开始吧!!! 碳储量的计算公式 生态系统通过从大气中释放和吸收二氧化碳等温室气体来调节地球气候,而森林、 草原和沼…

Stable Diffusion生成图片的参数查看与抹除方法

前几天分享了几张Stable Diffusion生成的艺术二维码,有同学反映不知道怎么查看图片的参数信息,还有的同学问怎么保护自己的图片生成参数不会泄露,这篇文章就来专门分享如何查看和抹除图片的参数。 查看图片的生成参数 1、打开Stable Diffus…

php反序列化入门

一,php面向对象。 1.面向对象: 以“对象”伪中心的编程思想,把要解决的问题分解成对象,简单理解为套用模版,注重结果。 2.面向过程: 以“整体事件”为中心的编程思想,把解决问题的步骤分析出…

就业班 第四阶段(docker) 2401--5.29 day3 Dockerfile+前后段项目若依ruoyi

通过Dockerfile创建镜像 Docker 提供了一种更便捷的方式&#xff0c;叫作 Dockerfile docker build命令用于根据给定的Dockerfile构建Docker镜像。docker build语法&#xff1a; # docker build [OPTIONS] <PATH | URL | ->1. 常用选项说明 --build-arg&#xff0c;设…

Windows安装Docker

启用虚拟化 打开 勾选Hyper-V 验证 下载Docker Docker官网 阿里云 安装Docker 傻瓜式安装 遇到问题&#xff1a; 打开命令窗口&#xff0c;执行命令&#xff1a; wsl --update升级完成之后点击Restart按钮即可 切换阿里镜像 https://fmkoym4e.mirror.aliyuncs.com

Firebase Local Emulator Suite详解

文章目录 Firebase Local Emulator Suite 组件安装和使用步骤1. 安装 Firebase CLI2. 初始化 Firebase 项目3. 配置模拟器4. 启动模拟器5. 配置应用程序使用本地模拟器 常见用途 Firebase Local Emulator Suite 是一组本地服务&#xff0c;可以模拟 Firebase 平台的在线服务&am…

每天写两道(五)合并两个有序链表、最长回文子串

21.合并两个有序链表 . - 力扣&#xff08;LeetCode&#xff09; 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4] (1)迭代法…

小白教你搭建测试环境(docker部署版)

如何使用docker创建多数据库端口&#xff08;云服务器版&#xff09; 背景&#xff1a; 需要搭建一个测试环境&#xff0c;同时还需要不同的端口映射mysql端口。那么我采用的docker拉取mysql镜像&#xff0c;通过宿主机和docker容器端口映射完成。 准备一台云服务器服务器安装…

如何跨渠道分析销售数据 - 6年软件销售经验小结

如何跨渠道分析销售数据 - 6年软件销售经验小结&#xff08;1&#xff09; 【前言】 在我过去6年销售工作生涯中&#xff0c;从第一年成为公司销冠后&#xff0c;我当时的确自满的一段时间&#xff0c;认为自己很了不起。但是第一年的销售业绩并没有拿到提成&#xff0c;最终…

初识C++ · 模拟实现list

目录 前言 1 push_back pop_back 2 迭代器类 2.1 ! 2.2 -- 2.3 * 3 Print_List 4 有关自定义类型 5 有关const迭代器 6 拷贝构造 赋值 析构 Insert erase 前言 有了string&#xff0c;vector的基础&#xff0c;我们模拟实现list还是比较容易的&#xff0c;这里同…

Pandas 使用 concat 数据合并你学会了吗?

1. 使用pd.concat()级联 pandas使用pd.concat函数&#xff0c;与np.concatenate函数类似 # 导包import numpy as npimport pandas as pd​# 为方便讲解&#xff0c;我们首先定义一个生成DataFrame的函数def make_df(indexs,columns): data [[str(j)str(i) for j in colum…

PWN-栈迁移

栈迁移 题目&#xff1a;BUUCTF在线评测 (buuoj.cn) 知识点&#xff1a;栈迁移 使用情况&#xff1a;题目中有栈溢出&#xff0c;但是 栈溢出的范围 有限&#xff0c;导致构造的ROP链不能完全写入到栈中&#xff0c;此时需要进行栈迁移&#xff0c;将栈迁移到能接受更多数据的…

go语言基于Gin集成后台管理系统开发定时任务管理cron/v3好用又好看

系统目前是支持两种定时类型&#xff0c;一种是函数类型&#xff0c;一种是接口类型&#xff0c;来支持多样的业务&#xff1b;时间周期可视化选择&#xff0c;方便设定执行周期。框架UI漂亮&#xff0c;添加管理定时任务设置简单&#xff0c;客户都可以做自己调整执行时间周期…

win10环境下nodejs安装过程

打开 https://nodejs.org/en/官网下载node.js 2.下载完成后的安装文件为node-v16.16.0-x64.msi&#xff0c;双击进行安装即可。 3.一直默认安装&#xff0c;记得可以更改安装路径 4.其他不用打勾&#xff0c;一直next&#xff0c;安装完成即可。 5.安装完成后&#xff0c;wi…

集成建筑5G商城为建筑行业开拓新方向

集成建筑5G商城为建筑行业开拓新方向 建筑业在我国有着悠久的发展历史&#xff0c;近年来&#xff0c;伴随着我国经济的快速增长、城镇化步伐加快&#xff0c;我国房地产、建筑业持续增长&#xff0c;建筑业显现出巨大的发展潜力。建筑行业近年来始终保持较高的增长速度。根据…

论文作图之高压缩比导出PDF

笔者使用Adobe Illustrator 2023创建可编辑pdf图&#xff0c;按照默认的导出设置保存pdf文件时&#xff0c;得到的图存储很大。为了解决存储过大且还保留一定编辑功能的问题&#xff0c;作者实践出了一种导出pdf的设置方法。 首先在AI中点击文件->存储为&#xff0c;点击保…

纯Java实现Google地图的KMZ和KML文件的解析

目录 前言 一、关于KMZ和KML 1、KMZ是什么 2、KML是什么 二、Java解析实例 1、POM.xml引用 2、KML 基类定义 3、空间对象的定义 4、Kml解析工具类 三、KML文件的解析 1、KML解析测试 2、KMZ解析测试 四、总结 前言 今天是六.一儿童节&#xff0c;在这里祝各位大朋友…

el-table超过宽度强制显示滚动条

使用css强制显示&#xff1a; .el-table .el-table__body-wrapper::-webkit-scrollbar {display: block; }