
通过控制中断的开关以此来达成一个不会被打断的代码段区域-----临界段
概念
一段在绝大部分情况下,不会被打断的代码段,常出现在对全局变量的操作上
被打断的情况
一种是:系统调度,也就是Pendsv中断,要执行任务切换
另一种是:外部中断
实现方法:通俗来说,也就是在执行这个代码段的时候,将能关的中断都关了,执行完之后,在将中断开起来
Cortex-M内核有三个屏蔽寄存器
PRIMASK:一位寄存器,置1后,除了NMI(不可屏蔽中断)和硬FAULT可以响应,其他的中断都被屏蔽了,0为缺省,不屏蔽任何中断
FAULTMASK:一位寄存器,置1后,除了NMI(不可屏蔽中断)可以响应,其他的中断都被屏蔽了,0为缺省,不屏蔽任何中断
BASEMASK:最多为9位,表示可以屏蔽的优先级的阈值,数值大于等于这个阈值的将会被屏蔽掉(stm32是值越大,优先级越低),为0时,不关闭任何中断
FreeRTOS采用的控制第三个寄存器(BASEMASK),来控制开关中断的方式
两种关中断:
带返回值:可以嵌套,可以在中断中使用; (portSET_INTERRUPT_MASK_FROM_ISR)
不带返回值:不可以嵌套,不可以在中断中使用 (portDISABLE_INTERRUPT)
两种开中断:一个方法,但是就是形参不一样
带形参:将关中断时带有的返回值(BASEPRI)作为一个形参,传递到开中断中,最为寄存器BASEPRI的值
不带形参:直接将BASEPRI的值设置为0,把所有的中断全开了,没有屏蔽
进入0R退出临界段的函数方法
为了方便记忆与调用,官方又在task.h文件中重新定定义了两种开中断和关中断的方法
关中断
不带返回值: #define taskENTER_CRITICAL() portENTER_CRITICAL()
带返回值: #define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR()
开中断
没有形参: #define taskEXIT_CRITICAL() portEXIT_CRITICAL()
有形参: #define taskEXIT_CRITICAL_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( x )
应用代码
/* 在中断场合,临界段可以嵌套 */ 2 { 3 uint32_t ulReturn; 4 /* 进入临界段,临界段可以嵌套 */ 5 ulReturn = taskENTER_CRITICAL_FROM_ISR(); 6 7 /* 临界段代码 */ 8 9 /* 退出临界段 */ 10 taskEXIT_CRITICAL_FROM_ISR( ulReturn ); 11 }/* 在非中断场合,临界段不能嵌套 */ 14 { 15 /* 进入临界段 */ 16 taskENTER_CRITICAL(); 17 18 /* 临界段代码 */ 19 20 /* 退出临界段*/ 21 taskEXIT_CRITICAL(); 22 }