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, ulNewBASEPRI
            dsb
            isb
/* *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();
}

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

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

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

相关文章

发型不满意试试开源AI换发型HairFastGAN;前OpenAI员工Karpathy1000纯C语言写完GPT-2

✨ 1: HairFastGAN 开源AI换发型 HairFastGAN 是一种先进的技术,专门设计用于在不同图片之间传输发型。这意味着如果你有一张人物的图片和另一张你喜欢的发型的图片,HairFastGAN 能够将你喜欢的那个发型复制到人物的头上,而且看起来非常自然…

强化学习MPC——(二)

本篇主要介绍马尔科夫决策(MDP)过程,在介绍MDP之前,还需要对MP,MRP过程进行分析。 什么是马尔科夫,说白了就是带遗忘性质,下一个状态S_t1仅与当前状态有关,而与之前的状态无关。 为…

深入浅出索引(上)

提到数据库索引,我想你并不陌生,在日常工作中会经常接触到。比如某一个 SQL 查询比较慢,分析完原因之后,你可能就会说“给某个字段加个索引吧”之类的解决方案。但到底什么是索引,索引又是如何工作的呢?今天…

NPW(监控片的)上---基础知识要点精讲

半导体的生产过程已经历经数十年的发展,其中主要有两个大的发展趋势,第一,晶圆尺寸越做越大,到目前已有超过70%的产能是12寸晶圆,不过18寸晶圆产业链推进缓慢;第二,电子器件的关键尺寸越做越小&…

【面试题】如何在级别用户中检查用户名是否存在?

前言 不知道大家有没有留意过,在使用一些app或者网站注册的时候,提示你用户名已经被占用了,比如我们熟知的《英雄联盟》有些人不知道取啥名字,干脆就叫“不知道取啥名”。 但是有这样困惑的可不止他一个,于是就出现了…

转圈游戏——快速幂

目录 题目 思路 代码 题目 思路 每个小朋友移动一次的位置为,移动 q 次的位置则为。那么题目要求移动 ,最后的位置为 。 但 的范围是,而总的移动次数是 。时间复杂度是在,因此是一定不能硬算的,肯定会超时。那么该…

苍穹外卖——员工管理,分类管理

内容 新增员工(重点)员工分页查询(重点)启用禁用员工账号编辑员工(重点)导入分类模块功能代码**功能实现:**员工管理、菜品分类管理。 员工管理效果:菜品分类管理效果: 1.新增员工 1.1 需求分析设计 1.1.1产品原型 一般在做需求分析时&a…

【VUE】Vue3+Element Plus动态间距处理

目录 1. 动态间距调整1.1 效果演示1.2 代码演示 2. 固定间距2.1 效果演示2.2 代码演示 其他情况 1. 动态间距调整 1.1 效果演示 并行效果 并列效果 1.2 代码演示 <template><div style"margin-bottom: 15px">direction:<el-radio v-model"d…

知识图谱的实际应用案例分析

知识图谱的实际应用案例分析 一、引言 知识图谱的重要性 在如今这个数据驱动的时代&#xff0c;数据已经成为了新的石油&#xff0c;而知识图谱则是我们提炼这种石油的精炼厂。知识图谱&#xff0c;一种将现实世界中的实体以及这些实体之间的复杂关系进行结构化表示的技术&am…

HarmonyOS开发实例:【状态管理】

状态管理 ArkUI开发框架提供了多维度的状态管理机制&#xff0c;和UI相关联的数据&#xff0c;不仅可以在组件内使用&#xff0c;还可以在不同组件层级间传递&#xff0c;比如父子组件之间&#xff0c;爷孙组件之间等&#xff0c;也可以是全局范围内的传递&#xff0c;还可以是…

C++数据结构与算法——贪心算法中等题

C第二阶段——数据结构和算法&#xff0c;之前学过一点点数据结构&#xff0c;当时是基于Python来学习的&#xff0c;现在基于C查漏补缺&#xff0c;尤其是树的部分。这一部分计划一个月&#xff0c;主要利用代码随想录来学习&#xff0c;刷题使用力扣网站&#xff0c;不定时更…

分享Fork/Join经典案例

shigen坚持更新文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 个人IP&#xff1a;shigen 在上一篇的文章java 多线程分治求和&#xff0c;太牛了的文章中&#xff0c;提到…

Docker使用— Docker部署安装Nginx

Nginx简介 Nginx 是一款高性能的 web 服务器、反向代理服务器以及电子邮件&#xff08;IMAP/POP3/SMTP&#xff09;代理服务器&#xff0c;由俄罗斯开发者伊戈尔塞索耶夫&#xff08;Igor Sysoev&#xff09;编写&#xff0c;并在2004年10月4日发布了首个公开版本0.1.0。Nginx…

因为使用ArrayList.removeAll(List list)导致的机器重启

背景 先说一下背景&#xff0c;博主所在的业务组有一个核心系统&#xff0c;需要同步两个不同数据源给过来的数据到redis中&#xff0c;但是每次同步之前需要过滤掉一部分数据&#xff0c;只存储剩下的数据。每次同步的数据与需要过滤掉的数据量级大概在0-100w的数据不等。 由…

鸿蒙HarmonyOS开发实例:【简单时钟】

简单时钟 介绍 本示例通过使用[ohos.display]接口以及Canvas组件来实现一个简单的时钟应用。 效果预览 主页 使用说明 1.界面通过setInterval实现周期性实时刷新时间&#xff0c;使用Canvas绘制时钟&#xff0c;指针旋转角度通过计算得出。 例如&#xff1a;"2 * M…

三角测量法恢复深度

参考&#xff1a;单目vo中的深度确定方法--三角测量_单目相机三角测量-CSDN博客 方法一&#xff1a;直接法 由于我们已经通过本质矩阵分解或者单应矩阵分解获得了R与t&#xff0c;此时想求的是两个特征点的深度 bool depthFromTriangulation(const SE3& T_search_ref,co…

电脑打开游戏的时候提示缺少.dll文件?照着这个来就行。

前言 小白曾经也是一个很喜欢玩游戏的人&#xff0c;但那只是曾经。那时候宿舍里一共6个人&#xff0c;都是比较喜欢玩游戏的小伙子。 话题好像偏了…… 有些小伙伴下载玩游戏之后&#xff0c;高高兴兴地想要开始玩。结果游戏根本没办法运行&#xff0c;可恶&#xff01;这该…

美国P6139B泰克无源探头

181/2461/8938产品概述&#xff1a; 500 MHz探头带宽探针尖端的大输入阻抗为10兆欧&#xff0c;8 pF补偿范围:8 pF至18 pF电缆长度:1.3米10倍衰减系数300 V CAT II输入电压用于探测小几何形状电路元件的紧凑探头小探针体增强了被测设备的可视性可更换探针头盒大型配件套装&…

《QT实用小工具·二十一》鼠标十字线

1、概述 源码放在文章末尾 该项目实现了界面绘制十字线并跟随鼠标移动的过程&#xff0c;下面是demo演示&#xff1a; 项目部分代码如下&#xff1a; #ifndef WIDGET_H #define WIDGET_H#include <QWidget>namespace Ui { class Widget; }class Widget : public QWidg…

Bioorganic Chemistry:中国药科大学王鹏课题组、陈俊青课题组设计的基于AIE机理的高荧光选择性鉴定Cys/HCy

文献来源&#xff1a;Highly selective fluorescent probe based on AIE for identifying cysteine/homocysteine - PubMed (nih.gov) 一、AIE机理在荧光探针设计方向的应用&#xff1a; 参考文献&#xff1a;几种代表性的AIE的发光特点和机制&#xff08;2020-10-11&#xff…