在 Cortex-M 架构中,中断响应的标准流程分为 5 步:
咬尾 / 晚到中断都是对「压栈 / 出栈」环节的优化,核心是减少重复的栈操作,降低中断延迟。
一、咬尾中断(Tail-Chaining)
1. 核心定义
当正在执行一个 ISR时,来了一个优先级更低或同级的中断请求,处理器不会等当前 ISR 执行完后 “出栈→再入栈”,而是直接复用已保存的栈帧,立刻执行新的 ISR,仅在最后执行一次出栈。
2. 执行流程图

3. 逐步骤拆解
假设场景:系统中有两个同级中断(优先级 2):UART_ISR(ISR1)、I2C_ISR(ISR2)
| 1 | 主程序运行中,触发 ISR1 | 中断控制器(NVIC)标记 ISR1 为 Pending |
| 2 | 硬件执行第一次压栈 | 保存主程序上下文到栈(PSR、PC、LR 等) |
| 3 | 跳转到 ISR1,执行 ISR1 代码 | 执行过程中,NVIC 检测到 ISR2 的 Pending 请求(同级) |
| 4 | ISR1 执行完毕 | 此时不执行 “出栈” 操作(核心优化点) |
| 5 | 直接跳转到 ISR2,执行 ISR2 代码 | 复用步骤 2 中已压栈的上下文,无重复压栈 |
| 6 | ISR2 执行完毕 | 硬件执行唯一一次出栈 |
| 7 | 恢复上下文,回到主程序 | 全程仅 1 次压栈 + 1 次出栈,比普通流程少 1 次压栈 + 1 次出栈 |
4. 核心优势
- 中断切换延迟降低:普通流程需要约 12 个时钟周期处理 “出栈 + 再压栈”,咬尾流程仅需 3 个时钟周期。
- 栈空间占用更少:无需重复保存上下文,减少栈开销。
二、晚到中断(Late-Arriving)
1. 核心定义
当处理器正在为低优先级中断执行压栈操作(还没进入 ISR)时,来了一个更高优先级的中断请求,处理器会先完成当前压栈,然后优先执行高优先级中断,执行完后再回头执行原低优先级中断,全程仅一次压栈。
2. 执行流程图

3. 逐步骤拆解(晚到流程)
假设场景:
- 低优先级中断 ISR_L(定时器,优先级 1)
- 高优先级中断 ISR_H(外部中断,优先级)
| 1 | 主程序运行中,触发 ISR_L | NVIC 标记 ISR_L 为 Pending |
| 2 | 硬件开始执行压栈操作 | 正在保存主程序上下文(还没完成压栈,也没进入 ISR_L) |
| 3 | 压栈过程中,NVIC 检测到 ISR_H 的 Pending 请求 | ISR_H 优先级更高,触发晚到中断机制 |
| 4 | 硬件完成当前压栈(不中断压栈) | 核心:先把上下文保存完,避免栈数据不完整 |
| 5 | 跳转到 ISR_H,执行 ISR_H 代码 | 高优先级中断插队执行(保证响应速度) |
| 6 | ISR_H 执行完毕 | 不执行出栈操作(核心优化点) |
| 7 | 直接跳转到 ISR_L,执行 ISR_L 代码 | 复用步骤 2/4 中已压栈的上下文 |
| 8 | ISR_L 执行完毕 | 硬件执行唯一一次出栈 |
| 9 | 恢复上下文,回到主程序 | 全程仅 1 次压栈 + 1 次出栈,比普通流程少 2 次压栈 + 2 次出栈 |
4. 核心优势
- 高优先级中断无额外延迟:不用等低优先级中断的压栈 / 出栈,直接插队,保证实时性。
- 避免栈数据混乱:先完成压栈再切换,不会出现栈帧不完整的问题。
三、咬尾 vs 晚到
| 触发阶段 | ISR执行中(已进入 ISR 函数) | 中断压栈中(未进入 ISR 函数) |
| 优先级关系 | 新中断 ≤ 当前执行的中断 | 新中断 > 正在压栈的中断 |
| 栈操作次数 | 1 次压栈 + 1 次出栈 | 1 次压栈 + 1 次出栈 |
| 执行顺序 | 先执行完当前 ISR,再执行新 ISR | 先执行高优先级新 ISR,再执行原低优先级 ISR |
| 典型场景 | 连续触发多个低 / 同级中断(如 UART+I2C) | 低优先级中断触发时,高优先级中断 “插队”(如定时器 + 外部中断) |







