目录
2.1.1 FreeRTOS配置PendSV和Systick中断优先级
一. 了解什么是中断
1.1 对中断的简单认识
认识:让CPU打断正常运行的程序,转而去处理紧急的事件,就叫做中断。
中断执行机制,可简单概括为三步:
① 中断请求:外设产生中断请求(GPIO外部中断、定时器中断等);
② 响应中断:CPU停止执行当前程序,转而去执行中断处理程序;
③ 退出中断:执行完毕,返回被打断的程序处,继续往下执行。(打断哪个点,就返回哪个点继续执行)
1.2 中断优先级分组
认识:
① 在ARM Cortex - M中使用了8位宽(256个优先级,0~255)的寄存器来配置中断的优先级,这个寄存器就是中断优先级配置寄存器。
② 在STM32中,只用了该寄存器的高4位[7:4],所以STM32提供了16个(0~15)的中断优先等级。
STM32 的中断优先级可以分为抢占优先级和子优先级
A. 抢占优先级:抢占优先级高的中断可以打断正在执行的抢占优先级低的中断。
B. 子优先级:当同时发生具有相同抢占优先级的多个中断时,子优先级高的先执行。若子优先级低的先执行,子优先级高的中断则无法打断。
注意:中断优先级数值越小越优先。
1.3 FreeRTOS的中断
① 低于configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY优先级的中断里才允许调用FreeRTOS 的API函数。
(例如,在代码中configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY设置的是5,所以能被FreeRTOS操作的中断优先级是5~15)
② 建议将所有优先级位指定为抢占优先级位,方便FreeRTOS管理
③ 中断优先级数值越小越优先,任务优先级数值越大越优先。
二. 中断相关寄存器
2.1 三个系统中断优先级配置寄存器
三个系统中断优先级配置寄存器,分别为 SHPR1、 SHPR2、 SHPR3
SHPR1寄存器地址:0xE000ED18
SHPR2寄存器地址:0xE000ED1C
SHPR3寄存器地址:0xE000ED20
表中一个地址是8个位,一个寄存器是32位。
若想设置PendSV的优先级,则需要从SHPR3首地址偏移16位;
若想设置SysTick的优先级,则SHPR3首地址偏移24位。
注意:
PendSV实现任务切换和调度。
SysTick给系统提供心跳节拍。
2.1.1 FreeRTOS配置PendSV和Systick中断优先级
其中0XE000ED20是寄存器SHPR3的首地址。
PendSV的首地址等于变量configKERNEL_INTERRUPT_PRIORITY左移16位,
Systick的首地址 等于变量configKERNEL_INTERRUPT_PRIORITY左移24位。
configKERNEL_INTERRUPT_PRIORITY为变量configLIBRARY_LOWEST_INTERRUPT_PRIORITY 左移 8-configPRIO_BITS位(其中configPRIO_BITS宏定义为4,configLIBRARY_LOWEST_INTERRUPT_PRIORITY宏定义为15),即将15左移4位,因为STM32优先级配置低4位并没有用到,左移4位到高四位。
经过以上配置将PendSV和Systick设置优先级位15。
设置最低:保证系统任务切换不会阻塞系统其他中断的响应(中断可以打断任务,任务不能打断中断,因为中断是较为紧急的事情)
2.2 三个中断屏蔽寄存器
三个中断屏蔽寄存器,分别为 PRIMASK、 FAULTMASK 、BASEPRI
2.2.1 BASEPRI这个寄存器的认识
BASEPRI:设置为某个值时,屏蔽优先级低于某一个阈值的中断,当设置为0时,则不关闭任何中断。
例如: BASEPRI设置为0x50,代表中断优先级在5~15内的均被屏蔽,0~4的中断优先级正常执行。
2.2.2 关中断函数
portDISABLE_INTERRUPTS();
关中断程序示例:
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI() static portFORCE_INLINE void vPortRaiseBASEPRI( void ) { uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY; __asm { msr basepri, ulNewBASEPRI dsb isb } } #define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 /* FreeRTOS可管理的最高中断优先级 */
以上程序中变量 configMAX_SYSCALL_INTERRUPT_PRIORITY为0x50,赋值给变量ulNewBASEPRI ,使用汇编语言将ulNewBASEPRI 赋值给BASEPRI寄存器。
2.2.3 开中断函数
portENABLE_INTERRUPTS();
开中断程序示例:
#define portENABLE_INTERRUPTS() vPortSetBASEPRI( 0 ) static portFORCE_INLINE void vPortSetBASEPRI( uint32_t ulBASEPRI ) { __asm { msr basepri, ulBASEPRI } }
以上程序将寄存器BASEPRI设置成0
在中断服务函数中调度FreeRTOS的API函数需注意:
1、中断服务函数的优先级需在FreeRTOS所管理的范围内;
2、在中断服务函数里边需调用FreeRTOS的API函数,必须使用带“FromISR”后缀的函数 ;
3、优先级分组必须设置为组4,全部设置成抢占优先级。