FreeRTOS临界段代码保护和任务调度器的挂起与恢复学习

FreeRTOS临界段代码保护和任务调度器的挂起与恢复学习

临界段代码保护

所谓临界段代码保护就是指必须完成运行,不能被打断的代码段。比如需要严格按照时序除初始化的外设:IIC、SPI,再或者因为系统自身需求和用户需求。
FreeRTOS 在进入临界段代码的时候需要关闭中断,当处理完临界段代码以后再打开中断。也就是临界区屏蔽了中断,系统调度靠中断,ISR也依靠中断。
在这里插入图片描述
具体调用如上述函数,
临界段代码保护具有以下特点:
1:成对使用
2:支持嵌套
3:要保持临界区代码内容短

任务调度器的挂起和恢复

挂起任务调度器,不需要关闭中断。具体函数为:
在这里插入图片描述

1:它仅仅是防止了任务之间的资源争夺,中断照样可以直接响应;
2:与临界区不一样的是,挂起任务调度器,未关闭中断;
3:挂起调度器的方式,适用于临界区位于任务与任务之间;既不用去延时中断,又可以做到临界区的安全
下面具体来看代码实现:

临界段代码保护内容理解

首先看临界区代码保护的。

void vPortEnterCritical( void )
{portDISABLE_INTERRUPTS();//关闭中断函数uxCriticalNesting++;/*在已经进入一个临界区的情况下再次进入另一个(或相同的)临界区的情况。这在多层函数调用中尤其常见,其中一个函数调用了另一个函数,两者都需要访问共享资源。在这种情况下,为了避免离开第一个临界区时意外地使整个系统对中断敏感,需要跟踪嵌套的深度。一旦嵌套深度回到零,系统才会重新启用中断。*//* This is not the interrupt safe version of the enter critical function so* assert() if it is being called from an interrupt context.  Only API* functions that end in "FromISR" can be used in an interrupt.  Only assert if* the critical nesting count is 1 to protect against recursive calls if the* assert function also uses a critical section. */if( uxCriticalNesting == 1 ){configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );}/*该段代码中的if语句检查是否是第一次进入临界区(uxCriticalNesting == 1),如果是,则执行一个断言(configASSERT)来确保当前不处于中断服务例程(ISR)中。这是因为中断服务例程中不应该调用非从ISR版本的API函数。断言检查的是portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK的结果是否为0,这个操作是用来检测当前是否有激活的中断:*/
}

下面我们来看下portDISABLE_INTERRUPTS()这个函数的具体内容;

/*-----------------------------------------------------------*/static portFORCE_INLINE void vPortRaiseBASEPRI( void ){uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;__asm{/* Set BASEPRI to the max syscall priority to effect a critical* section. */
/* *INDENT-OFF* */msr basepri, ulNewBASEPRIdsbisb
/* *INDENT-ON* */}}
/*-----------------------------------------------------------*/

basepri这个寄存器上一节中断管理提过这个寄存器,用来屏蔽中断的。在这里插入图片描述
这里就是把5到15的中断全部关闭了。因为FreeRTOS管理的中断范围就是5-15。

void vPortExitCritical( void )
{configASSERT( uxCriticalNesting );uxCriticalNesting--;if( uxCriticalNesting == 0 ){portENABLE_INTERRUPTS();}
}

下面我们来看下portENABLE_INTERRUPTS()这个函数的具体内容:

/*-----------------------------------------------------------*/static portFORCE_INLINE void vPortSetBASEPRI( uint32_t ulBASEPRI ){__asm{/* Barrier instructions are not used as this function is only used to* lower the BASEPRI value. */
/* *INDENT-OFF* */msr basepri, ulBASEPRI
/* *INDENT-ON* */}}
/*-----------------------------------------------------------*/

在这里插入图片描述
ulBASEPRI入口参数设置为0就是不关闭任何中断。
uxCriticalNesting这个变量就是用于嵌套调用临界区时候使用的变量。这里有这样的一个例子。

void doSomethingElse() {vPortEnterCritical(); // 进入临界区// 对共享资源进行一些操作vPortExitCritical(); // 退出临界区
}void doSomething() {vPortEnterCritical(); // 进入临界区// 对共享资源进行一些操作doSomethingElse(); // 调用另一个需要保护的函数// 可能还有更多操作vPortExitCritical(); // 退出临界区
}void mainFunction() {doSomething(); // 调用需要保护的函数
}

在这个例子中,当mainFunction调用doSomething时,我们首先进入一个临界区,此时uxCriticalNesting从0变为1。然后,在doSomething函数内部,我们调用了doSomethingElse,它也试图进入临界区。由于我们已经在一个临界区内,uxCriticalNesting此时会增加到2,而不是尝试禁用中断,因为它们已经被禁用了。当doSomethingElse完成其操作并调用vPortExitCritical时,它会减少uxCriticalNesting的值,将其从2变回1,但不会重新启用中断,因为我们仍然处于外部doSomething函数的临界区内。只有当doSomething也完成其操作,调用vPortExitCritical,并将uxCriticalNesting减少到0时,中断才会被重新启用。

任务调度器的挂起和恢复代码理解

void vTaskSuspendAll( void )
{/* A critical section is not required as the variable is of type* BaseType_t.  Please read Richard Barry's reply in the following link to a* post in the FreeRTOS support forum before reporting this as a bug! -* https://goo.gl/wu4acr *//* portSOFTWARE_BARRIER() is only implemented for emulated/simulated ports that* do not otherwise exhibit real time behaviour. */portSOFTWARE_BARRIER();/* The scheduler is suspended if uxSchedulerSuspended is non-zero.  An increment* is used to allow calls to vTaskSuspendAll() to nest. */++uxSchedulerSuspended;/* Enforces ordering for ports and optimised compilers that may otherwise place* the above increment elsewhere. */portMEMORY_BARRIER();
}

在这里插入图片描述
具体过程如上图所示。

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

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

相关文章

SMW200A罗德与施瓦茨SMW200A信号发生器

181/2461/8938产品概述: SMW200A是开发新型宽带通信系统,验证3G和4G基站,以及需数字调制信号的理想信号发生器。 SMW200A 矢量信号发生器 具有内部基带、高达2 GHz的I/Q调制带宽可以满足第4代和第5代标准(例如,5G、LTE-Advanced…

比例多路阀控制器US-DAT2-A

液压比例阀放大器是一种用于精确控制液压系统的技术,它通过电信号实现对液压阀的连续量控制。接收来自控制器的低功率电信号,然后将其放大并转换为高功率信号,这个高功率信号足以驱动比例阀的开启和关闭。这种技术允许进行非常精细的调节&…

想要实现自动化批量抓取淘宝商品数据店铺数据订单数据的看过来(淘宝开放平台API调用实例)

item_get 获得淘宝商品详情 获取API测试keyitem_get_pro 获得淘宝商品详情高级版item_review 获得淘宝商品评论item_fee 获得淘宝商品快递费用item_password 获得淘口令真实urlitem_list_updown 批量获得淘宝商品上下架时间seller_info 获得淘宝店铺详情item_search 按关键字…

过亿级别的用户数据如何检查用户名是否存在?

目录 引言用户名存在性检查的挑战用户规模庞大带来的性能挑战数据一致性与并发性问题防止恶意行为的挑战 常见的解决方案基于数据库的方案基于缓存的方案基于分布式系统的方案基于搜索引擎的方案 案例分析与实践经验分享社交媒体平台的用户名检查方案 引言 随着互联网的普及和数…

AI预测福彩3D第29弹【2024年4月7日预测--第7套算法重新开始计算第2次测试】

今天咱们继续进行进行第7套算法的测试,今天是第2次测试,昨天已经成功命中,其中7码大方案全部命中,四码小方案也命中。再接再厉,继续验证,废话不多说,直接上图上结果~ 2024年4月7日3D的七码预测结…

Python项目21:一个简单的记账系统(收入+支出+查询)

------------★Python练手项目源码★------------ Python项目源码20:银行管理系统(开户、查询、取款、存款、转账、锁定、解锁、退出) Python项目19:学员信息管理系统(简易版) Python项目18:…

Nacos集群监控搭建

Nacos集群监控搭建 结合prometheus和grafana监控Nacos Nacos 0.8.0版本完善了监控系统,支持通过暴露metrics数据接入第三方监控系统监控Nacos运行状态。 搭建Nacos集群暴露metrics数据 按照之前的集群搭建文档,搭建一个nacos集群。配置application.p…

分享多张自己绘制的 JavaScript 原型图

svg 图片自取 先来个最经典的 然后是对象与 Object 接着是函数与 Function。图中的 [[Prototype]] 指的就是原型对象 Function 和 Object 之间的关系也不能少。 这两个对象 Object 和 Function 是由 v8 自己创建的,理由是打印这两个对象时,终端输出 ƒ…

Django複習總結

①Django是框架。那麼什麼是框架: 框架很像是一個骨架,帶有很多默認器官的骨架。我們可以根據需要改寫、複寫這些器官。 從而實現自己所需要的功能。 ②Django是MVC模型\MVT模型: MVC模型:M:models模型層 V&#…

C语言 | Leetcode C语言题解之第12题整数转罗马数字

题目: 题解: const char* thousands[] {"", "M", "MM", "MMM"}; const char* hundreds[] {"", "C", "CC", "CCC", "CD", "D", "DC"…

ubuntu系统安装k8s1.28精简详细步骤

目录 一、规划二、环境准备2.1 配置apt仓库配置系统基本软件仓库配置k8s软件仓库安装常用软件包 2.2 修改静态ip、ntp时间同步、主机名、hosts文件、主机免密2.3 内核配置2.4 关闭防火墙、selinux、swap2.5 安装软件安装docker安装containerd安装k8s软件包 三、安装配置k8s3.1 …

WEBAPIS知识案例总结(续)

其他事件 页面加载事件 加载外部资源(如图片,外联css和js等)加载完毕时触发的事件有时候需要等页面资源全部处理完之后做一些事情老代码喜欢把script写在head中,这时候直接找dom元素找不到事件名:load监听页面所有资…