首页 > 编程语言 >Freertos应用与源码分析:临界区

Freertos应用与源码分析:临界区

时间:2024-10-11 14:49:58浏览次数:10  
标签:CRITICAL Task Freertos 中断 basepri void 临界 源码

目录

一、概述

二、应用

三、源码分析

1、进入临界区

2、退出临界区

3、中断临界区

(1)应用

(2)进入中断临界区

(3)退出中断临界区

四、注意事项

一、概述

        当一个任务在使用某个资源的过程中,即还没有完全结束对资源的访问时,便被切出运行态,使得资源处于非一致,不完整的状态。如果这个时候有另一个任务或者中断来访问这个资源,则会导致数据损坏或是其它相似的错误。如下

  • 任务 A 运行,并往 LCD 写字符串”Hello world”。
  • 任务 A 被任务 B 抢占,但此时字符串才输出到”Hello w”。
  • 任务 B 往 LCD 写”Abort, Retry, Fail?”,然后进入阻塞态。
  • 任务 A 从被抢占处继续执行,完成剩余的字符输出——“orld”。 
  • 现在 LCD 显示的是被破坏了的字符串”Hello wAbort, Retry, Fail?orld”。

        因为在程序运行时,是将语句拆分若干条指令,比如a++操作,执行读->加->写,CPU每一行一条指令,就会判断一下有没有中断或异常触发。
        如下,当任务A_Task调用add_Task时候,执行到“读”操作,此时被B_Task抢占执行,B_Task执行完读->加->写操作后,此时a=1,那么A_Task再次去执行的时候,执行完读->加->写后,那么a到底等于1还是等于2?此时就会出现问题。那么如何避免?其中一个方法,我们加入临界区。 

uint8_t a=0;
void add_Task(void)
{
        a++;
}
void A_Task(void *p)
{
    while(1)
    {
        add_Task();  
    }
}
void B_Task(void *p)
{
    while(1)
    {
        add_Task(); 
    }
}

二、应用

        相关函数

/*进入临界区*/
void taskENTER_CRITICAL( void );
/*退出临界区*/
void taskEXIT_CRITICAL( void );

        当A_Task执行调用add_Task函数,进入临界区保护后,a++就被保护起来了,可以理解为关中断。如果所使用的 FreeRTOS 移植使用了configMAX_SYSCALL_INTERRUPT_PRIORITY 内核配置常量,那么将会禁用优先级低于或等于configMAX_SYSCALL_INTERRUPT_PRIORITY宏定义设置的优先级的中断,并启用所有高于此优先级的中断。抢占式上下文切换仅在中断内发生, 在中断被禁用时不会发生。

uint8_t a=0;
void add_Task(void)
{
    //进入临界区
    taskENTER_CRITICAL();
    //临界资源
    a++;
    //退出临界区
    taskEXIT_CRITICAL();
}
void A_Task(void *p)
{
    while(1)
    {
        add_Task();  
    }
}
void B_Task(void *p)
{
    while(1)
    {
        add_Task(); 
    }
}

三、源码分析

1、进入临界区

/*进入临界区*/
void taskENTER_CRITICAL( void );

        经过层层调用,最后来到vPortEnterCritical函数。如下,portDISABLE_INTERRUPTS()函数作用表示将中断优先级设置为configMAX_SYSCALL_INTERRUPT_PRIORITY宏定义所设置的值(后续会讲)。uxCriticalNesting之所以执行++,是因为临界区可以嵌套使用。

void vPortEnterCritical( void )
{   
    /*关闭中断*/
    portDISABLE_INTERRUPTS();
    uxCriticalNesting++;
    /*可以理解为:设置中断优先级,大于可屏蔽中断优先级,这样就不会被抢占*/
    if( uxCriticalNesting == 1 )
    {
        configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
    }
}

        如下,portDISABLE_INTERRUPTS()经过调用后,来到了vPortRaiseBASEPRI函数。将basepri强制设置成configMAX_SYSCALL_INTERRUPT_PRIORITY参数。

        basepri寄存器的作用:禁止优先级低于某个特定等级的中断,只需要将所需的屏蔽优先级写入basepri寄存器即可。通俗一点讲,禁止优先级低于等于basepri的中断。

static portFORCE_INLINE void vPortRaiseBASEPRI( void )
{
    /*configMAX_SYSCALL_INTERRUPT_PRIORITY中断优先级*/
    uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;
    __asm
    {
        /*将ulNewBASEPRI写进basepri*/
        msr basepri, ulNewBASEPRI
        /*确保指令完全执行*/
        dsb
        isb

    }
}

        那么我们就可以理解,当我们定义了configMAX_SYSCALL_INTERRUPT_PRIORITY宏定义之后。进入临界区,就是将禁止优先级低于等于configMAX_SYSCALL_INTERRUPT_PRIORITY宏定义的中断触发。

2、退出临界区

/*退出临界区*/
void taskEXIT_CRITICAL( void );

        如下,经过层层调用,最后来到vPortExitCritical函数。portENABLE_INTERRUPTS()函数作用表示将basepri设置为0。因为临界区可以嵌套使用,执行uxCriticalNesting--,当xCriticalNesting等于0的时候表示完全退出临界区。

/*退出临界区*/
void vPortExitCritical( void )
{
    /*检查作用*/
    configASSERT( uxCriticalNesting );
    /*确保嵌套结束*/
    uxCriticalNesting--;
    /*退出中断,将中断优先级设置为0,这样相当于退出中断*/
    if( uxCriticalNesting == 0 )
    {
        /*将basepri置0*/
        portENABLE_INTERRUPTS();
    }
}

        如下,portENABLE_INTERRUPTS()经过调用后,来到了vPortSetBASEPRI函数。说明此时将要完全退出临界区,故将将basepri强制设置成0。

#define portENABLE_INTERRUPTS()                   vPortSetBASEPRI( 0 )
static portFORCE_INLINE void vPortSetBASEPRI( uint32_t ulBASEPRI )
{
    __asm
    {
        msr basepri, ulBASEPRI
    }
}

那么我们就可以理解,退出临界区就是将basepri设置为0即可。

3、中断临界区

(1)应用
UBaseType_t taskENTER_CRITICAL_FROM_ISR( void );
void taskEXIT_CRITICAL_FROM_ISR( UBaseType_t uxSavedInterruptStatus );

        中断临界区函数使用和临界区函数使用有一点区别,但是核心一样,都是将其basepri寄存器设置为configMAX_SYSCALL_INTERRUPT_PRIORITY宏定义数值。只不过在设置之前需要保存当前中断掩码。

//应用方法
void vDemoISR( void )
{	/*定义保存中断掩码变量*/
    UBaseType_t uxSavedInterruptStatus;
    /*保存返回值(中断掩码)*/
    uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
    //资源
    /*写入中断掩码,用于退出临界区*/
    taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
}
(2)进入中断临界区

        经过taskENTER_CRITICAL_FROM_ISR()的层层调用,来到了ulPortRaiseBASEPRI函数。先保存旧的中断掩码等级,随后在设置新的BASEPRI等级。

static portFORCE_INLINE uint32_t ulPortRaiseBASEPRI( void )
{
    /*设置新的ulNewBASEPRI等级,与之前步骤相同*/
    uint32_t ulReturn, ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;

    __asm
    {
        /*保存当前basepri等级*/
        mrs ulReturn, basepri
        /*设置新的basepri*/
        msr basepri, ulNewBASEPRI
        /*确保指令完全执行*/
        dsb
        isb
    }
    /*返回原始中断掩码*/
    return ulReturn;
}
(3)退出中断临界区

        经过taskEXIT_CRITICAL_FROM_ISR(参数)的层层调用,来到了vPortSetBASEPRI函数。ulBASEPRI传入的原始中断掩码参数

static portFORCE_INLINE void vPortSetBASEPRI( uint32_t ulBASEPRI )
{
    __asm
    {	/*将原始中断掩码写入basepri寄存器*/
        msr basepri, ulBASEPRI
    }
}

四、注意事项

1、临界区必须简短,因为长时间关闭中断会极大影响系统性能。

2、不得从临界区调用Freertos api函数。

3、中断服务程序(ISR)中想要使用临界区要使用专门的函数。

4、不能在临界区出现阻塞等任务操作。

标签:CRITICAL,Task,Freertos,中断,basepri,void,临界,源码
From: https://blog.csdn.net/2301_80348599/article/details/142815078

相关文章

  • 计算机毕业设计 | vue+SpringBoot图书借阅管理系统 图书管理系统(附源码)
    1,概述1.1课题背景随着现在科学技术的进步,人类社会正逐渐走向信息化,图书馆拥有丰富的文献信息资源,是社会系统的重要组成部分,在信息社会中作用越来越重要,在我国图书馆计算机等信息技术的应用起步于20世纪70年代末期,随着改革开放的步伐的迅速发展,特别是90年代以后,我......
  • 批量生成二维码源码系统 一键生成二维码 带完整的安装代码包以及搭建部署教程
    系统概述批量生成二维码源码系统是一款功能强大的工具,它旨在为用户提供高效、便捷的二维码生成服务。该系统采用先进的技术和算法,能够快速生成大量高质量的二维码,满足不同用户的需求。该系统具有高度的可扩展性和灵活性,能够与各种应用场景和业务需求相结合。无论是在商业营销......
  • 计算机毕业设计 | SSM 旅游网站后台管理系统(附源码)
    1,概述1.1背景分析随着人们生活水平的提高和对休闲旅游的日益重视,旅游业已成为全球最大的经济产业之一。越来越多的人选择通过在线方式进行旅行预订,这种趋势为旅游网站提供了巨大的商机。用户体验是决定旅游网站成功与否的关键因素。良好的用户界面设计、快速的搜索结果、......
  • 【开题报告】基于django+vue健身房管理系统(论文+源码)计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着现代社会对健康生活的追求日益增长,健身房作为一种提供专业健身服务和设施的场所,受到了广大消费者的青睐。然而,传统的健身房管理方式往......
  • Java项目: 基于SpringBoot+mybatis+maven+vue健身房管理系统(含源码+数据库+毕业论文)
    一、项目简介本项目是一套基于SpringBoot+mybatis+maven+vue健身房管理系统包含:项目源码、数据库脚本等,该项目附带全部源码可作为毕设使用。项目都经过严格调试,eclipse或者idea确保可以运行!该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用......
  • 基于YOLO11/v10/v8/v5深度学习的安检X光危险品检测与识别系统设计与实现【python源码+
    《博主简介》小伙伴们好,我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。✌更多学习资源,可关注公-仲-hao:【阿旭算法与机器学习】,共同学习交流~......
  • 基于django的民宿预定管理系统的设计与实现---附源码60197
    目录摘要1绪论1.1选题背景与意义1.2国内外研究现状1.3论文结构与章节安排2系统分析2.1可行性分析2.1.1经济可行性分析2.1.2技术可行性分析2.1.3操作可行性分析2.2系统流程分析2.2.1系统开发流程2.2.2用户登录流程2.2.3系统操作流程2.2.......
  • [含文档+PPT+源码等]精品基于Python实现的个性化阅读推荐系统
    基于Python实现的个性化阅读推荐系统的背景主要源于互联网技术的飞速发展和用户对于个性化信息获取的需求增加。以下是对该背景的具体阐述:一、互联网技术发展随着互联网技术的不断进步,数字化阅读已成为人们获取信息的重要方式。无论是电子书、在线文章还是各类文献资料,都通过......
  • jsp大学生公寓管理系统tj767--程序+源码+数据库+调试部署+开发环境
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表学生,工作人员,宿舍信息,住宿信息,报修信息,维修信息,人员评分,评分信息开题报告内容一、研究背景与目的随着高校扩招,大学生公寓管理面临诸多挑战,如住宿分配、......
  • jsp大学生创新创业管理系统09jwy程序+源码+数据库+调试部署+开发环境
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表学生,教师,专家,项目信息,项目分配,项目类型开题报告内容一、项目名称大学生创新创业管理系统二、项目背景与意义在“大众创业,万众创新”的时代背景下,大学生......