中断管理
让CPU打断正常运行的程序,转而去处理紧急的事件(程序),就叫中断
中断执行机制,可简单概括为三步:
- 中断请求:外设发出中断请求;
- 响应中断:CPU停止执行当前程序,转而去执行中断处理程序;
- 推出中断:执行完毕,返回被打断的程序处继续执行。
中断优先级分组设置
优先级分类
ARM Cortex-M使用了8位宽的寄存器来配置中断的优先级,这个寄存器就是中断优先级配置寄存器
但STM32只使用了中断优先级配置寄存器的高4位[7:4],所以STM32提供了最大16级的中断优先等级。
STM32的中断优先级可以分为抢占优先级和子优先级。
抢占优先级:抢占优先级高的中断可以打断正在执行但抢占优先级低的中断
子优先级:当同时发生具有相同抢占优先级的两个中断时,子优先级数值小的优先执行
中断优先级数值越小越优先
分配方式
中断优先级一共有5中分配方式,对应这中断优先级分组的5个组
优先级分组 | 抢占优先级 | 子优先级 | 优先级配置寄存器高4位 |
---|---|---|---|
NVIC_PrioriGroup_0 | 0级抢占优先级 | 0-15级子优先级 | 0bit用于抢占优先级;4bit用于子优先级级 |
NVIC_PrioriGroup_1 | 0-1级抢占优先级 | 0-7级子优先级 | 1bit用于抢占优先级;3bit用于子优先级级 |
NVIC_PrioriGroup_2 | 0-3级抢占优先级 | 0-3级子优先级 | 2bit用于抢占优先级;2bit用于子优先级级 |
NVIC_PrioriGroup_3 | 0-7级抢占优先级 | 0-1级子优先级 | 3bit用于抢占优先级;1bit用于子优先级级 |
NVIC_PrioriGroup_4 | 0-15级抢占优先级 | 0级子优先级 | 4bit用于抢占优先级;0bit用于子优先级级 |
FreeRTOS主要使用NVIC_PrioriGroup_4管理中断优先级,即无子优先级。
FreeRTOS中断特点
- 低于configMAX_SYSCALL_INTERRUPT_PRIORITY优先级的中断里才允许调用FreeRTOS的API函数——上份笔记中提到的优先级(5-15)才允许调用挂起任务函数。
- 所有优先级位指定为抢占优先级位,方便FreeRTOS管理
- 中断优先级数值越小越优先,任务优先级数值越大越优先
中断相关寄存器
系统中断优先级配置寄存器
三个系统中断优先级配置寄存器,分别为SHPR1、SHPR2、SHPR3,大小均为32位
SHPR1寄存器地址:0xE000ED18
SHPR2寄存器地址:0xE000ED1C
SHPR3寄存器地址:0xE000ED20
地址 | 名称 | 描述 |
---|---|---|
0xE000ED18 | PRI_4 | 存储器管理fault的优先级 |
0xE000ED19 | PRI_5 | 总线fault的优先级 |
0xE000ED1A | PRI_6 | 用法fault的优先级 |
0xE000ED1B | - | - |
0xE000ED1C | - | - |
0xE000ED1D | - | - |
0xE000ED1E | - | - |
0xE000ED1F | PRI_11 | SVC优先级 |
0xE000ED20 | PRI_12 | 调试监视器的优先级 |
0xE000ED21 | - | - |
0xE000ED22 | PRI_14 | PendSV的优先级 |
0xE000ED23 | PRI_15 | SysTick的优先级 |
PendSV和Systick一般配置为中断最低优先级,保证系统切换任务时不会阻塞系统其他中断的响应
中断屏蔽寄存器
三个中断屏蔽寄存器,分别位PRIMASK、FAULTMASK和MASEPRI
名字 | 功能描述 |
---|---|
PRIMASK | 这是个只有1个位的寄存器,当它置1时,就关掉所有可屏蔽的中断,只剩下NMI和硬fault可以响应。它的缺省值是0,表示没有关中断 |
FAULTMASK | 这是个只有1个位的寄存器,当它置1时,只剩下NMI可以响应。它的缺省值是0,表示没有关中断 |
BASEPRI | 这个寄存器最多有9位(由表达优先级的位数决定)。它定义了被屏蔽优先级的阈值。当它被设置成某个值后,所有优先级号大于等于此值的中断都被关 |
FreeRTOS所使用的中断管理就是利用的BASEPRI这个寄存器
比如:BASEPRI设置为0x50,表示中断优先级在5~15内的均被屏蔽,优先级高于5的中断则不会被FreeRTOS屏蔽
在中断服务函数中调度FreeRTOS的API函数需注意:
- 中断服务函数的优先级需在FreeRTOS所管理的范围内
- 在中断服务函数里边需调用FreeRTOS的API函数,必须使用带“FromISR”后缀的函数
FreeRTOS的中断管理就是利用BASEPRI寄存器实现的。