FreeRTOS资源管理

1.以前临界资源的保护方式

有使用过静态局部变量来保护临界资源,也有用队列,信号量,互斥量来保护临界资源。这些都是在多个任务会共同使用临界资源的情况下我们的保护方式。

问题提出:如果有个传感器在读取数据时有严格的时序,如果在读取数据中途被打断,就会读取错误,为了防止这一过程被打断我们会进行一些管理(关闭中断或调度器)。

1.2队列,信号量/互斥量,事件组,任务通知内部如何实现互斥的? 

核心就是谁跟我抢我就屏蔽谁,中断抢我就屏蔽中断,任务要抢我就进制调度器。什么意思呢?举两个例子。

1.2.1队列例子:

我们可以在中断里去写队列,也可以在任务里写队列,所以在写队列的函数里一定是去关闭中断的。我们要知道调度器切换任务也是基于中断的,我只关闭所有中断就可以达到防止任务和中断抢。因此写队列里一定是去关闭中断的。要注意的是关闭中断前先要记录当前中断的状态,再关闭中断,之后在根据记录的当前状态去恢复中断的状态。

写队列源码分析:

中断写队列

从图中可以看出在中断中写队列先记录当前中断状态,在返回中断状态的函数里执行了关闭中断的操作。在第二张图中是xQueueGenericSendFromISR()函数末尾执行的一个恢复中断的一个函数。 

任务写队列:

 

1.2.2事件组例子:

没有中断参与的我们只需要关闭调度器即可,比如事件组,事件组也有在中断中写事件组的函数为什么是关闭调度器呢?

在写事件组函数内部去写一个Timer队列,然后去守护任务会去唤醒定时器任务,在任务里去写事件值。虽然他是在中断中执行的,但是本质是去唤醒一个任务在任务中进行操作我们只需要停止调度器即可无需关中断。

​​

2.如何去关闭中断,如何去关闭调度器?

关闭中断:

关闭中断就是去操作某个寄存器。

关闭调度器:

设置一个变量,把这个变量++,根据这个变量是否为0,去判断是否要切换任务。

切换上下文, 加了之后这个变量就不等于0,就不进行切换。else才是执行任务切换。

2.1在任务中屏蔽中断

在任务中屏蔽中断的示例代码如下:

/* 在任务中,当前时刻中断是使能的
 * 执行这句代码后,屏蔽中断
 */
taskENTER_CRITICAL();

/* 访问临界资源 */

/* 重新使能中断 */
taskEXIT_CRITICAL();

在 taskENTER_CRITICA()/taskEXIT_CRITICAL() 之间:

  • 低优先级的中断被屏蔽了:优先级低于、等于 configMAX_SYSCALL_INTERRUPT_PRIORITY
  • 高优先级的中断可以产生:优先级高于 configMAX_SYSCALL_INTERRUPT_PRIORITY
    • 但是,这些中断ISR里,不允许使用FreeRTOS的API函数
  • 任务调度依赖于中断、依赖于API函数,所以:这两段代码之间,不会有任务调度产生

这套 taskENTER_CRITICA()/taskEXIT_CRITICAL() 宏,是可以递归使用的,它的内部会记录嵌套的深度,只有嵌套深度变为0时,调用 taskEXIT_CRITICAL() 才会重新使能中断。

使用 taskENTER_CRITICA()/taskEXIT_CRITICAL() 来访问临界资源是很粗鲁的方法:

  • 中断无法正常运行
  • 任务调度无法进行
  • 所以,之间的代码要尽可能快速地执行

2.2 在ISR中屏蔽中断

要使用含有"FROM_ISR"后缀的宏,示例代码如下:

void vAnInterruptServiceRoutine( void )
{
    /* 用来记录当前中断是否使能 */
    UBaseType_t uxSavedInterruptStatus;
    
    /* 在ISR中,当前时刻中断可能是使能的,也可能是禁止的
     * 所以要记录当前状态, 后面要恢复为原先的状态
     * 执行这句代码后,屏蔽中断
     */
    uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
    
    /* 访问临界资源 */

    /* 恢复中断状态 */
    taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
    /* 现在,当前ISR可以被更高优先级的中断打断了 */
}

在 taskENTER_CRITICA_FROM_ISR()/taskEXIT_CRITICAL_FROM_ISR() 之间:

  • 低优先级的中断被屏蔽了:优先级低于、等于 configMAX_SYSCALL_INTERRUPT_PRIORITY
  • 高优先级的中断可以产生:优先级高于 configMAX_SYSCALL_INTERRUPT_PRIORITY
    • 但是,这些中断ISR里,不允许使用FreeRTOS的API函数
  • 任务调度依赖于中断、依赖于API函数,所以:这两段代码之间,不会有任务调度产生

2.3 暂停调度器

如果有别的任务来跟你竞争临界资源,你可以把中断关掉:这当然可以禁止别的任务运行,但是这代价太大了。它会影响到中断的处理。

如果只是禁止别的任务来跟你竞争,不需要关中断,暂停调度器就可以了:在这期间,中断还是可以发生、处理。

使用这2个函数来暂停、恢复调度器:

/* 暂停调度器 */
void vTaskSuspendAll( void );

/* 恢复调度器
 * 返回值: pdTRUE表示在暂定期间有更高优先级的任务就绪了
 *        可以不理会这个返回值
 */
BaseType_t xTaskResumeAll( void );

示例代码如下:

vTaskSuspendScheduler();

/* 访问临界资源 */

xTaskResumeScheduler();

这套 vTaskSuspendScheduler()/xTaskResumeScheduler() 宏,是可以递归使用的,它的内部会记录嵌套的深度,只有嵌套深度变为0时,调用 taskEXIT_CRITICAL() 才会重新使能中断。

 3.总结

在使用临界资源时,需要严格的读取时序图时我们的管理方式为,在中断中我们就先关闭中断,在任务中我们就暂停调度器,除此之外互斥操作尽可能是使用信号量,互斥量来实现。

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

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

相关文章

使用idea编辑器回退git已经push的代码

直接上结果 选择想要回退的那次/多次提交历史, 右击, 选中 revert commit git自动产生一个Revert记录,然后我们会看到git自动将我第三次错误提交代码回退了,这个其实就相当于git帮我们手动回退了代码。 后续,只需要我们将本次改动push到远…

js之DOM 文档对象模型

当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model),简称 DOM。DOM 模型被结构化为对象树,又称DOM 树。 DOM 实际上是以面向对象方式描述的对象模型,它将文档建模为一个个对象&#xf…

ChatGPT的真实能力如何?七大NLP任务一探究竟!

文章链接:https://arxiv.org/pdf/2405.00704 ChatGPT已经改变了人工智能社区,一个活跃的研究方向是ChatGPT的性能评估。评估的一个关键挑战是ChatGPT仍然是闭源的,传统的基准数据集可能已被ChatGPT用作训练数据。在本文中: 调查了最近的研究…

Linux 内核的操作系统确实需要一直运行

在开始前我有一些资料,是我根据网友给的问题精心整理了一份「 Linux的资料从专业入门到高级教程」, 点个关注在评论区回复“888”之后私信回复“888”,全部无偿共享给大家!!! 但是这并不是调度的基础。每…

【1小时掌握速通深度学习面试6】图神经网络-下

目录 23. GraphSage 24.简述图神经网络的推理机制在其他领域中的应用 与传统NN的区别(GNN优点) 23. GraphSage GraphSage出现之前的图网络方法需要图中所有的顶点在训练embedding的时候都出现,这些的方法本质上是transductive&#xff0c…

字节上岸成功,整理一波测试开发岗的基础知识,含答案

本科非科班,去年秋招找非技术岗工作失败(无法通过群面)。谁又能想到今年春招形势严峻比去年秋招还严峻…. 太难了!!!! 2月末开始投简历,3月份开始面了tplink、字节、美团、广立微电…

自编码器网络

1.自编码器网络 自动编码器是一种无监督的数据维度压缩和数据特征表达方法。 无监督 在海量数据的场景下,使用无监督的学习方法比有监督的学习方法更省力。 维度上的压缩 自编码网络可以根据输入的数据,对其进行表征学习。输入数据转换到隐藏层co…

简单介绍IIC通信协议

文章目录 一,简单介绍二,IIC物理层三,IIC通信时序1.起始位与停止位2.IIC读写地址位信号3.IIC应答信号4.IIC数据位收发信号 四,总线速率五,主机发送数据流程六,主机接收数据流程七,IIC的时钟延展…

ComfyUI 基础教程(十四):ComfyUI中4种实现局部重绘方法

在ComfyUI中有多种方式可以实现局部重绘,简单的方式是使用VAE内补编码器进行局部重绘,也可以用Fooocus inpaint进行局部重绘,还可以用controlNet的inpaint模型进行局部重绘,以及使用Clip seg蒙版插件! 本篇介绍使用VAE內补编码器进行局部重绘的方法。 1、VAE内补编码器 局…

OpenHarmony实战开发-请求自绘制内容绘制帧率

对于基于XComponent进行Native开发的业务,可以请求独立的绘制帧率进行内容开发,如游戏、自绘制UI框架对接等场景。 接口说明 开发步骤 说明: 本范例是通过Drawing在Native侧实现图形的绘制,并将其呈现在NativeWindow上 1.定义Ark…

docker的commit命令使用制作镜像

docker run -it ubuntu 最基础的ubuntu启动后安装vim 的命令 apt-get update apt-get -y install vim docker commit -m"my_test_ubuntu" -a"za" 80977284a998 atljw/myubuntu:1.0 将本地镜像推送到阿里云 首先登录阿里云服务-控制台 记得一定要设定设…

免费领取!最新2024中国行政区划数据(Shp)!审图号:GS(2024)0650号

最新2024中国行政区划数据(Shp) 最近,在天地图官网对外公布了带审图号的行政区划矢量,包含省、市、县。官网提供GeoJSON格式下载。 数据介绍 分为省、市、县三级尺度。通过格式转换,形成shape格式的边界线数据和面数…

springboot版本升级,及解决springsecurity漏洞问题

背景: 项目中要解决 Spring Security RegexRequestMatcher 认证绕过漏洞(CVE-2022-22978) 漏洞问题,并且需要将项目的版本整体升级到boot版本2.1.7,升级改造过程非常的痛苦,一方面对整个框架的代码不是很熟…

关于视频号小店,常见问题解答,开店做店各方面详解

大家好,我是电商笨笨熊 视频号小店作为今年风口,一个新推出的项目,凭借着自身流量加用户群体的优势吸引了不少的电商玩家。 但对于很多玩家来说,视频号小店完全是一个新的项目、新的领域,因此也会存在很多的疑问&…

后缀字串排序

直接sort: #include <iostream> #include <cstring> #include <algorithm> #include <vector>using namespace std;int main() {string str;cin >> str;int len str.size();vector<string> strings;for(int i 0; i < len; i){strin…

云原生专栏丨基于K8s集群网络策略的应用访问控制技术

在当今云计算时代&#xff0c;Kubernetes已经成为容器编排的事实标准&#xff0c;它为容器化应用提供了强大的自动化部署、扩展和管理能力。在Kubernetes集群中&#xff0c;网络策略(Network Policy)作为对Pod间通信进行控制的关键功能&#xff0c;对保障应用安全和隔离性起到了…

[报错解决]SpringBoot子项目打jar包启动报 XXX--1.0-SNAPSHOT.jar中没有主清单属性

目录 报错信息解决原因原因分析解决方案 报错信息 解决 原因 在使用SpringBoot架构搭建父子工程时&#xff0c;使用IDEA可以正常启动&#xff0c;对子项目打成jar包后使用jar方式启动时&#xff0c;会报错xx.jar中没有主清单属性。 原因分析 原因主要是在使用jar方式启动时…

使用nvm切换nodejs版本

查看可以安装的版本&#xff1a; 使用nvm list显示已安装的nodejs版本&#xff1a; 选择一个版本下载&#xff1a; 切换对应的版本&#xff1a;

3D+仿真分析:高效实现海底石油管道系统设计

Bentley AutoPIPE 助力节省寻找更佳管道路线所需的时间和成本 评估管道完整性以提高石油产量 从墨西哥湾浅水区开采石油通常需要铺设新的海底管道&#xff0c;从而在高压和高温条件下高效、安全地输送原油。 Grupo EspecializadoenObras Marinas (GEOMSA) 是墨西哥湾管道—土体…

MaxKB宝塔Docker安装并配置域名访问

准备 Linux系统 bt面板 默认环境LNMP随便装 服务器环境配置最好是4G&#xff0c; 占用硬盘存储大概1G 对于一些海外AI产品的对接需要使用香港或者海外的服务器 安装 在宝塔面板中打开SSH或者你本地使用SSH工具去链接服务器 运行docker命令 前提是放开服务器的8080端口 doc…