×

FreeRTOS学习之旅(六) -----临界段保护

zxjy辉 zxjy辉 发表于2022-09-05 15:40:56 浏览242 评论0

抢沙发发表评论

桂林山水甲天下.jpeg

通过控制中断的开关以此来达成一个不会被打断的代码段区域-----临界段

  1. 概念

    1. 一段在绝大部分情况下,不会被打断的代码段,常出现在对全局变量的操作上

    2. 被打断的情况

      1. 一种是:系统调度,也就是Pendsv中断,要执行任务切换

      2. 另一种是:外部中断

  2. 实现方法:通俗来说,也就是在执行这个代码段的时候,将能关的中断都关了,执行完之后,在将中断开起来

    1. Cortex-M内核有三个屏蔽寄存器

      1. PRIMASK:一位寄存器,置1后,除了NMI(不可屏蔽中断)和硬FAULT可以响应,其他的中断都被屏蔽了,0为缺省,不屏蔽任何中断

      2. FAULTMASK:一位寄存器,置1后,除了NMI(不可屏蔽中断)可以响应,其他的中断都被屏蔽了,0为缺省,不屏蔽任何中断

      3. BASEMASK:最多为9位,表示可以屏蔽的优先级的阈值,数值大于等于这个阈值的将会被屏蔽掉(stm32是值越大,优先级越低),为0时,不关闭任何中断

    2. FreeRTOS采用的控制第三个寄存器(BASEMASK),来控制开关中断的方式

      1. 两种关中断:

        1. 带返回值:可以嵌套,可以在中断中使用;             (portSET_INTERRUPT_MASK_FROM_ISR)

        2. 不带返回值:不可以嵌套,不可以在中断中使用      (portDISABLE_INTERRUPT)

      2. 两种开中断:一个方法,但是就是形参不一样

        1. 带形参:将关中断时带有的返回值(BASEPRI)作为一个形参,传递到开中断中,最为寄存器BASEPRI的值

        2. 不带形参:直接将BASEPRI的值设置为0,把所有的中断全开了,没有屏蔽

  3. 进入0R退出临界段的函数方法

    1. 为了方便记忆与调用,官方又在task.h文件中重新定定义了两种开中断和关中断的方法

      1. 关中断

        1.   不带返回值:  #define taskENTER_CRITICAL()                        portENTER_CRITICAL()                                  

        2.   带返回值:     #define taskENTER_CRITICAL_FROM_ISR()      portSET_INTERRUPT_MASK_FROM_ISR()

      2. 开中断

        1.  没有形参:     #define taskEXIT_CRITICAL()                            portEXIT_CRITICAL()

        2. 有形参:        #define taskEXIT_CRITICAL_FROM_ISR( x )      portCLEAR_INTERRUPT_MASK_FROM_ISR( x )

  4. 应用代码

    1. /* 在中断场合,临界段可以嵌套 */
      2 {
      3 uint32_t ulReturn;
      4 /* 进入临界段,临界段可以嵌套 */
      5 ulReturn = taskENTER_CRITICAL_FROM_ISR();
      6
      7 /* 临界段代码 */
      8
      9 /* 退出临界段 */
      10 taskEXIT_CRITICAL_FROM_ISR( ulReturn );
      11 }
    2. /* 在非中断场合,临界段不能嵌套 */
      14 {
      15 /* 进入临界段 */
      16 taskENTER_CRITICAL();
      17
      18 /* 临界段代码 */
      19
      20 /* 退出临界段*/
      21 taskEXIT_CRITICAL();
      22 }
#好好学习!

群贤毕至

访客