mcpField
I
interrupts-and-exceptions-baremetal

interrupts-and-exceptions-baremetal

github.com/mohitmishra786开发269319 次安装18 周前更新
代码仓库

关于 interrupts-and-exceptions-baremetal

面向处理 ARM Cortex-M 裸机中断的 Agent,提供实用操作指南。内容涵盖 NVIC 设置、ISR 约束、故障诊断与延迟权衡。

主要功能

  1. 01NVIC 配置与 IRQ 优先级
  2. 02编写非阻塞 ISR
  3. 03HardFault 与 BusFault 诊断
  4. 04临界区与中断屏蔽
  5. 05延迟与尾链分析

适用场景

  1. 01配置外设 IRQ 优先级
  2. 02排查启用中断后的 HardFault
  3. 03在 ISR 与主循环间传递数据
  4. 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