一、问题描述:
定时器3的中断优先级设置为6(0-15级),将 configMAX_SYSCALL_INTERRUPT_PRIORITY 的值设置为5。程序预计实现的功能为当进入临界区时,屏蔽定时器3中断,退出临界区时恢复定时器3中断。但是实际验证过程中发现进入临界区后,定时器3中断仍能够正常执行,未能实现预期的功能。
二、问题原因:
在FreeRTOS中,是通过寄存器 basepri 来屏蔽中断的,basepri 的作用是关闭优先级低于或等于某个阈值的中断,优先级高于这个阈值的中断将不会被关闭。由FreeRTOS进入临界区的源码的可知,configMAX_SYSCALL_INTERRUPT_PRIORITY 的值为0x05时,basepri 寄存器的值为0x05,定时器3的优先级低于0x05,进入临界区后应该屏蔽才对啊,是什么原因导致未能屏蔽呢?查看M3权威指南后发现 basepri 寄存器最大可以使用9位,而在STM32中使用FreeRTOS时,使用的中断优先级分组为组4,也就是说16级抢占优先级,没有响应优先级,即高四位为有效位。当 basepri 的值为0x05时,即高四位为0,实际上相当于0x00,此时basepri是无效的,因此无法屏蔽定时器3中断。应该将 configMAX_SYSCALL_INTERRUPT_PRIORITY 的值设置为0x5F才能正常屏蔽定时器3中断。还需要注意的是,basepri 寄存器对应的是抢占优先级,与响应优先级无关,例如定时器3抢占优先级为2,响应优先级为2,此时若想屏蔽定时器3中断,应该将 configMAX_SYSCALL_INTERRUPT_PRIORITY 的值设置为0x2F。
static portFORCE_INLINE void vPortRaiseBASEPRI( void )
{
uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;
__asm
{
/* Set BASEPRI to the max syscall priority to effect a critical
section. */
msr basepri, ulNewBASEPRI
dsb
isb
}
}
//FreeRTOS进入临界区源码
三、M3中另外两个屏蔽中断的寄存器(截图来源:正点原子的《STM32F1 FreeRTOS开发手册》)