目录
一 ARM Cortex-M 微控制器中中断优先级分组的不同配置方式
三 ARM Cortex-M 处理器上设置不同的中断优先级分组
四 STM32 HAL_NVIC_SetPriorityGrouping设置优先级分组
1 HAL_NVIC_SetPriorityGrouping函数
HAL_NVIC_SetPriorityGrouping 函数
一 ARM Cortex-M 微控制器中中断优先级分组的不同配置方式
这张表格展示了 ARM Cortex-M 微控制器中中断优先级分组的不同配置方式。ARM Cortex-M 处理器的中断管理系统 NVIC(Nested Vectored Interrupt Controller)支持可配置的抢占优先级和子优先级,以便灵活地管理和调度中断事件。
在表中,列出了五种不同的优先级分组(NVIC_PriorityGroup_0 到 NVIC_PriorityGroup_4),每种分组定义了抢占优先级和子优先级的位数分配。抢占优先级决定了哪个中断可以打断正在执行的中断,而子优先级则用于确定同级别的中断之间的优先顺序。
优先级分组 | 抢占优先级 | 子优先级 | 优先级配置寄存器高 4 位 |
---|---|---|---|
NVIC_PriorityGroup_0 | 0 级抢占优先级 | 0-15 级子优先级 | 0bit 用于抢占优先级 4bit 用于子优先级 |
NVIC_PriorityGroup_1 | 0-1 级抢占优先级 | 0-7 级子优先级 | 1bit 用于抢占优先级 3bit 用于子优先级 |
NVIC_PriorityGroup_2 | 0-3 级抢占优先级 | 0-3 级子优先级 | 2bit 用于抢占优先级 2bit 用于子优先级 |
NVIC_PriorityGroup_3 | 0-7 级抢占优先级 | 0-1 级子优先级 | 3bit 用于抢占优先级 1bit 用于子优先级 |
NVIC_PriorityGroup_4 | 0-15 级抢占优先级 | 0 级子优先级 | 4bit 用于抢占优先级 0bit 用于子优先级 |
每个优先级分组的含义如下:
- NVIC_PriorityGroup_0:在这种配置下,只有 1 位用于抢占优先级,因此最多支持 2 种抢占优先级(0 和 1)。剩余的 4 位用于子优先级,这意味着可以有 16 种子优先级。总共有 32 种不同的中断优先级组合。
- NVIC_PriorityGroup_1:这种配置下,2 位用于抢占优先级,支持 4 种抢占优先级(0-3)。剩下的 3 位用于子优先级,支持 8 种子优先级。总共支持 32 种不同的中断优先级组合。
- NVIC_PriorityGroup_2:在这种配置下,3 位用于抢占优先级,支持 8 种抢占优先级(0-7)。剩下的 2 位用于子优先级,支持 4 种子优先级。总共支持 32 种不同的中断优先级组合。
- NVIC_PriorityGroup_3:这种配置下,4 位用于抢占优先级,支持 16 种抢占优先级(0-15)。剩下的 1 位用于子优先级,支持 2 种子优先级。总共支持 32 种不同的中断优先级组合。
- NVIC_PriorityGroup_4:在这种配置下,所有 4 位都用于抢占优先级,支持 16 种抢占优先级(0-15)。没有子优先级可用。总共支持 16 种不同的中断优先级组合。
通过调整优先级分组,可以根据实际需求平衡抢占优先级的数量和子优先级的数量。在某些情况下,可能需要更多的抢占优先级来区分不同的中断类型,而在其他情况下,可能需要更多的子优先级来微调同一抢占级别下的中断顺序。
二 实例
为了更好地理解中断优先级分组的工作原理,让我们来看一个简单的实例。假设我们有两个中断源:中断 A 和中断 B。我们想让中断 A 具有更高的抢占优先级,同时在抢占优先级相同的情况下,中断 B 应具有较高的子优先级。
首先,我们需要设置 NVIC 的优先级分组。在这个例子中,我们将使用 NVIC_PriorityGroup_2,因为它提供了足够的抢占优先级(8 个)和子优先级(4 个)。
接下来,我们将为中断 A 设置抢占优先级为 7(最高值),子优先级为 0。这样,A 的优先级表示为二进制形式为 11100000
(即 0xE0)。同样,我们将中断 B 的抢占优先级设为 0(最低值),子优先级设为 3。B 的优先级表示为二进制形式为 00011000
(即 0x18)。
现在,如果我们触发这两个中断,它们的优先级比较如下:
- 当中断 A 触发时,由于它的抢占优先级更高,处理器会立即响应中断 A,暂停当前正在执行的任务。
- 如果中断 B 在此期间触发,由于它的抢占优先级低于中断 A,处理器不会响应中断 B,直到完成中断 A 的处理。
- 当中断 A 处理完成后,如果中断 B 仍在等待,则处理器会响应中断 B,因为它们具有相同的抢占优先级,但是中断 B 的子优先级较高。
注意,在实际应用中,还需要设置中断使能和中断处理程序,这里只是简要说明中断优先级的概念。在 ARM Cortex-M 处理器中,可以使用 SCB->AIRCR
寄存器的 PRIGROUP 字段来设置优先级分组。此外,还需要使用 NVIC_SetPriority()
函数来设置中断的抢占优先级和子优先级。
三 ARM Cortex-M 处理器上设置不同的中断优先级分组
要在 ARM Cortex-M 处理器上设置不同的中断优先级分组,你需要修改系统的控制块(System Control Block,SCB)中的 AIRCR(Application Interrupt and Reset Control Register)寄存器。AIRCR 寄存器的 PRIGROUP 位用于指定中断优先级分组。以下是设置不同优先级分组的一般步骤:
- 获取 SCB 的地址:
1volatile uint32_t *SCB_AIRCR = (uint32_t *)0xE000ED0C; // Address of the AIRCR register
- 解析 PRIGROUP 位。PRIGROUP 位于 AIRCR 寄存器的第 8 位至第 10 位,共 3 位。这些位的值决定了抢占优先级和子优先级的位宽。计算公式如下:
1#define NVIC_PRIORITYGROUP_0 ((uint32_t)0x00000007) /*!< 0 bits for preemption priority, 4 bits for subpriority */
2#define NVIC_PRIORITYGROUP_1 ((uint32_t)0x00000006) /*!< 1 bits for preemption priority, 3 bits for subpriority */
3#define NVIC_PRIORITYGROUP_2 ((uint32_t)0x00000005) /*!< 2 bits for preemption priority, 2 bits for subpriority */
4#define NVIC_PRIORITYGROUP_3 ((uint32_t)0x00000004) /*!< 3 bits for preemption priority, 1 bit for subpriority */
5#define NVIC_PRIORITYGROUP_4 ((uint32_t)0x00000000) /*!< 4 bits for preemption priority, 0 bits for subpriority */
- 设置 PRIGROUP 位。例如,如果你想使用 NVIC_PriorityGroup_2,可以这样写:
1*SCB_AIRCR = (*SCB_AIRCR & ~(0x7 << 8)) | (NVIC_PRIORITYGROUP_2 << 8);
这段代码首先清除 PRIGROUP 位(使用按位 AND 操作),然后设置新的值(使用按位 OR 操作)。
- 重新加载 AIRCR 寄存器。为了使更改生效,必须触发复位序列。为此,可以设置 VECTKEY 字段(位于 AIRCR 寄存器的第 16 位至第 31 位)并将复位值设置为 0x5FA:
1*SCB_AIRCR = (*SCB_AIRCR & ~0xFFFF0000) | 0x5FA00;
完整的代码片段可能是这样的:
1volatile uint32_t *SCB_AIRCR = (uint32_t *)0xE000ED0C;
2
3void set_priority_grouping(uint32_t priority_group)
4{
5 switch(priority_group)
6 {
7 case NVIC_PRIORITYGROUP_0:
8 *SCB_AIRCR = (*SCB_AIRCR & ~(0x7 << 8)) | (NVIC_PRIORITYGROUP_0 << 8);
9 break;
10 case NVIC_PRIORITYGROUP_1:
11 *SCB_AIRCR = (*SCB_AIRCR & ~(0x7 << 8)) | (NVIC_PRIORITYGROUP_1 << 8);
12 break;
13 case NVIC_PRIORITYGROUP_2:
14 *SCB_AIRCR = (*SCB_AIRCR & ~(0x7 << 8)) | (NVIC_PRIORITYGROUP_2 << 8);
15 break;
16 case NVIC_PRIORITYGROUP_3:
17 *SCB_AIRCR = (*SCB_AIRCR & ~(0x7 << 8)) | (NVIC_PRIORITYGROUP_3 << 8);
18 break;
19 case NVIC_PRIORITYGROUP_4:
20 *SCB_AIRCR = (*SCB_AIRCR & ~(0x7 << 8)) | (NVIC_PRIORITYGROUP_4 << 8);
21 break;
22 default:
23 // Handle invalid input
24 break;
25 }
26
27 *SCB_AIRCR = (*SCB_AIRCR & ~0xFFFF0000) | 0x5FA00;
28}
这个函数接受一个参数 priority_group
,它可以是 NVIC_PRIORITYGROUP_0 到 NVIC_PRIORITYGROUP_4 之一。然后,函数根据输入的值设置相应的优先级分组,并触发复位序列。
请记住,这只是示例代码,实际实现可能会因编译器和目标硬件而异。在使用之前,请确保检查你的特定设备的参考手册以获取正确的寄存器映射和操作方法。
四 STM32 HAL_NVIC_SetPriorityGrouping设置优先级分组
1 HAL_NVIC_SetPriorityGrouping函数
HAL_NVIC_SetPriorityGrouping
函数是STM32 HAL库中的一个函数,用于设置嵌套向量中断控制器(NVIC)的优先级分组。NVIC是ARM Cortex-M微控制器的一部分,负责处理中断和异常。在STM32微控制器中,中断的优先级可以通过设置优先级分组来调整,以优化中断处理的效率和响应速度。
优先级分组的概念
在STM32中,每个中断都可以被分配一个优先级。但是,这个优先级实际上是由两部分组成的:抢占优先级(Preemption Priority)和子优先级(Subpriority 或 Sub-Priority)。这两部分优先级的具体位数是由程序员通过NVIC的优先级分组寄存器来配置的。
优先级分组是通过设置NVIC的AIRCR
(应用程序中断和复位控制寄存器)中的PRIGROUP
字段来实现的。PRIGROUP
字段决定了抢占优先级和子优先级的位数分配。例如,如果PRIGROUP
设置为0x04
,那么抢占优先级占用4位,而子优先级占用0位(这意味着没有子优先级)。
HAL_NVIC_SetPriorityGrouping 函数
HAL_NVIC_SetPriorityGrouping
函数正是用来设置这个PRIGROUP
字段的,从而定义抢占优先级和子优先级的位数分配。
函数原型通常如下所示(具体细节可能因HAL库版本而异):
c复制代码
HAL_StatusTypeDef HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup); |
-
参数:
PriorityGroup
是一个表示优先级分组的参数,其值定义了抢占优先级和子优先级的位数分配。这个参数的值是预定义的,通常与STM32的参考手册中描述的PRIGROUP
字段的值相对应。 -
返回值:函数返回一个
HAL_StatusTypeDef
枚举值,表示操作是否成功。成功时返回HAL_OK
,失败时返回错误代码。
使用示例
假设你想要将优先级分组设置为抢占优先级占3位,子优先级占1位(这对应于STM32F10x系列中的NVIC_PriorityGroup_4
),你可以这样调用HAL_NVIC_SetPriorityGrouping
函数:
c复制代码
if (HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4) != HAL_OK) | |
{ | |
// 错误处理 | |
} |
注意:NVIC_PRIORITYGROUP_4
是一个宏定义,代表了你想要的优先级分组设置。这个宏定义的值应该与你的STM32系列和HAL库版本相匹配。
总结
HAL_NVIC_SetPriorityGrouping
函数是STM32 HAL库中用于设置NVIC优先级分组的重要函数。通过调整抢占优先级和子优先级的位数分配,你可以根据需要优化中断处理的性能。正确设置优先级分组对于确保系统稳定运行和高效响应中断至关重要。
2 STM32微控制器中用于配置中断优先级分组--NVIC
NVIC(Nested Vectored Interrupt Controller,嵌套向量中断控制器)的NVIC_PriorityGroup
是STM32微控制器中用于配置中断优先级分组的一个重要概念。STM32将中断的优先级分为两部分:抢占优先级(Preemption Priority)和子优先级(Subpriority 或 Sub-Priority)。通过配置NVIC_PriorityGroup
,可以决定这两部分优先级各自占用的位数,从而灵活地调整中断处理的优先级策略。
STM32的NVIC_PriorityGroup
通常有以下几种配置(以STM32F1系列为例,不同系列可能有所不同,但基本概念相同):
- NVIC_PriorityGroup_0:
- 所有4位都用于指定响应优先级(Subpriority),没有抢占优先级(Preemption Priority)。
- 这意味着所有中断都不能抢占正在执行的中断,中断处理完全按照它们在中断向量表中的顺序进行。
- NVIC_PriorityGroup_1:
- 最高1位用于指定抢占优先级(Preemption Priority),最低3位用于指定响应优先级(Subpriority)。
- 这种分组方式允许高抢占优先级的中断打断低抢占优先级的中断,但在同一抢占优先级下,中断处理顺序仍由响应优先级决定。
- NVIC_PriorityGroup_2:
- 最高2位用于指定抢占优先级(Preemption Priority),最低2位用于指定响应优先级(Subpriority)。
- 相比Group_1,这种分组方式提供了更多的抢占优先级级别,适用于需要更细致中断优先级控制的应用场景。
- NVIC_PriorityGroup_3:
- 最高3位用于指定抢占优先级(Preemption Priority),最低1位用于指定响应优先级(Subpriority)。
- 在这种分组方式下,抢占优先级的级别更多,但响应优先级的级别较少。
- NVIC_PriorityGroup_4(在某些STM32系列中可能不存在,或命名有所不同):
- 假设存在此分组,则可能是所有4位都用于指定抢占优先级(Preemption Priority),没有响应优先级(Subpriority)。
- 这种极端情况允许最高级别的中断无条件地打断所有其他中断,但在实际应用中较为少见,因为缺乏响应优先级的区分可能会导致中断处理不够灵活。
注意:
- 上述分组方式的具体实现和命名可能因STM32系列和HAL库版本的不同而有所差异。因此,在编写代码时,应参考具体STM32系列的参考手册和HAL库文档。
NVIC_PriorityGroup
的设置通常在系统初始化阶段完成,并且一旦设置,就不建议更改,因为更改优先级分组可能会影响到已经配置好的中断优先级。- 在实际应用中,应根据系统需求合理选择优先级分组方式,以优化中断处理的性能和响应速度。