中断控制寄存器
对中断的屏蔽与否,通过一下控制寄存器决定
简单来说就是PRIMASK只留了个NMI(不可屏蔽异常,一般是系统出错)和硬件异常;FAULTMASK只留了个硬件异常;而BASEPRI可以选择性屏蔽
临界区
其实就是中断的开关,而开关的中断就是通过对BASEPRI这个中断屏蔽寄存器赋值实现,当优先级低于其设置的中断都被屏蔽。在freertos中定义和实现如下
无返回
进临界区
task.h文件中,宏定义为
#define taskENTER_CRITICAL() portENTER_CRITICAL()
portmacro.h文件中,宏定义为
#define portENTER_CRITICAL() vPortEnterCritical()
port.c文件中,vPortEnterCritical函数的定义
void vPortEnterCritical(void) { /* 进入临界区--不带中断保护 */ portDISABLE_INTERRUPTS(); uxCriticalNesting++; if(uxCriticalNesting == 1) { //configASSERT((portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0); } }
portmacro.h文件中,宏定义为
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
同文件中vPortRaiseBASEPRI函数的定义
static portFORCE_INLINE void vPortRaiseBASEPRI(void) { /*无返回关中断*/ uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY; __asm { msr basepri, ulNewBASEPRI //直接将中断屏蔽值载入 dsb isb } }
出临界区
基本和进临界区一致,区别在于最后的内联函数,使用的是对BASEPRI寄存器赋值的函数,这里赋值为0即开启中断,后面有返回出临界区还会使用到
static portFORCE_INLINE void vPortSetBASEPRI(uint32_t ulBASEPRI) { /* 设置中断寄存器,用来开启中断 */ __asm { msr basepri, ulBASEPRI } }
有返回
进临界区
task.h
#define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR()
portmacro.h
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
同文件ulPortRaiseBASEPRI函数定义
static portFORCE_INLINE uint32_t ulPortRaiseBASEPRI(void) { /*有返回关中断*/ uint32_t ulReturn, ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY; __asm { mrs ulReturn, basepri //先保存这一层嵌套中断的优先级 msr basepri, ulNewBASEPRI //新的优先级载入basepri dsb isb } return ulReturn; //返回这一层的嵌套中断优先级 }
出临界区
因为是出某一层的临界区回到上一层的嵌套,所以要把上一层嵌套的basepri给回去,所以这里使用和无返回出临界区一样的函数,但传入的参数不再是0,而是上一层嵌套basepri
static portFORCE_INLINE void vPortSetBASEPRI(uint32_t ulBASEPRI) { /* 设置中断寄存器,用来开启中断 */ __asm { msr basepri, ulBASEPRI } }
标签:中断,进出,void,寄存器,临界,basepri,uint32 From: https://www.cnblogs.com/toriyung/p/16897648.html