FreeRTOS——临界段

目录

一、临界段

1.1临界段的作用

1.2临界段API

1.2.1关闭中断

1.2.2恢复中断

1.2.3任务中进入临界段

1.2.4任务中退出临界段

1.2.5中断中进入临界段

1.2.6中断中退出临界段

1.5应用

二、临界段实现原理

2.1FreeRTOS中断管理

2.2任务中进入临界段

2.3任务中退出临界段

2.4中断中进入临界段

2.5中断中退出临界段


一、临界段

1.1临界段的作用

实际上就是一段代码(进入和退出之间操作),为了保护共享资源暂时单独使用

对于不想被打断访问的资源有这些:

  • 全局变量 (比如SysTick中断时增加tick值就是进入临界段操作的)

  • 不可重入函数——不能多个任务或线程同时调用的函数,或者当被同时调用时可能导致不确定或不正确的结果

  • 外设(硬件资源)

  • 对时许有精准要求的操作

  • 用户不想被打断的代码

1.2临界段API

1.2.1关闭中断

#inlcude "FreeRTOS.h"
#include "task.h"

/*关闭中断 实际上保留了某些紧急中断 下面实现原理会提到*/
void taskDISABLE_INTERRUPTS(void)
   
注意事项: 使用此API时,不允许嵌套操作

特殊情况下才使用此API,因为此操作相当于把所有中断都关掉了

1.2.2恢复中断

#inlcude "FreeRTOS.h"
#include "task.h"

/*恢复中断*/
void taskENABLE_INTERRUPTS(void)

1.2.3任务中进入临界段

#inlcude "FreeRTOS.h"
#include "task.h"

/*进入临界段,支持嵌套,任务在运行态时调用,不被中断打断*/
void taskENTER_CRITICAL(void)


注意事项: 
        该函数需要和对应的退出函数成对使用;
        确保临界段中的操作尽快执行

1.2.4任务中退出临界段

#inlcude "FreeRTOS.h"
#include "task.h"

/*退出临界段,支持嵌套,任务在运行态内调用,不被中断打断*/
void taskEXTI_CRITICAL(void)

这对API成对使用,其实很好操作,就是把要保护的代码,用这两个API上下包裹住

1.2.5中断中进入临界段

#inlcude "FreeRTOS.h"
#include "task.h"

/*中断中 进入临界段*/
UBaseType_t taskENTER_CRITICAL_FROM_ISR(void)

return: 返回中断屏蔽寄存器的值,退出时需要从传入该参数  

1.2.6中断中退出临界段

#inlcude "FreeRTOS.h"
#include "task.h"

/*中断中 退出临界段*/
void taskEXTI_CRITICAL_FROM_ISR(UBaseType_t uxSavedInterruptStatus)

params: 传入taskENTER_CRITICAL_FROM_ISR()的返回值
    

1.5应用

实现如下功能:两个任务分别间隔50ms打印一次运行信息,通过临界段解决共享资源冲突问题

1.第一次尝试,两个任务分别间隔50ms打印,结果如下

可以看出:两个打印任务“打架”了,原因就是两个任务优先级相同,其中一个任务执行时,遇上另一个任务从阻塞恢复成就绪态时,就影响了上个任务

解决办法:任务中进入临界段来执行打印任务

注意:

2.第二次尝试

可以看出,两个任务不会再打架了

二、临界段实现原理

2.1FreeRTOS中断管理

HAL_Init--->HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4)

实际上就是图上分组3,无响应优先级,只有抢占优先级

FreeRTOS采用更灵活BASEPRI指令,同时,中断优先级,值越小,优先级越大,而任务优先级, 值越大优先级越高

这里需要注意一下:basepri值默认为0,表示不关闭任何中断。而一旦设置成某个值,表示>=该值的中断都会被屏蔽

即:中断屏蔽门限值5,>=5的中断都被关 (这个是用来关中断的) 同时 内核调度中断优先级为最低的15

因此,

  • 关中断:将中断屏蔽门限值(5)赋值给basepri (这一点其实就能看出来,FreeRTOS并没有将所有中断都关了,还是保留了一部分紧急的中断)
  • 开中断:basepri赋值0

2.2任务中进入临界段

  • taskENTER_CRITICAL 是宏替换,原函数属于Cortex M4的硬件外设资源,Port说明移植到其他平台现需要自己实现这段代码

  • 函数内部:

    • 关中断,临界段嵌套值++(这个值在内核启动时初始化为0,后续如果嵌套就再自增)

2.3任务中退出临界段

  • 函数内部:临界段嵌套值 — — (说明确实需要成对出现,不然是无法恢复中断的)

  • 恢复中断,basepri置0

2.4中断中进入临界段

  • 函数内部主要做了两件事:先把当前basepri值返回,再重新basepri赋值

2.5中断中退出临界段

  • 把上次保存的basepri值赋值给basepri

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值