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

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

相关推荐
hollq1 小时前
STM32F103RCT6+STM32CubeMX+keil5(MDK-ARM)+Flymcu实现串口重定向
arm开发·stm32·嵌入式硬件
小鱼儿电子3 小时前
17-基于STM32的宠物饲养系统设计与实现
stm32·嵌入式硬件·物联网·宠物·宠物饲养系统
小莞尔4 小时前
【51单片机】【protues仿真】基于51单片机四层电梯系统
单片机·嵌入式硬件
F133168929575 小时前
WD5030A,24V降5V,15A 大电流,应用于手机、平板、笔记本充电器
stm32·单片机·嵌入式硬件·51单片机·硬件工程·pcb工艺
易享电子6 小时前
基于单片机电器断路器保护器系统Proteus仿真(含全部资料)
单片机·嵌入式硬件·fpga开发·51单片机·proteus
piaoroumi7 小时前
AM62X调试蓝牙
linux·arm开发·驱动开发
爱倒腾的老唐9 小时前
01、如何学习单片机
单片机·嵌入式硬件·学习
点灯小铭9 小时前
基于单片机的夹具压力控制系统设计
单片机·嵌入式硬件·mongodb·毕业设计·课程设计
雾削木15 小时前
stm32解锁芯片
javascript·stm32·单片机·嵌入式硬件·gitee
璞致电子17 小时前
fpga开发板ZYNQ 璞致 PZ7010/7020 邮票孔核心板简介-ZYNQ7000系列小系统学习板
linux·嵌入式硬件·学习·fpga开发·fpga·fpga开发板·xilinx开发板