当前位置:网站首页>NVIC中断优先级管理
NVIC中断优先级管理
2022-07-07 06:26:00 【一只大喵咪1201】
作者:一只大喵咪1201
专栏:《STM32学习》
格言:你只管努力,剩下的交给时间!
描述
中断可以看作是一个事件。
比如,你正在家里学习,突然来了电话,你只能停下当前的学习去接电话,在接电话的过程中又有人敲门,你只好放下电话去开门,然后再拿起电话继续打电话,当挂掉电话后又继续前面的学习。
在上面的例子中,学习是一直在进行的事件,而打电话是一个中断事件,在打电话过程中有人敲门又是一个中断事件。
STM32中的中断也是这个道理,在执行主程序的过程中会有其他事件打断这个过程,进入到事件中的程序去执行,执行完中断程序后再返回主程序继续执行,这样就是中断。
🦔中断类型
- CM3内核支持256个中断,其中包含了16个内核中断和240个外部中断,并且具有256级的可编程中断设置。
- STM32F10系列并没有使用CM3内核的全部东西,而是只用了它的一部分。
- STM32F10系列有84个中断,包括16个内核中断和68个可屏蔽中断,具有16级可编程的中断优先级。
- STM32F103系列上面,又只有60个可屏蔽中断(在107系列才有68个)。
这里的外部中断和可屏蔽中断都是一个意思,是指不包括内核中断的所有中断。
此图便是本喵使用的STM32F103ZET6的60个外部中断。
中断优先级分组
有这么多类型的中断,是怎么管理的呢?STM32通分组的方式来管理这些中断。
该分组的设置是由 SCB->AIRCR 寄存器的 bit10~8 来定义的。
通过赋予SCB->AIRCR寄存器中第8位到第10位的值将这些中断类型分为5个组。
不同的分组中,AIRCR寄存器中的第4位到第8位管理优先级的情况不同。
比如常用的第2组,这4位中两位是管理抢占优先级的,两位是管理响应优先级的。按照从左到右的顺序。
这时又有疑惑了,抢占优先级和响应优先级是什么呢?
🦔抢占优先级和响应优先级
抢占优先级:
- 抢占优先级是指中断的打断优先级,抢占优先级高的中断可以打断正在执行的抢占优先级低的中断。
响应优先级
- 响应优先级是指中断的响应顺序,响应优先级只有在抢占优先级相同的情况下才有意义。当抢占优先级相同时,俩个中断同时发生,响应优先级高的中断先响应。
俩个优先级中,数字越小表示的优先级越高。
举例说明:
- 假定设置中断优先级组为2
- 然后设置
- 中断3(RTC中断)的抢占优先级为2,响应优先级为1。
- 中断6(外部中断0)的抢占优先级为3,响应优先级为0。
- 中断7(外部中断1)的抢占优先级为2,响应优先级为0。
那么的这三个中断的优先级顺序就是
- 中断7>中断3>中断6
当抢占优先级和响应优先级都相同的时候,哪个中断先发生就先执行哪个中断程序。
注意:
中断分组仅在系统的初始化完成后设置一次。如果在后面的程序中有修改分组就会混乱。
比如当使用的是2组的时候
优先级管理位如上图设置,此时的抢占优先级是2,响应优先级是2。
在使用这个分组后再将分组设置成3组的时候,此时抢占优先级是5,响应优先级是0。
如此一来,优先级的管理就混乱了。
🦔中断优先级分组函数
ST官方提供了设置分组的库函数,不用我们自己去挨个设置寄存器的值。
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
{
/* Check the parameters */
assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));
/* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */
SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
}
这是中断优先级分组的函数,他在ST官方固件库的misc.c源文件中。
通过函数的定义我们可以看到,它的实质就是在配置AIRCR寄存器。
#define NVIC_PriorityGroup_0 ((uint32_t)0x700) /*!< 0 bits for pre-emption priority 4 bits for subpriority */
#define NVIC_PriorityGroup_1 ((uint32_t)0x600) /*!< 1 bits for pre-emption priority 3 bits for subpriority */
#define NVIC_PriorityGroup_2 ((uint32_t)0x500) /*!< 2 bits for pre-emption priority 2 bits for subpriority */
#define NVIC_PriorityGroup_3 ((uint32_t)0x400) /*!< 3 bits for pre-emption priority 1 bits for subpriority */
#define NVIC_PriorityGroup_4 ((uint32_t)0x300) /*!< 4 bits for pre-emption priority 0 bits for subpriority */
以上5个宏定义就是中断优先级分组函数的入口参数,需要分成哪一组就将哪一组对应的参数传入函数中。
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
如此便将这60个外部中断分好了组。
中断优先级设置
虽然分好了组,方便管理了,但是具体是哪个中断发生,它的优先级是多少还需要进行具体的设置。
🦔中断优先级设置寄存器
typedef struct
{
__IO uint32_t ISER[8]; /*!< Offset: 0x000 Interrupt Set Enable Register */
uint32_t RESERVED0[24];
__IO uint32_t ICER[8]; /*!< Offset: 0x080 Interrupt Clear Enable Register */
uint32_t RSERVED1[24];
__IO uint32_t ISPR[8]; /*!< Offset: 0x100 Interrupt Set Pending Register */
uint32_t RESERVED2[24];
__IO uint32_t ICPR[8]; /*!< Offset: 0x180 Interrupt Clear Pending Register */
uint32_t RESERVED3[24];
__IO uint32_t IABR[8]; /*!< Offset: 0x200 Interrupt Active bit Register */
uint32_t RESERVED4[56];
__IO uint8_t IP[240]; /*!< Offset: 0x300 Interrupt Priority Register (8Bit wide) */
uint32_t RESERVED5[644];
__O uint32_t STIR; /*!< Offset: 0xE00 Software Trigger Interrupt Register */
} NVIC_Type;
在ST官方的固件库中的misc.h中定义了这样一个结构体,结构体的寄存器就是用来设置中断的优先级的。
- ISER[8]:ISER 全称是:Interrupt Set-Enable Registers,这是一个中断使能寄存器组。STM32F103 的可屏蔽中断只有 60 个,所以对我们来说,有用的就是两个(ISER[0]和 ISER[1]),总共可以表示 64 个中断。而 STM32F103 只用了其中的前 60 位。ISER[0]的 bit 0到31 对应中断0到31。ISER[1]的 bit 0到27 对应中断 32~59;这样总共 60 个中断就分别对应上了。你要使能某个中断,必须设置相应的 ISER 位为 1。
- ICER[8]:全称是:Interrupt Clear-Enable Registers,是一个中断除能寄存器组。该寄存器组与 ISER 的作用恰好相反,是用来清除某个中断的使能的。这里要专门设置一个 ICER 来清除中断位,而不是向 ISER 写 0 来清除,是因为 NVIC 的这些寄存器都是写 1 有效的,写 0 是无效的。
- ISPR[8]:全称是:Interrupt Set-Pending Registers,是一个中断挂起控制寄存器组。每个位对应的中断和 ISER 是一样的。通过置 1,可以将正在进行的中断挂起,而执行同级或更高级别的中断。写 0 是无效的。
- ICPR[8]:全称是:Interrupt Clear-Pending Registers,是一个中断解挂控制寄存器组。其作用与 ISPR 相反,对应位也和 ISER 是一样的。通过设置 1,可以将挂起的中断接挂。写 0 无效。
- IABR[8]:全称是:Interrupt Active Bit Registers,是一个中断激活标志位寄存器组。对应位所代表的中断和 ISER 一样,如果为 1,则表示该位所对应的中断正在被执行。这是一个只读寄存器,通过它可以知道当前在执行的中断是哪一个。在中断执行完了由硬件自动清零。
- IP[240]:全称是:Interrupt Priority Registers,是一个中断优先级控制的寄存器组。这个寄存器组相当重要STM32 的中断分组与这个寄存器组密切相关。STM32F103只用到了其中的前 60 个。IP[59]到IP[0]分别对应中断 59~0。而每个可屏蔽中断占用的 8bit 并没有全部使用,而是只用了高 4 位。这 4 位,又分为抢占优先级和响应优先级。抢占优先级在前,响应优先级在后。而这两个优先级各占几个位又要根据 SCB->AIRCR 中的中断分组设置来决定。
在ST官方的固件库的core_cm3.h中有几个库函数
static __INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn);
static __INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn);
static __INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn);
分别的作用是挂起某中断,读某中断状态,解除挂起的某中断。
🦔中断优先级初始化函数
ST官方同样提供了中断优先级的设置函数,不用我们去挨个设置寄存器。
typedef struct
{
uint8_t NVIC_IRQChannel; //设置中断通道
uint8_t NVIC_IRQChannelPreemptionPriority;//设置抢占优先级
uint8_t NVIC_IRQChannelSubPriority; //设置响应优先级
FunctionalState NVIC_IRQChannelCmd; //使能/使能
} NVIC_InitTypeDef;
在misc.h中定义了这样一个结构体,成员变量分别代表着
- 中断通道,也就是哪个类型的中断。
- 抢占优先级。
- 响应优先级。
- 中断使能。
而使用这个结构体和GPIO的使用方法类似
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;// 抢占优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;// 子优先级位2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据上面指定的参数初始化NVIC寄存器
以上便完成了中断优先级的初始化。
总结
在使用中断的时候
系统运行后先设置中断优先级分组。
调用函数:void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);整个系统执行过程中,只设置一次中断分组。针对每个中断,设置对应的抢占优先级和响应优先级。
调用函数:void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);如果需要挂起/解挂,查看中断当前激活状态,分别调用相关函数即可。
边栏推荐
- ncs成都新电面试经验
- OpenGL三维图形绘制
- Quick sorting (detailed illustration of single way, double way, three way)
- JS operation
- Esp32-ulp coprocessor low power mode RTC GPIO interrupt wake up
- [step on the pit] Nacos registration has been connected to localhost:8848, no available server
- Selenium automation integration, eight years of testing experience, soft test engineer, an article to teach you
- Synchronized underlying principle, volatile keyword analysis
- A bug using module project in idea
- Simulation volume leetcode [general] 1705 The maximum number of apples to eat
猜你喜欢
Markdown editor Use of MD plug-in
let const
【Istio Network CRD VirtualService、Envoyfilter】
PPT模板、素材下载网站(纯干货,建议收藏)
[Yugong series] February 2022 U3D full stack class 005 unity engine view
Greenplum 6.x build_ Environment configuration
Simple use of Xray
Calf problem
Greenplum6.x搭建_环境配置
Interpolation lookup (two methods)
随机推荐
How to realize sliding operation component in fast application
xray的简单使用
channel. Detailed explanation of queuedeclare parameters
Skills that testers must know: Selenium's three waiting ways are interpreted clearly
Explain Huawei's application market in detail, and gradually reduce 32-bit package applications and strategies in 2022
9c09730c0eea36d495c3ff6efe3708d8
LeetCode 736. LISP syntax parsing
GoLand set goproxy
Several common database connection methods
Speaking of a software entrepreneurship project, is there anyone willing to invest?
阿里p8手把手教你,自动化测试应该如何实现多线程?赶紧码住
Other 7 features of TCP [sliding window mechanism ▲]
Golang etcdv3 reports an error. The attribute in grpc does not exist
外部中断实现按键实验
Port occupation troubleshooting
实现自定义内存分配器
With an annual salary of 50W, Alibaba P8 will come out in person to teach you how to advance from testing
Unityshader introduction essentials personal summary -- Basic chapter (I)
年薪50w阿里P8亲自下场,教你如何从测试进阶
阿里p8推荐,测试覆盖率工具—Jacoco,实用性极佳