中断嵌套优先级配置

中断嵌套与优先级配置是嵌入式系统实时响应的核心机制。

一、中断嵌套原理

1. 触发条件

  • 优先级规则:高优先级中断可抢占低优先级中断(数值越小优先级越高,如ARM Cortex-M)。
  • 状态允许:当前中断服务程序(ISR)中全局中断使能(如ARM的PRIMASK已清除)。

2. 执行流程

1
2
3
4
5
6
7
8
9
10
11
低优先级ISR执行中...

高优先级中断触发

处理器自动保存当前上下文(压栈)

跳转至高优先级ISR

高优先级ISR执行完毕,恢复上下文

返回低优先级ISR继续执行

二、优先级配置方法(以ARM Cortex-M4为例)

1. 优先级分组

  • 寄存器SCB->AIRCR(应用程序中断及复位控制寄存器)

  • 分组模式:将8位优先级分为抢占优先级(Preemption)和子优先级(Subpriority)

    1
    2
    // 示例:选择优先级分组2(2位抢占,2位子优先级)
    NVIC_SetPriorityGrouping(2);
    AIRCR分组值 抢占优先级位数 子优先级位数
    0 0 4
    3 3 1

2. 设置中断优先级

  • 函数:

    1
    NVIC_SetPriority(IRQn, priority)
    1
    2
    // 设置UART中断抢占优先级1,子优先级0 → 优先级值 = (1 << (4 - 抢占位数)) | 子优先级
    NVIC_SetPriority(UART0_IRQn, 0x10 | 0x0); // 假设分组为2(抢占2位,子2位)

3. 关键代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void UART0_IRQHandler(void) {
// 低优先级中断(抢占优先级2)
// 处理UART数据...
}

void Timer1_IRQHandler(void) {
// 高优先级中断(抢占优先级1)
// 紧急任务处理...
}

int main() {
NVIC_SetPriorityGrouping(2); // 2位抢占,2位子优先级
NVIC_SetPriority(UART0_IRQn, 0x20); // 抢占优先级2(二进制10),子优先级0
NVIC_SetPriority(Timer1_IRQn, 0x10); // 抢占优先级1(二进制01),子优先级0
NVIC_EnableIRQ(UART0_IRQn);
NVIC_EnableIRQ(Timer1_IRQn);
__enable_irq(); // 使能全局中断
while(1);
}

三、中断嵌套深度与性能影响

1. 最大嵌套深度

  • 硬件限制:Cortex-M默认支持无限嵌套(受栈空间限制)。

  • 栈溢出风险:每次嵌套需保存上下文(如8个寄存器),深度嵌套可能导致栈溢出。

    1
    2
    3
    4
    // 计算最大安全嵌套深度
    #define STACK_SIZE 1024 // 假设栈大小1KB
    #define CONTEXT_SIZE 32 // 每个中断保存32字节上下文
    int max_nesting = STACK_SIZE / CONTEXT_SIZE; // 32层

2. 实时性优化

  • ISR短小化:高优先级ISR应少于10μs,避免阻塞低优先级任务。
  • 延迟处理:将耗时操作移至任务循环或低优先级中断。

四、实际应用案例(STM32F4)

1. 场景需求

  • 外部中断(按键):低优先级,响应用户输入。
  • PWM捕获中断:高优先级,精确测量电机转速。

2. 配置步骤

1
2
3
4
5
6
7
8
9
10
11
12
// 设置优先级分组为2位抢占,2位子优先级
NVIC_SetPriorityGrouping(2);

// 配置EXTI0中断(按键)抢占优先级3
NVIC_SetPriority(EXTI0_IRQn, 0x30); // 二进制11 | 00

// 配置TIM1捕获中断抢占优先级1
NVIC_SetPriority(TIM1_CC_IRQn, 0x10); // 二进制01 | 00

// 使能中断
NVIC_EnableIRQ(EXTI0_IRQn);
NVIC_EnableIRQ(TIM1_CC_IRQn);

3. 行为验证

  • 按键中断触发:进入EXTI0_IRQHandler

  • TIM1捕获中断触发:立即抢占,执行TIM1_CC_IRQHandler

  • 嵌套时序图:

    1
    2
    3
    4
    5
    6
    TIME    | EVENT
    --------------------------
    0ms | EXTI0_IRQHandler开始
    0.5ms | TIM1_CC中断触发,抢占
    1ms | TIM1_CC_IRQHandler结束
    1.5ms | EXTI0_IRQHandler恢复并结束

五、常见问题与调试

1. 中断不嵌套

  • 原因:未重新使能全局中断(如ARM中未清除PRIMASK)。
  • 解决:在低优先级ISR内调用__enable_irq()

2. 优先级反转

  • 场景:低优先级ISR占用共享资源,阻塞高优先级ISR。
  • 方案:使用临界区保护或优先级继承(如FreeRTOS的互斥量)。

3. 性能分析工具

  • 逻辑分析仪:抓取中断触发时序。
  • RTOS Trace:记录中断执行时间和嵌套深度。

六、对比总结

架构 优先级位数 自动嵌套 典型应用
ARM Cortex-M 4-8位可配置 支持 实时控制系统
AVR (Arduino) 2级固定 不支持 简单嵌入式设备
x86 APIC多级 支持 桌面/服务器

正确配置中断优先级和嵌套可提升系统实时性,但需权衡响应速度与资源消耗。