interrupts-and-exceptions-baremetal について
ARM Cortex-Mのベアメタル割り込み処理をエージェント向けに案内します。NVIC設定、ISRの制約、障害診断、遅延の考慮事項を扱います。
主な機能
- 01NVIC設定とIRQ優先度
- 02ブロックしないISRの作成
- 03HardFaultとBusFaultの診断
- 04クリティカルセクションと割り込みマスク
- 05遅延とテールチェイニングの分析
活用シーン
- 01周辺機器のIRQ優先度設定
- 02割り込み有効化後のHardFault調査
- 03ISRとメインループ間のデータ共有
- 04割り込み遅延の測定と最適化
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ mohitmishra786/ low-level-dev-skills --skill interrupts-and-exceptions-baremetalインストール後、Claude Code で/interrupts-and-exceptions-baremetalを入力して読み込まれたか確認します。
詳細
割り込みと例外(ベアメタル)
目的
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. エージェントの使用例
/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 対応