什么是临界段?临界段就是在执行时不能被打断(除非是系统调度(pend SV中断),或外部中断)的代码。
FreeRTOS对临界段的保护还是通过对中断的开和关来控制。
Cortex-M内核快速关中断指令:
①:
这个寄存器是只有一位的寄存器。控制方式如下:
②:
同样也是一位的寄存器。
③:
关中断
freeRTOS关中断的函数定义在 portmacro.h 文件中。
关中断函数分为带返回值和不带返回值两种。
不带返回值的如下:
注意:不带返回值的是不能嵌套,且不能在中断中使用的。
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
static portFORCE_INLINE void vPortRaiseBASEPRI(void)
{
uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;
__asm
{
msr basepri, ulNewBASEPRI // 大于11 是不能被响应的,小于11是能响应的
dsb
isb
}
}
带返回值的如下:
注意:带返回值的是能够用于中断且能嵌套使用的。
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI() // 凡是看到FROM_ISR,都是在中断里面用到。
// 返回一个无符号整型变量。 可嵌套,可在中断中使用
static portFORCE_INLINE uint32_t ulPortRaiseBASEPRI(void)
{
uint32_t ulReturn,ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;
__asm
{
mrs ulReturn,basepri // 把原先basepri的值保存在返回值中
msr basepri,ulNewBASEPRI // 在设置basepri的值
dsb
isb
}
return ulReturn;
}
开中断
与关中断一样,开中断函数也是在 portmacro.h 函数中定义的。
开中断函数分为有中断保护的和不带中断保护的函数。
带中断保护的:
与带返回值的关中断函数portSET_INTERRUPT_MASK_FROM_ISR()
配对使用。
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x)
static portFORCE_INLINE void vPortSetBASEPRI(uint32_t ulBASEPRI) // 开中断函数
{
__asm
{
msr basepri,ulBASEPRI
}
}
不带中断保护的:
与不带返回值的 portDISABLE_INTERRUPTS()
配对使用。
#define portENABLE_INTERRUPTS() vPortSetBASEPRI(0)
开中断函数将 ulBASEPRI保存到BASEPRI寄存器中(汇编语言:msr用于恢复状态寄存器的内容或改变寄存器的内容。),根据传进来的形参选择两者中的一个。
进入/退出临界段
进入和退出临界段的宏分中断保护版本和非中断版本, 但最终都是通过开/关中断来实现。
进入临界段:
退出临界段:
有一部分是根据野火freeRTOS内核实现与应用开发实战指南截图的。
如果有需要PDF的请联系我。
如有错误,欢迎批评指正。
欢迎交流学习!
完。