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. 测试五

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

相关推荐
python_use1 小时前
充电管理芯片
单片机·嵌入式硬件
Industio_触觉智能2 小时前
瑞芯微RK3568鸿蒙开发板OpenHarmony系统修改cfg文件权限方法
嵌入式硬件·openharmony·开源鸿蒙·瑞芯微rk3568
Q行天下2 小时前
x86的Docker环境下载ARM版容器镜像
arm开发·docker·容器
小朱在敲代码3 小时前
IIC 协议
单片机·嵌入式硬件
iot王国的战士4 小时前
合宙Air201资产定位模组LuatOS入门课程:FOTA远程升级,点点鼠标就搞定
嵌入式硬件·物联网·硬件工程
Whappy0014 小时前
51单片机-DS1302(实时时钟+可调时钟)(可参考主页上一节内容介绍)
单片机·嵌入式硬件·51单片机
百里与司空5 小时前
HAL库学习梳理——SPI
stm32·嵌入式硬件
iot王国的战士7 小时前
合宙Air201资产定位模组LuatOS:开机容易关机难?PWRKEY控制来帮忙
嵌入式硬件·物联网·硬件工程
m0_739312878 小时前
【STM32】独立看门狗(IWDG)原理详解及编程实践(下)
stm32·单片机·嵌入式硬件