一、先说明中断分组的由来
中断优先级分组表:
优先级分组 | 抢占优先级 | 响应优先级 | bit[7:4] 分配情况 | 备注 |
NVIC_PriorityGroup_0 | 取值:0 | 取值:0~15 | 0:4 | 0bit抢占优先级、4bit响应优先级 |
NVIC_PriorityGroup_1 | 取值:0~1 | 取值:0~7 | 1:3 | 1bit抢占优先级、3bit响应优先级 |
NVIC_PriorityGroup_2 | 取值:0~3 | 取值:0~3 | 2:2 | 2bit抢占优先级、2bit响应优先级 |
NVIC_PriorityGroup_3 | 取值:0~7 | 取值:0~1 | 3:1 | 3bit抢占优先级、1bit响应优先级 |
NVIC_PriorityGroup_4 | 取值:0~15 | 取值:0 | 4: | 4bit抢占优先级、0bit响应优先级 |
抢占优先级和响应优先级:
1、抢占优先级不同,会涉及到中断嵌套,抢占优先级高的会优先抢占优先级低的,优先得到执行。
(注意:优先级数字越小,优先级越高)
2、抢占优先级相同,不涉及到中断嵌套,响应优先级不同,响应优先级高的先响应。
(例如:两个中断同时响应,这里就会先执行响应优先级高的那个中断)(注意:优先级数字越小,优先级越高)
3、抢占优先级和响应优先级都相同,则比较它们的硬件中断编号,中断编号越小,优先级越高。
(硬件中断编号从中断向量表当中查看)
二、配置中断优先级分组
整个系统执行过程中,只设置一次中断分组。(NVIC_PriorityGroupConfig只是对一个寄存器操作。多次操作以最后一次设置为准。)
即我们在上电初始化进行一次配置即可,正常是配置分组2
三、关于RTOS的中断优先级分组配置
(1)RTOS的中断配置没有处理亚优先级这种情况,即要求全部为抢占优先级,所以我们在 RTOS 调度启动前调用函数NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 )将全部优先级设为抢占优先级.
(2)相对于FreeRTOS优先级设置
configKERNEL_INTERRUPT_PRIORITY
设置 FreeRTOS 内核本身使用的中断优先级, 因为FreeRTOS内核中断不应当抢占用户使用的中断, 因此一般定义为硬件最低优先级
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY15 //中断最低优先级
我的理解目前知道这边。后面子在看看资料有没有更深入理解。
转发一位大哥记录的由于中断分组导致RTOS出现的问题:
原文:https://blog.csdn.net/HuiCMs/article/details/83065791
最近一年多在做freeRTOS+stm32F407IG+LwIP+CAN等的应用,研发铁路逻辑控制单元LCU,实现可视化IO逻辑编程。
其中有一项功能,是利用TCP连接在PC机和LCU机箱内的控制板之间进行数据同步,从而实现IO逻辑代码Debug。
TCP连接作为一个任务,传输调试信息。要求TCP连接要稳定(至少24小时以上,因为地铁一般每天运行不会超过18小时),且不能影响其他任务的实时性(IO逻辑、机箱控制逻辑等)。因此TCP连接任务优先级较低(但是LwIP任务优先级较高),且为信号触发性任务。
此为背景。
在调试该功能的过程中,出现连接不稳定、死机等情况:
测试现象每次都不太一样,hardfault中断、陷入OS的死循环、任务全部停止但程序未死、部分任务停止运行而其他任务正常等等。基本每次建立连接后几分钟到十几二十分钟,就会出现以上各种各样的问题。甚至有根本连接不上的情况。
直观判断,很像内存溢出,或者任务堆栈溢出。在尝试增加任务堆栈、分析内存消耗后,未解决问题。
最后重新翻书
ALIENTEK的基础例程默认将STM32的优先级分组配置为2,即4个抢占优先级、4个亚优先级。而freeRTOS的中断配置没有处理亚优先级这种情况,即要求全部为抢占优先级。所以STM32移植freeRTOS时,应将中断优先级配置为4,即16个抢占优先级。
依此修改代码:
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
修改为
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
此后测试,以太网稳如狗,问题得到较好解决。
心得:看书要从头看,温故知新。
转载一位大哥的:https://www.cnblogs.com/milton/p/16884964.html
这部分我还没理解,有兴趣同学可以琢磨看下
FreeRTOS优先级设置
对于 STM32F103, FreeRTOSConfig.h 中需要配置 configKERNEL_INTERRUPT_PRIORITY 和 configMAX_SYSCALL_INTERRUPT_PRIORITY, 另外在 FreeRTOS 调度启动前调用函数NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 )将全部优先级设为抢占优先级.
configKERNEL_INTERRUPT_PRIORITY
设置 FreeRTOS 内核本身使用的中断优先级, 因为FreeRTOS内核中断不应当抢占用户使用的中断, 因此一般定义为硬件最低优先级
对于STM32F103, 优先级总共4-bit, 在字节的最高位, bit[7:4], 全一表示的最低优先级, 所以在 FreeRTOSConfig.h 中将其设置为 0B1111xxxx 的任一个值就行 [240, 255]
对于AIR32F103, 优先级总共3-bit, 字节最高位 bit[7:5], 所以设置为 0B111xxxxx 的任一个值就行 [160, 255]
configMAX_SYSCALL_INTERRUPT_PRIORITY
设置可以在中断服务程序中, 调用中断安全的FreeRTOS API函数的最高中断优先级.
FreeRTOS 中断嵌套方案将可用的中断优先级分成2组: 被 FreeRTOS 临界区覆盖的, 和不会被覆盖的(这些中断是无法被屏蔽的), 优先级高于配置值的中断, 不受FreeRTOS管控, 在 FreeRTOS 中无法通过进入临界区屏蔽这些中断, 因此也不能在这些中断中调用 FreeRTOS API, 否则系统会有崩溃的风险
例如将这个优先级设置为5, 那么如果有一个中断优先级等于4, 在这个中断中调用了FreeRTOS API, 则系统会有崩溃的风险, 如果使能了configASSERT宏, 会触发断言失败.
在STM32中要保证所有的优先级设置为可抢占优先级, 具体实现方式是在 FreeRTOS 启动前, 调用函数NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4)
STM32使用了中断优先级寄存器中的4位, bit[7:4], 如果设置优先级为5, 对应的二进制值为0x101,
对应STM32使用的 bit[7:4] 就是0x0101, 剩余的 bit[3:0] 可以设置成任何值, 但为了兼容,最好将他们设置成1. 因此就是0x0101 1111 = 0x5F = 95
对应AIR32/MH32使用的是 bit[7:5] 就是0x101, 剩余的 bit[4:0] 可以设置成任何值, 设成全1就是0x1011 1111 = 0xBF = 191
/* AIR32F103 only use 3 bits(bit[7:5]) for priority */
/* This is the raw value as per the Cortex-M3 NVIC. Values can be 255
(lowest) to 0 (1?) (highest). */
/* equivalent to 0xFF (0x111x xxxx, x=1), or priority 7. */
#define configKERNEL_INTERRUPT_PRIORITY 255
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
/* equivalent to 0xBF (0x101x xxxx, x=1), or priority 5. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 191
常见的是结合 CMSIS_CORE 的宏进行设置, 下面是M0/M0+的例子, 如果是M3/M4, 将 configPRIO_BITS 改为 4, configLIBRARY_LOWEST_INTERRUPT_PRIORITY 改为 0x0F. 如果是AIR32F103则是 3 和 0x07.
/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS
/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
#define configPRIO_BITS __NVIC_PRIO_BITS
#else
#define configPRIO_BITS 2 /* 4 priority levels for Cortex M0/M0+ */
#endif
/* The lowest interrupt priority that can be used in a call to a "set priority"
function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x03
/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 0x01
/* This is the raw value as per the Cortex-M3 NVIC. Values can be 255
(lowest) to 0 (1?) (highest). */
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
configMAX_PRIORITIES
configMAX_PRIORITIES 表示任务支持的优先级,创建任务时, 任务的优先级取值范围为 [0, configMAX_PRIORITIES – 1],数字越大优先级越高。
要注意区分前面的configKERNEL_INTERRUPT_PRIORITY, configMAX_SYSCALL_INTERRUPT_PRIORITY 两个设置项和这个设置项的区别, 这个设置项是任务优先级, 不是中断优先级, 是 FreeRTOS 用于控制任务优先级的, 值不受上面的优先级范围限制.
如果将 configUSE_PORT_OPTIMISED_TASK_SELECTION 设置为1, 表示使用根据硬件优化的优先级控制, 会对 configMAX_PRIORITIES 最大值有限制.
configMAX_PRIORITIES的值, 对于Cortex-M3, 一般设成15以内,对于ESP32默认是25, 对于Cortex-M0, 建议设置在7以内.