ARM32开发——(九)中断优先级Priority

1. NVIC中断控制器

NVIC(Nested Vectored Interrupt Controller)是一种嵌套式向量中断控制器,它是用于控制和管理嵌入式设备中的中断的硬件模块。NVIC可以自动地响应中断,并管理中断优先级、中断处理程序等,从而实现多个中断的快速、有序、有效地响应。

NVIC是通过对中断向量表的修改来处理中断的。在NVIC中,中断向量表是一个数组,存储了所有中断处理函数的地址。当一个中断触发时,处理器会在中断向量表中查找对应中断号的处理函数地址,并跳转到该地址执行对应中断的处理。

ARM系统的中断,内置的就是这种控制器。

2. 中断优先级

中断优先级分为抢占优先级,响应优先级和自然优先级

2.1 抢占优先级

抢占优先级用于确定在多个中断请求同时发生时,哪个中断可以中断当前正在执行的中断。具有更高抢占优先级的中断请求可以抢占 正在执行的较低抢占优先级的中断。这个机制允许高优先级的任务在需要时能够立即得到处理。

2.2 响应优先级

响应优先级用于确定中断请求被接收并开始执行的优先级。在多中断环境中,不同中断请求可能同时发生,系统需要根据响应优先级来决定哪个中断会首先得到处理。但响应优先级不会导致中断处理的打断,它仅在中断请求同时发生且抢占优先级相同时决定处理顺序。

2.3 自然优先级

自然优先级实际上是中断向量表的序号,序号越小优先级越高。

优先级的界定: 无论是抢占优先级还是响应优先级,都是用数值表示的,数值越小,优先级越高。

3. 优先级分组

优先级分组主要是说明抢占优先级和响应优先级的关系。

在ARM中,为了表示抢占优先级和响应优先级,仅用了4个Bit表示了优先级的等级。

|-------|------|----------|------|----------|
| 优先级分组 | 抢占优先级 || 响应优先级 ||
| 优先级分组 | 位数 | 范围 | 位数 | 范围 |
| 分组0 | 0bit | NONE | 4bit | [0,15] |
| 分组1 | 1bit | [0,1] | 3bit | [0,7] |
| 分组2 | 2bit | [0,3] | 2bit | [0,3] |
| 分组3 | 3bit | [0,7] | 1bit | [0,1] |
| 分组4 | 4bit | [0,15] | 0bit | NONE |

在代码中我们可以对全局进行中断优先级分组:

objectivec 复制代码
nvic_priority_group_set(NVIC_PRIGROUP_PRE0_SUB4);
nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);
nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
nvic_priority_group_set(NVIC_PRIGROUP_PRE3_SUB1);
nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);

对与具体的中断,我们可以进行配置抢占和响应优先级

objectivec 复制代码
nvic_irq_enable(xxx_irqn, 抢占优先级, 响应优先级);

4. 案例准备

  • 创建多个外部中断
  • 配置不同的中断优先级
  • 中断中进行耗时操作(不对的行为,仅仅是用来观察执行结果)
  • 比较中断执行

4.1 外部中断级别逻辑

4.1.1 中断初始化
objectivec 复制代码
static void EXTI0_config() {
    uint32_t extix = EXTI_0; // 哪个中断
    uint32_t extix_irq = EXTI0_IRQn;

    /********************* EXTI config *********************/
    // 时钟配置
    rcu_periph_clock_enable(RCU_SYSCFG);
    // 中断初始化
    exti_init(extix, EXTI_INTERRUPT, EXTI_TRIG_NONE);
    // 配置中断优先级
    nvic_irq_enable(extix_irq, 2, 1);
    // 使能中断
    exti_interrupt_enable(extix);
    // 清除中断标志位
    exti_interrupt_flag_clear(extix);
}
4.1.2 中断函数
objectivec 复制代码
void EXTI0_IRQHandler(void)
{
    if(SET == exti_interrupt_flag_get(EXTI_0)) {
        uint32_t i;
        for(i = 0; i < 10; i++) {
            printf("exti 0 : %d \r\n", i);
            delay_1ms(1000);
        }
    }
    // 清除中断标志位
    exti_interrupt_flag_clear(EXTI_0);
}

4.1.3 中断触发

objectivec 复制代码
exti_software_interrupt_enable(EXTI_0);

4.2 串口接收中断逻辑

objectivec 复制代码
if(data[0] == 0x00) {
    printf("0\r\n");
    exti_software_interrupt_enable(EXTI_0);
} else if(data[0] == 0x01) {
    printf("1\r\n");
    exti_software_interrupt_enable(EXTI_1);
} else if(data[0] == 0x02) {
    printf("2\r\n");
    exti_software_interrupt_enable(EXTI_2);
}

5. 测试一

|-------|---------|-------|-------|
| 中断类型 | 全局优先级分组 | 抢占优先级 | 响应优先级 |
| 串口接收 | 分组2 | 0 | 0 |
| 外部中断0 | 分组2 | 1 | 0 |
| 外部中断1 | 分组2 | 2 | 0 |
| 外部中断2 | 分组2 | 3 | 0 |

5.1 优先级配置

objectivec 复制代码
#define EXTI0_PRIORITY	1, 0
#define EXTI1_PRIORITY	2, 0
#define EXTI2_PRIORITY	3, 0

响应优先级相同,抢占优先级不同,测试不同的结果。

5.2 测试逻辑

通过串口,依次控制先执行 外部中断2,外部中断1,外部中断0,观察打印输出结果。

5.3 结论

  • 抢占优先级数值越小,优先级高
  • 抢占优先级高的中断,可以打断优先级低的,先执行,执行完成后,其他中断接着执行

6. 测试二

|-------|---------|-------|-------|
| 中断类型 | 全局优先级分组 | 抢占优先级 | 响应优先级 |
| 串口接收 | 分组2 | 0 | 0 |
| 外部中断0 | 分组2 | 2 | 0 |
| 外部中断1 | 分组2 | 2 | 1 |
| 外部中断2 | 分组2 | 2 | 2 |

6.1 优先级配置

objectivec 复制代码
#define EXTI0_PRIORITY	2, 0
#define EXTI1_PRIORITY	2, 1
#define EXTI2_PRIORITY	2, 2

应优先级相同,抢占优先级不同,测试不同的结果。

6.2 测试逻辑

通过串口,依次控制先执行 外部中断2,外部中断1,外部中断0,观察打印输出结果。

6.3 结论

  • 响应优先级数值越小,优先级高
  • 响应优先级高的中断,在中断排队时,享有更靠前的优先级

7. 测试三

|-------|---------|-------|-------|
| 中断类型 | 全局优先级分组 | 抢占优先级 | 响应优先级 |
| 串口接收 | 分组2 | 0 | 0 |
| 外部中断0 | 分组2 | 1 | 0 |
| 外部中断1 | 分组2 | 2 | 1 |
| 外部中断2 | 分组2 | 2 | 2 |

7.1 优先级控制

objectivec 复制代码
#define EXTI0_PRIORITY	1, 0
#define EXTI1_PRIORITY	2, 1
#define EXTI2_PRIORITY	2, 2

响应优先级相同,抢占优先级不同,测试不同的结果。

7.2 测试逻辑

通过串口,依次控制先执行 外部中断2,外部中断1,外部中断0,观察打印输出结果。

7.3 结论

  • 中断优先级中,抢占优先级优于响应优先级

8. 测试四

|-------|---------|-------|-------|
| 中断类型 | 全局优先级分组 | 抢占优先级 | 响应优先级 |
| 串口接收 | 分组2 | 0 | 0 |
| 外部中断0 | 分组2 | 2 | 0 |
| 外部中断1 | 分组2 | 2 | 0 |
| 外部中断2 | 分组2 | 2 | 0 |

8.1 优先级配置

objectivec 复制代码
#define EXTI0_PRIORITY	2, 0
#define EXTI1_PRIORITY	2, 0
#define EXTI2_PRIORITY	2, 0

响应优先级相同,抢占优先级不同,测试不同的结果。

8.2 测试逻辑

通过串口,依次控制先执行 外部中断2,外部中断1,外部中断0,观察打印输出结果。

8.3 结论

  • 抢占优先级和响应优先级相同时,比较自然优先级

9. 测试五

全局优先级分组和中断优先级冲突。

相关推荐
陌上花开缓缓归以17 小时前
phy降速自愈到100M重试流程分析
arm开发
凉、介18 小时前
ARM 总线技术 —— APB
arm开发·笔记·学习
物联网牛七七19 小时前
单片机中的中断
单片机·嵌入式硬件
Jerry丶Li1 天前
十九、STM32的TIM(十)(编码器)
stm32·单片机·嵌入式硬件
IT阳晨。1 天前
【STM32】串口通信及相关实验和项目
stm32·单片机·嵌入式硬件
安庆平.Я1 天前
STM32——IWDG
stm32·单片机·嵌入式硬件
太空1号1 天前
VxWorks入门小白菜鸟教程4 —— 异步I/O库(AIO)的使用
嵌入式硬件
怀民民民1 天前
轮询&中断 串口实训
单片机·嵌入式硬件·串口·中断·轮询·学习日志·keill
kaka❷❷1 天前
STM32 单片机 ESP8266 联网 和 MQTT协议
stm32·单片机·嵌入式硬件·物联网·mqtt·esp8266
古译汉书1 天前
Stm32江科大入门教程--各章节详细笔记---查阅传送门
数据结构·stm32·单片机·嵌入式硬件·算法