STM32 M3M4 MCU与FreeRTOS 中断优先级配置

STM32 M3/M4 MCU与FreeRTOS 中断优先级配置

文章目录

1.MCU NVIC硬件介绍

强烈推荐用户将 Cortex-M3 内核的 STM32F103 和 Cortex-M4 内核的 STM32F407 以及STM32F429 的 NVIC 优先级分组设置为 4,即:NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);这样中断优先级的管理将非常方便。 这个也是官方强烈建议的。

STM32 M3M4 MCU与FreeRTOS 中断优先级配置

(注意:一旦初始化好 NVIC 的优先级分组后,切不可以在应用中再次更改。)
设置 NVIC 的优先级分组为 4 表示支持 0-15 级抢占优先级 (注意, 0-15 级是 16 个级别,包含 0 级), 不支持子优先级。
在这里继续强调下这一点,在 NVIC 分组为 4 的情况下,抢占优先级可配置范围是 0-15,那么数值越小,抢占优先级的级别越高,即 0 代表最高优先级,15 代表最低优先级。

; 2.FreeRTOS 配置选项中 NVIC 相关配置

FreeRTOSConfig.h 配置文件中设置到 NVIC 中断的有如下几个选项:

/*
 * Cortex-M内核使用8bit来配置优先级,但是STM32只使用了高4bit,数值越小,优先级越高。
 * 在往寄存器里面写数值配置的时候,是按照8bit来写的,所以真正写的时候需要经过转换,公式为:
 * ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff)&#xFF0C;&#x5176;&#x4E2D;&#x7684;priority&#x5C31;&#x662F;&#x6211;&#x4EEC;&#x914D;&#x7F6E;&#x7684;&#x771F;&#x6B63;&#x7684;&#x4F18;&#x5148;&#x7EA7;
 */
#ifdef __NVIC_PRIO_BITS  /* __NVIC_PRIO_BITS &#x5DF2;&#x7ECF;&#x5728;stm32f4xx.h&#x91CC;&#x9762;&#x5B9A;&#x4E49;&#x4E3A;4 */
    #define configPRIO_BITS               __NVIC_PRIO_BITS
#else
    #define configPRIO_BITS               4
#endif
/*============================================== SysTick&#x4E2D;&#x65AD;&#x4F18;&#x5148;&#x7EA7;&#x914D;&#x7F6E; ============================================*/
/*
 * &#x5728;&#x5F80;&#x5BC4;&#x5B58;&#x5668;&#x91CC;&#x9762;&#x5199;&#x6570;&#x503C;&#x914D;&#x7F6E;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x662F;&#x6309;&#x7167;8bit&#x6765;&#x5199;&#x7684;&#xFF0C;&#x6240;&#x4EE5;&#x771F;&#x6B63;&#x5199;&#x7684;&#x65F6;&#x5019;&#x9700;&#x8981;&#x7ECF;&#x8FC7;&#x8F6C;&#x6362;&#xFF0C;&#x516C;&#x5F0F;&#x4E3A;&#xFF1A;
 * ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff)&#xFF0C;&#x5176;&#x4E2D;&#x7684;priority&#x5C31;&#x662F;&#x6211;&#x4EEC;&#x914D;&#x7F6E;&#x7684;&#x771F;&#x6B63;&#x7684;&#x4F18;&#x5148;&#x7EA7;&#x3002;&#x7ECF;&#x8FC7;&#x8FD9;&#x4E2A;&#x516C;&#x5F0F;&#x4E4B;&#x540E;&#x5F97;&#x5230;&#x7684;&#x662F;
 * &#x4E0B;&#x9762;&#x7684;&#x8FD9;&#x4E2A;&#x5B8F;&#xFF1A;configKERNEL_INTERRUPT_PRIORITY
 * SysTick&#x7684;&#x4F18;&#x5148;&#x7EA7;&#x6211;&#x4EEC;&#x4E00;&#x822C;&#x914D;&#x7F6E;&#x4E3A;&#x6700;&#x4F4E;&#xFF0C;&#x5373;0xf &#x3002;&#x8FD9;&#x6837;&#x53EF;&#x4EE5;&#x63D0;&#x9AD8;&#x7CFB;&#x7EDF;&#x7684;&#x5B9E;&#x65F6;&#x54CD;&#x5E94;&#x80FD;&#x529B;&#xFF0C;&#x5373;&#x5176;&#x4ED6;&#x7684;&#x5916;&#x90E8;&#x4E2D;&#x65AD;&#x53EF;&#x4EE5;&#x53CA;&#x65F6;&#x7684;&#x5F97;&#x5230;&#x54CD;&#x5E94;&#x3002;
 */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY            0xf
#define configKERNEL_INTERRUPT_PRIORITY         ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

/*===========================================&#x53EF;&#x5C4F;&#x853D;&#x7684;&#x4E2D;&#x65AD;&#x4F18;&#x5148;&#x7EA7;&#x914D;&#x7F6E;====================================================*/
/*
 * &#x7528;&#x4E8E;&#x914D;&#x7F6E;STM32&#x7684;&#x7279;&#x6B8A;&#x5BC4;&#x5B58;&#x5668;basepri&#x5BC4;&#x5B58;&#x5668;&#x7684;&#x503C;&#xFF0C;&#x7528;&#x4E8E;&#x5C4F;&#x853D;&#x4E2D;&#x65AD;&#xFF0C;&#x5F53;&#x5927;&#x4E8E;basepri&#x503C;&#x7684;&#x4F18;&#x5148;&#x7EA7;&#x7684;&#x4E2D;&#x65AD;&#x5C06;&#x88AB;&#x5168;&#x90E8;&#x5C4F;&#x853D;&#x3002;basepri&#x53EA;&#x6709;4bit&#x6709;&#x6548;&#xFF0C;
 * &#x9ED8;&#x8BA4;&#x53EA;&#x4E3A;0&#xFF0C;&#x5373;&#x5168;&#x90E8;&#x4E2D;&#x65AD;&#x90FD;&#x6CA1;&#x6709;&#x88AB;&#x5C4F;&#x853D;&#x3002;configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY&#x914D;&#x7F6E;&#x4E3A;&#xFF1A;5&#xFF0C;&#x610F;&#x601D;&#x5C31;&#x662F;&#x4E2D;&#x65AD;&#x4F18;&#x5148;&#x7EA7;&#x5927;&#x4E8E;5&#x7684;&#x4E2D;&#x65AD;&#x90FD;&#x88AB;&#x5C4F;&#x853D;&#x3002;
 * &#x5F53;&#x628A;&#x914D;&#x7F6E;&#x597D;&#x7684;&#x4F18;&#x5148;&#x7EA7;&#x5199;&#x5230;&#x5BC4;&#x5B58;&#x5668;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x662F;&#x6309;&#x7167;8bit&#x6765;&#x5199;&#x7684;&#xFF0C;&#x6240;&#x4EE5;&#x771F;&#x6B63;&#x5199;&#x7684;&#x65F6;&#x5019;&#x9700;&#x8981;&#x7ECF;&#x8FC7;&#x8F6C;&#x6362;&#xFF0C;&#x516C;&#x5F0F;&#x4E3A;&#xFF1A;
 * ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff)&#xFF0C;&#x5176;&#x4E2D;&#x7684;priority&#x5C31;&#x662F;&#x6211;&#x4EEC;&#x914D;&#x7F6E;&#x7684;&#x771F;&#x6B63;&#x7684;&#x4F18;&#x5148;&#x7EA7;&#x3002;&#x7ECF;&#x8FC7;&#x8FD9;&#x4E2A;&#x516C;&#x5F0F;&#x4E4B;&#x540E;&#x5F97;&#x5230;&#x7684;&#x662F;&#x4E0B;&#x9762;&#x7684;&#x8FD9;&#x4E2A;&#x5B8F;&#xFF1A;
 * configMAX_SYSCALL_INTERRUPT_PRIORITY
 *
 * &#x5728;FreeRTOS&#x4E2D;&#xFF0C;&#x5173;&#x4E2D;&#x65AD;&#x662F;&#x901A;&#x8FC7;&#x914D;&#x7F6E;basepri&#x5BC4;&#x5B58;&#x5668;&#x6765;&#x5B9E;&#x73B0;&#x7684;&#xFF0C;&#x5173;&#x6389;&#x7684;&#x4E2D;&#x65AD;&#x7531;&#x914D;&#x7F6E;&#x7684;basepri&#x7684;&#x503C;&#x51B3;&#x5B9A;&#xFF0C;&#x5C0F;&#x4E8E;basepri&#x503C;&#x7684;
 * &#x4E2D;&#x65AD;FreeRTOS&#x662F;&#x5173;&#x4E0D;&#x6389;&#x7684;&#xFF0C;&#x8FD9;&#x6837;&#x505A;&#x7684;&#x597D;&#x5904;&#x662F;&#x53EF;&#x4EE5;&#x7CFB;&#x7EDF;&#x8BBE;&#x8BA1;&#x8005;&#x53EF;&#x4EE5;&#x4EBA;&#x4E3A;&#x7684;&#x63A7;&#x5236;&#x90A3;&#x4E9B;&#x975E;&#x5E38;&#x91CD;&#x8981;&#x7684;&#x4E2D;&#x65AD;&#x4E0D;&#x80FD;&#x88AB;&#x5173;&#x95ED;&#xFF0C;&#x5728;&#x7D27;&#x8981;&#x7684;&#x5173;&#x5934;&#x5FC5;&#x987B;&#x88AB;&#x54CD;&#x5E94;&#x3002;
 * &#x800C;&#x5728;UCOS&#x4E2D;&#xFF0C;&#x5173;&#x4E2D;&#x65AD;&#x662F;&#x901A;&#x8FC7;&#x63A7;&#x5236;PRIMASK&#x6765;&#x5B9E;&#x73B0;&#x7684;&#xFF0C;PRIMASK&#x662F;&#x4E00;&#x4E2A;&#x5355;1&#x7684;&#x4E8C;&#x8FDB;&#x5236;&#x4F4D;&#xFF0C;&#x5199;1&#x5219;&#x9664;&#x80FD;&#x9664;&#x4E86;NMI&#x548C;&#x786C; fault&#x7684;&#x6240;&#x6709;&#x4E2D;&#x65AD;&#x3002;&#x5F53;UCOS&#x5173;&#x95ED;
 * &#x4E2D;&#x65AD;&#x4E4B;&#x540E;&#xFF0C;&#x5373;&#x4F7F;&#x662F;&#x4F60;&#x5728;&#x7CFB;&#x7EDF;&#x4E2D;&#x8BBE;&#x8BA1;&#x7684;&#x975E;&#x5E38;&#x7D27;&#x6025;&#x7684;&#x4E2D;&#x65AD;&#x6765;&#x4E86;&#x90FD;&#x4E0D;&#x80FD;&#x9A6C;&#x4E0A;&#x54CD;&#x5E94;&#xFF0C;&#x8FD9;&#x52A0;&#x5927;&#x4E86;&#x4E2D;&#x65AD;&#x5EF6;&#x8FDF;&#x7684;&#x65F6;&#x95F4;&#xFF0C;&#x5982;&#x679C;&#x662F;&#x6027;&#x547D;&#x6538;&#x5173;&#x7684;&#x573A;&#x5408;&#xFF0C;&#x90A3;&#x540E;&#x679C;&#x4F30;&#x8BA1;&#x633A;&#x4E25;&#x91CD;&#x3002;
 * &#x76F8;&#x6BD4;UCOS&#x7684;&#x5173;&#x4E2D;&#x65AD;&#x7684;&#x8BBE;&#x8BA1;&#xFF0C;FreeRTOS&#x7684;&#x8BBE;&#x8BA1;&#x5219;&#x663E;&#x5F97;&#x4EBA;&#x6027;&#x5316;&#x5F88;&#x591A;&#x3002;
 *
 */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY    5
#define configMAX_SYSCALL_INTERRUPT_PRIORITY     ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

define configPRIO_BITS 4

此宏定义用于配置 STM32 的 8 位优先级设置寄存器实际使用的位数。 STM32F103,STM32F407
和 STM32F429 都是使用的 4 位。 另外注意一点,这里使用了一个条件编译,用户可以选择将条件编
译删掉,直接定义一个#define configPRIO_BITS 4 即可。使用条件编译的好处就是方便与系统统
一。这个__NVIC_PRIO_BITS 在 STM32F103 标准库的头文件 stm32f10x.h 中以及 STM32F407/439
的标准库的头文件 stm32f4xx.h 中分别有定义。如果用户在 FreeRTOSConfig.h 文件里面包含了这个
标准库的头文件,那么就会执行条件编译选项:

define configPRIO_BITS __NVIC_PRIO_BITS

STM32 M3M4 MCU与FreeRTOS 中断优先级配置

define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x0f

此宏定义是用来配置 FreeRTOS 用到的 SysTick 中断和 PendSV 中断的优先级。在 NVIC 分组设置为
4 的情况下,此宏定义的范围就是 0-15,即专门配置抢占优先级。这里配置为了 0x0f,即 SysTick
和 PendSV 都是配置为了最低优先级,实际项目中也建议大家配置最低优先级即可。
 SVC 中断
在 FreeRTOS 的移植文件 ports.c 中有用到 SVC 中断的 0 号系统服务,即 SVC 0。此中断在 FreeRTOS
中仅执行一次, 用于启动第一个要执行的任务。 另外, 由于 FreeRTOS 没有配置 SVC 的中断优先级,
默认没有配置的情况下, SVC 中断的优先级就是最高的 0。 如果用户在不清楚自己配置的 PendSV 和
SysTick 中断是否跟实际情况一致时,可以进行硬件调试。 比如 MDK,我们可以在硬件调试的状态下,
先点击全速运行,然后查看如下调试组件:

STM32 M3M4 MCU与FreeRTOS 中断优先级配置

STM32 M3M4 MCU与FreeRTOS 中断优先级配置

define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 0x01

此宏定义比较重要,定义了受 FreeRTOS 管理的最高优先级中断。简单的说就是允许用户在这个中断
服务程序里面调用 FreeRTOS 的 API 的最高优先级。 设置 NVIC 的优先级分组为 4 的情况下。 配置
configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 为 0x01 表示用户可以在抢占式优先级为 1

到 15 的中断里面调用 FreeRTOS 的 API 函数,抢占式优先级为 0 的中断里面是不允许调用的。 不受
FreeRTOS 管理的中断有什么深层的含义吗?

不受 FreeRTOS 管理中断的深入讨论
讲解不受 FreeRTOS 管理的中断之前要说一个小知识点—-中断延迟。 中断延迟时间是衡量 RTOS 实
时操作系统的一项重要指标,那什么又是中断延迟呢?从中断触发到执行中断服务程序的第一条指令这段
时间就是中断延迟时间。
FreeRTOS 内核源码中有多处开关全局中断的地方,这些开关全局中断会加大中断延迟时间。 比如在
源码的某个地方关闭了全局中断,但是此时有外部中断触发,这个中断的服务程序就需要等到再次开启全
局中断后才可以得到执行。开关中断之间的时间越长,中断延迟时间就越大,这样极其影响系统的实时性。
如果这是一个紧急的中断事件,得不到及时执行的话,后果是可想而知的。
针对这种情况,FreeRTOS 就专门做了一种新的开关中断实现机制。 关闭中断时仅关闭受 FreeRTOS
管理的中断,不受 FreeRTOS 管理的中断不关闭,这些不受管理的中断都是高优先级的中断,用户可以在
这些中断里面加入需要实时响应的程序。 FreeRTOS 能够实现这种功能的奥秘就在于 FreeRTOS 开关中断
使用的是寄存器 basepri,而像 uCOS 这种使用的是 primask,详情请看下面整理的表格:

STM32 M3M4 MCU与FreeRTOS 中断优先级配置

STM32 M3M4 MCU与FreeRTOS 中断优先级配置

define configKERNEL_INTERRUPT_PRIORITY

宏定义 configLIBRARY_LOWEST_INTERRUPT_PRIORITY的数值经过 4bit偏移后得到一个 8bit
的优先级数值,即宏定义 configKERNEL_INTERRUPT_PRIORITY 的数值。这个 8bit 的数值才可以
实际赋值给相应中断的优先级寄存器。
也许初学者有疑问了,为什么前面 NVIC 配置的时候不是 8bit 的方式进行配置?这是因为 ST 的
库函数 NVIC_Init()已经为我们做好了。 这里的宏定义数值是供 PendSV 和 SysTick 中断进行优先级
配置的。 比如:我们这里配置宏定义 configLIBRARY_LOWEST_INTERRUPT_PRIORITY 是 0x0f,经
过 4bit 偏移后就是 0xf0,即 SysTick 和 PendSV 的中断优先级就是 240。

define configMAX_SYSCALL_INTERRUPT_PRIORITY

宏定义 configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 的数值经过 4bit 偏移后得到一
个 8bit 的优先级数值,即宏定义 configMAX_SYSCALL_INTERRUPT_PRIORITY 的数值。 这个数值
是赋值给寄存器 basepri 使用的,8bit 的数值才可以实际赋值给相应中断的优先级寄存器。
这里的宏定义数值赋给寄存器 basepri 后就可以实现全局的开关中断操作了。 比如:我们这里配
置宏定义 configLIBRARY_LOWEST_INTERRUPT_PRIORITY 是 0x01,经过 4bit 偏移后就是 0x10,
即 16。 调用了 FreeRTOS 的关中断后,所有优先级数值大于等于 16 的中断都会被关闭。优先级数值
小于 16 的中断不会被关闭,对寄存器 basepri 寄存器赋值 0,那么被关闭的中断会被打开。

上面的优先级数值,240和16,是十进制数,是真正8bit的数值,但是ST给我们了库函数,我们只配置4-7位,就可以了,其实就在配置这4-7位为0xf,表示优先级为15,实际十进制为240,配置这4-7位为 0x1,表示优先级为1,实际十进制为16.不要混淆了。
NOTE:

这里configMAX_SYSCALL_INTERRUPT_PRIORITY的优先级是个8bit的,之前的configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY是4bit,注意有没有LIBRARY。

结合实例说明一下:假定设置中断优先级组为2,然后设置

中断3(RTC_WKUP中断)的抢占优先级为2,响应优先级为1.

中断6(外部中断0)的抢占优先级为3,响应优先级为0。

中断7(外部中断1)的抢占优先级为2,响应优先级为0。

那么这3个中断的优先级顺序为:中断7>中断3>中断6。
上面例子中的中断3和中断7都可以打断中断6的中断。而中断7和中断3却不可以相互中断。

级为1.

中断6(外部中断0)的抢占优先级为3,响应优先级为0。

中断7(外部中断1)的抢占优先级为2,响应优先级为0。

那么这3个中断的优先级顺序为:中断7>中断3>中断6。
上面例子中的中断3和中断7都可以打断中断6的中断。而中断7和中断3却不可以相互中断。

Original: https://blog.csdn.net/xushx_bigbear/article/details/127815784
Author: 悟空胆好小
Title: STM32 M3M4 MCU与FreeRTOS 中断优先级配置

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/653021/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球