中断,在任务函数运行的过程中,出现了特定的中断触发条件(中断源,其实就是识别到中断标志位发生改变),让 CPU 打断原本正在运行的程序,转而去处理紧急事件(ISR),执行中断服务函数,处理完后又返回原来被暂停的位置继续运行。
中断的执行机制:(从触发中断到结束的过程)
中断请求:外设产生中断请求(GPIO外部中断、定时器中断等)
↓
响应中断:CPU停止执行当前程序,转而去执行中断处理程序(ISR)
↓
退出中断:执行完毕,返回被打断的程序处,继续往下执行
中断优先级:
当有多个中断源同时申请中断时,CPU 会根据中断源的优先级大小来进行裁决,决定哪个中断优先执行。中断优先级数值越小,越先执行,跟 FreeRTOS 任务优先级相反,任务优先级是越大越优先执行。
ARM Cortex-M 使用了 8 位宽的寄存器来配置中断的优先等级,这个寄存器就是中断优先级配置寄存器,所以中断优先级配置范围在 0~255,可配置的中断优先级范围很大。跟 ARM Cortex-M 相比,STM32 只用了中断优先级配置寄存器的高4位 [7 : 4](即 8 位寄存器中只用了 4~7 这4位,不使用低四位 0~3),所以STM32提供了最大16级(即 0~15)的中断优先等级,如下图
STM32 的中断优先级可分为抢占优先级和子优先级:
抢占优先级: 抢占优先级高的中断可以打断正在执行但抢占优先级低的中断。
子优先级:当同时发生具有相同抢占优先级的两个中断时,子优先级数值小的优先执行。
两者区别:子优先级高的并不能打断正在执行的其他任务的,只能等待任务执行完才能轮到他。类似排队做核酸,子优先级高的是直接插入准备做核酸的下一位,而抢占优先级高的是直接把核酸做一半的人赶走,自己来做。
中断优先级共有5种优先级分组方式:(根据中断优先级配置寄存器的4位的不同配置来分组)
NVIC_PriorityGroup_0:0个bit 用于抢占优先级,4个bit 用于子优先级
NVIC_PriorityGroup_1:1个bit 用于抢占优先级,3个bit 用于子优先级
NVIC_PriorityGroup_2:2个bit 用于抢占优先级,2个bit 用于子优先级
NVIC_PriorityGroup_3:3个bit 用于抢占优先级,1个bit 用于子优先级
NVIC_PriorityGroup_4:4个bit 用于抢占优先级,0个bit 用于子优先级
补充:在 STM32 中,用 NVIC 来专门管理所有中断(所有中断分配的工作都交给了NVIC,给不同的中断分配中断优先级的),是内核的一个外设,用来减轻 CPU 的负担。NVIC 总共有 16 个中断优先等级(0~15,由用户自己分配决定),为了处理不同形式的优先级, STM32 的 NVIC 对中断优先级进行了分组,分为了五组。
FreeRTOS 用的是 NVIC_PriorityGroup_4
FreeRTOS 中断优先级的特点:
1、低于 configMAX_SYSCALL_INTERRUPT_PRIORITY 优先级(即大于等于5的优先级,在5~15之间)的中断里才允许调用FreeRTOS 的API函数。
中断优先级要 >= 5,这样在中断函数里调用 FreeRTOS 的 API 函数才能用,因为 FreeRTOS 所管理的最高中断优先级大于 5 的(中断优先级里是越低越高)。
2、建议将所有优先级位指定为抢占优先级位(即 NVIC_PriorityGroup_4),方便FreeRTOS管理。
3、中断优先级数值越小越优先,任务优先级数值越大越优先。