关于 interrupts-and-exceptions-baremetal
面向处理 ARM Cortex-M 裸机中断的 Agent,提供实用操作指南。内容涵盖 NVIC 设置、ISR 约束、故障诊断与延迟权衡。
主要功能
- 01NVIC 配置与 IRQ 优先级
- 02编写非阻塞 ISR
- 03HardFault 与 BusFault 诊断
- 04临界区与中断屏蔽
- 05延迟与尾链分析
适用场景
- 01配置外设 IRQ 优先级
- 02排查启用中断后的 HardFault
- 03在 ISR 与主循环间传递数据
- 04测量并优化中断延迟
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mohitmishra786/ low-level-dev-skills --skill interrupts-and-exceptions-baremetal安装后在 Claude Code 中输入/interrupts-and-exceptions-baremetal确认已加载。
详细介绍
中断与异常(裸机)
用途
指导 Agent 在 ARM Cortex-M 上处理裸机中断:NVIC 配置、ISR 编写规则、异常处理程序(HardFault、BusFault)、优先级分组、嵌套、尾链和延迟注意事项。
适用场景
- 配置外设 IRQ 优先级
- 编写不能阻塞的 ISR
- 启用中断后调试 HardFault
- 在 ISR 与主循环之间共享数据
- 优化中断延迟
工作流
1. NVIC 概览(Cortex-M)
Exception / IRQ flow
├── NVIC receives IRQ (priority compare with BASEPRI/PRIMask)
├── Stacking: automatic save r0-r3, r12, lr, pc, psr
├── Branch to handler from vector table
├── Handler runs (should be short)
└── Unstack and return — tail-chain if another IRQ pending
2. 启用 IRQ 并设置其优先级
#include "stm32f4xx.h" /* CMSIS device header */
void uart_irq_init(void) {
NVIC_SetPriority(USART2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 2, 0));
NVIC_EnableIRQ(USART2_IRQn);
}
优先级:数值越小,紧急程度越高(大多数 Cortex-M 实现如此)。优先级分组位请查阅厂商文档。
3. ISR 模板
void USART2_IRQHandler(void) {
if (USART2->SR & USART_SR_RXNE) {
uint8_t b = (uint8_t)USART2->DR; /* read clears RXNE */
ringbuf_push(b);
}
if (USART2->SR & USART_SR_ORE) {
(void)USART2->DR; /* clear overrun */
}
}
ISR 规则:
- 不要使用会阻塞的调用(
printf、malloc、长循环) - 尽量减少工作量——通过标志或环形缓冲区将任务延后到主循环处理
- 按照数据手册清除中断标志(读清除还是写 1 清除)
4. 临界区
uint32_t primask = __get_PRIMASK();
__disable_irq();
/* atomic section */
__set_PRIMASK(primask);
也可以提高 BASEPRI,只屏蔽低优先级 IRQ。
5. HardFault 处理程序
void HardFault_Handler(void) {
__asm volatile(
"tst lr, #4\n"
"ite eq\n"
"mrseq r0, msp\n"
"mrsne r0, psp\n"
"b hard_fault_c\n"
);
}
void hard_fault_c(uint32_t *stack) {
uint32_t r0 = stack[0];
uint32_t pc = stack[6];
uint32_t psr = stack[7];
/* log pc — GDB: info registers, bt */
while (1);
}
解码 CFSR/HFSR 寄存器,确定故障原因:
volatile uint32_t cfsr = SCB->CFSR;
volatile uint32_t hfsr = SCB->HFSR;
volatile uint32_t bfar = SCB->BFAR;
6. 延迟与尾链
| 因素 | 影响 |
|---|---|
| 更高优先级的 IRQ | 抢占低优先级 IRQ |
| 尾链 | 连续处理 IRQ 时跳过出栈/重新入栈 |
| FPU 上下文 | 延迟堆栈操作会增加 M4F/M7 上的延迟 |
| 较长的 ISR | 导致其他 IRQ 和主循环得不到执行 |
使用 GPIO 翻转和示波器,或 DWT 周期计数器(DWT->CYCCNT)进行测量。
7. Agent 使用示例
/interrupts-and-exceptions-baremetal Configure NVIC priority for UART vs SysTick
/interrupts-and-exceptions-baremetal Decode HardFault stacked PC with GDB
常见问题
| 症状 | 原因 | 修复方法 |
|---|---|---|
| IRQ 从未触发 | NVIC 未启用或 IRQ 被屏蔽 | NVIC_EnableIRQ;检查 PRIMASK |
| 异常重入 | 标志未清除 | 按照 RM 清除(ORE 需要读取 DR) |
| ISR 中发生 HardFault | 堆栈溢出 | 增大 _estack;检查 ISR 堆栈 |
| 字节丢失 | ISR 速度太慢 | 使用环形缓冲区并提高 IRQ 优先级 |
| 优先级反转 | 临界区过长 | 缩短 __disable_irq 屏蔽时间 |
相关技能
skills/baremetal/baremetal-startup— 向量表条目skills/baremetal/uart-serial-baremetal— UART IRQ 处理程序skills/embedded/openocd-jtag— 在 ISR 中设置 GDB 断点skills/debuggers/gdb— 检查故障堆栈帧skills/low-level-programming/assembly-arm— 故障处理程序汇编代码
评论
支持 Markdown