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

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

相关推荐
漠落8 分钟前
STM32 SD卡拔插后FatFs挂载失败可能原因
stm32·单片机·嵌入式硬件
电鱼智能的电小鱼12 分钟前
产线视觉检测设备技术方案:基于EFISH-SCB-RK3588/SAIL-RK3588的国产化替代赛扬N100/N150全场景技术解析
linux·人工智能·嵌入式硬件·计算机视觉·视觉检测·实时音视频
Python小老六1 小时前
STC51系列单片机引脚分类与功能速查表(以STC89C52为例)
单片机·嵌入式硬件
MaoXian_n1 小时前
[IMX] 03.时钟树 - Clock Tree
arm开发·驱动开发·单片机·嵌入式硬件
茯苓gao2 小时前
电机控制储备知识学习(二) 电机的分类
嵌入式硬件·bldc电机学习
小智学长 | 嵌入式3 小时前
单片机-STM32部分:15、直流电机与步进电机 PWM/IO
stm32·单片机·嵌入式硬件
情意绵绵6744 小时前
车用CAN接口芯片:汽车神经系统的沉默构建者
单片机·嵌入式硬件·汽车·硬件架构·硬件工程
2401_859049084 小时前
MSPM0--Timer(一口一口喂版)
arm开发·单片机·mcu·算法
田园诗人之园5 小时前
ARM A64 LDR指令
arm开发·arm a64 ldr指令
xu_wenming5 小时前
华为Watch的ECG功能技术分析
人工智能·嵌入式硬件·算法