注:在使用大多数功能时,FreeRTOS都要将对应的宏置为1,具体的需要查看FreeRTOS官方文档。
注:中断优先级数字越小,优先级越高;任务优先级书记越小,优先级越小。
中断简介
让CPU打断正常运行的程序,转而去处理紧急事件(程序),就是中断
执行机制
1.中断请求:外设产生中断请求(GPIO外部中断,定时器中断等)
2.响应中断:CPU停止执行当前程序,去处理中断程序(ISR)
3.退出中断:执行完毕,返回被打断的程序处继续执行
中断优先级分组
ARM Cortex-M 使用8位宽的寄存器配置中断优先级,最大可支持 2^8(256) 个中断源.
STM32只使用高四位[7:4],最多配置 2^4 个中断优先级。
优先级分组在NVIC中配置
抢占优先级: 抢占优先级高的中断可以打断正在执行但抢占优先级低的中断,即中断嵌套。
子优先级: 抢占优先级相同时,子优先级高的中断不能打断正在执行但子优先级低的中的中断,即子优先级不支持中断嵌套。
任务切换流程图
所有任务只有进入就绪态后才可以进入运行态。
中断相关寄存器
中断优先级配置寄存器
系统中断有独立的中断优先级配置寄存器,分别为 SHPR1、 SHPR2、 SHPR3
三个寄存器地址如下
单独看地址我们很难理解其进行配置的原理,那让我们来看下FreeRTOS是如何对PEND_SV和滴答定时器中断进行配置优先级的,下面是两个定时器的优先级地址,
可以看到,每一位地址代表8位,每四个地址位32位,代表一个中断优先级配置寄存器,也就是说,如果我们要设置PendSV中断优先级的话,只需要将寄存器SHPR3向左移16位即可,在FreeRTOS中的代码表现如下,
此处左移四位的原因是,STM32只操作高四位[7:4],所以需要将低四位左移到高四位,上述操作最终的结果是,将PendSV中断优先级设置为最低15。
设置成优先级最低的原因是保证系统任务切换不会阻塞其他中断的响应。
上述代码难度较大,做出以下解释,
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
不是将portNVIC_PENDSV_PRI
与地址0xE000ED20
进行或运算,而是与0xE000ED20
地址指向的寄存器的内容进行运算。因为该处定义的portNVIC_SHPR3_REG是一个指针。
- 假设我们要将优先级设置为15,假设
SHPR3
寄存器的初始值是0x00000000,
步骤可以总结如下,- 步骤1:
SHPR3
寄存器当前值为0x00000000
。 - 步骤2: 将
portNVIC_PENDSV_PRI
(0x000F0000
) 与SHPR3
当前值 (0x00000000
) 进行按位或运算,结果是0x000F0000
。 - 步骤3: 将结果
0x000F0000
写回SHPR3
寄存器。
- 步骤1:
中断屏蔽寄存器
ARM Cortex-M 有三个用于屏蔽中断的寄存器,分别为 PRIMASK、FAULTMASK 和BASEPRI。
FreeRTOS使用BASEPRI寄存器来管理中断,用于屏蔽优先级低于某个阈值的中断。
中断管理的源码如下,
简单理解就是,通过设置某个与子ulNewBASEPRI,将其写入寄存器basepri,屏蔽掉所有低于该优先级的中断。同样,在打开中断时,则将该值设置为0即可。
以下是FreeeRTOS中断配置,