Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Interrupts And Exceptions Baremetal

ASecurity

Use when writing Cortex-M NVIC ISRs, configuring priorities, handling HardFault, tail-chaining, or measuring interrupt latency. Not for the vector table itself: use baremetal-startup.

54 stars
0 votes
0 copies
1 views
Added 9/20/2026
ai-agents

Security Analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned 9/20/2026

$npx -y skills add OutlineDriven/outline-driven-development --skill interrupts-and-exceptions-baremetal --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Interrupts And Exceptions Baremetal?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Interrupts And Exceptions Baremetal
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/outlinedriven-interrupts-and-exceptions-baremetal-outline-driven-development/badge)](https://www.skillsdirectory.com/skills/outlinedriven-interrupts-and-exceptions-baremetal-outline-driven-development)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: interrupts-and-exceptions-baremetal
description: 'Use when writing Cortex-M NVIC ISRs, configuring priorities, handling HardFault, tail-chaining, or measuring interrupt latency. Not for the vector table itself: use baremetal-startup.'
---

# Interrupts and exceptions on bare metal

## Contract

| Field | Bound contract |
|---|---|
| Trigger | A peripheral interrupt must be enabled and prioritized, an ISR must share data with the main loop, a HardFault appears after interrupts are enabled, or interrupt latency must be measured or reduced on Cortex-M. |
| Authority | Read-only: emits NVIC configuration, ISR templates, fault-decoding code, and measurement steps to chat; the user places them in the firmware. Rollback is not needed because no file is written. No remote mutation. |
| Side effect | Chat output only. |
| Done | The IRQ is enabled with an explicit priority, the ISR clears its flag the way the reference manual states, shared data crosses the boundary through a critical section or a lock-free buffer, and fault decoding names the stacked PC and the fault status registers for the core. |

## Inputs

- Target core (Cortex-M0+, M3, M4, M7, M33) and the vendor CMSIS device header.
- The interrupt: NVIC number (`*_IRQn`), the peripheral flag that raises it, and how that flag clears.
- Priority relationships with other interrupts and with the scheduler tick, if any.
- For faults: whether a debugger is attached and which registers are readable.

## Procedure

1. State the exception flow. The NVIC compares the pending priority with the current one and with `PRIMASK` and `BASEPRI`; on entry the hardware stacks `r0` to `r3`, `r12`, `lr`, `pc`, and `xPSR`; it branches through the vector table; on return it unstacks, or tail-chains directly into the next pending exception without unstacking. Done when: the flow is stated as an ordered list.
2. Set the priority, then enable the interrupt. Lower numeric value means higher urgency on every Cortex-M. The number of implemented priority bits is vendor-specific (STM32 implements 4), and `NVIC_SetPriorityGrouping` splits them into preempt and sub-priority fields. Done when: the priority is written with `NVIC_SetPriority` before `NVIC_EnableIRQ`, and the relation to other interrupts is recorded.

   ```c
   #include "stm32f4xx.h"

   void uart_irq_init(void)
   {
       uint32_t group = NVIC_GetPriorityGrouping();
       NVIC_SetPriority(USART2_IRQn, NVIC_EncodePriority(group, 2, 0));
       NVIC_EnableIRQ(USART2_IRQn);
   }
   ```

3. Write the ISR to do the minimum and clear the source. Read the status register once, handle each flag that is set, and clear each flag the way the manual states: some clear on a data-register read, some clear on writing 1, some on writing 0. Hand data to the main loop through a ring buffer or a flag. No blocking calls, no `printf`, no `malloc`, no waiting loops. Done when: every flag the ISR handles has its clearing action in the body, and the ISR calls nothing that can block.

   ```c
   void USART2_IRQHandler(void)
   {
       uint32_t sr = USART2->SR;
       if (sr & USART_SR_RXNE) {
           ringbuf_push((uint8_t)USART2->DR);   /* reading DR clears RXNE */
       }
       if (sr & USART_SR_ORE) {
           (void)USART2->DR;                    /* SR read then DR read clears ORE */
       }
   }
   ```

4. Protect shared data with a critical section that restores the previous mask, so nesting works. Where only some interrupts must be held off, raise `BASEPRI` instead of `PRIMASK` (not available on Cortex-M0 and M0+). Keep the window short; a long masked window is the usual cause of missed deadlines elsewhere. Done when: every access to data the ISR also touches is inside a section, or the data structure is single-producer single-consumer with atomic indices.

   ```c
   uint32_t primask = __get_PRIMASK();
   __disable_irq();
   /* shared update */
   __set_PRIMASK(primask);
   ```

5. Install a HardFault handler that captures the faulting frame. The handler must be `naked`, because a compiler prologue would overwrite the stacked registers before they are read. Bit 2 of `lr` selects the main or process stack; the stacked PC is at index 6 and xPSR at index 7. Done when: a deliberate fault (a read from an unmapped address) stops in `hard_fault_c` with the PC of the faulting instruction.

   ```c
   __attribute__((naked)) 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 *frame)
   {
       volatile uint32_t pc  = frame[6];
       volatile uint32_t psr = frame[7];
       volatile uint32_t cfsr = SCB->CFSR;   /* ARMv7-M and later; absent on M0/M0+ */
       volatile uint32_t hfsr = SCB->HFSR;
       volatile uint32_t bfar = SCB->BFAR;   /* valid only when CFSR.BFARVALID is set */
       (void)pc; (void)psr; (void)cfsr; (void)hfsr; (void)bfar;
       for (;;) { }
   }
   ```

   Decode `CFSR` by its three bytes: memory management, bus fault, and usage fault. `HFSR.FORCED` means a lower-priority fault escalated. On Cortex-M0 and M0+ these registers do not exist; only the stacked PC is available.

6. Reduce latency where it matters. Done when: each row that applies has been acted on.

   | Factor | Effect | Action |
   |---|---|---|
   | Long ISR | Delays every lower and equal priority interrupt | Move work to the main loop through a buffer |
   | Long critical section | Delays every interrupt | Shorten the masked window; use `BASEPRI` |
   | Lazy FPU stacking (M4F, M7) | Extra stacking cycles when the ISR uses float | Keep float out of ISRs or accept the cost |
   | Priority order | A slow high-priority ISR starves the rest | Give the tightest deadline the highest priority |
   | Tail-chaining | Back-to-back exceptions skip unstack and restack | Free; no action, but do not rely on a gap between them |

7. Measure latency instead of estimating it. Toggle a GPIO at the top of the ISR and compare with the trigger on a scope, or read the DWT cycle counter. `DWT->CYCCNT` exists on ARMv7-M cores and needs `CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk` and `DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk` first. Done when: a latency number with its measurement method is recorded.

## Failure and recovery

| Symptom | Cause | Fix |
|---|---|---|
| Interrupt never fires | NVIC entry not enabled, `PRIMASK` set, or peripheral interrupt enable bit clear | `NVIC_EnableIRQ`; check `PRIMASK`; set the peripheral's interrupt enable. |
| ISR re-enters at once | Flag not cleared, or cleared the wrong way | Follow the manual's clearing action for that flag. |
| HardFault inside an ISR | Stack overflow, or an unaligned or unmapped access | Grow the stack; decode `CFSR` and `BFAR`. |
| Bytes lost under load | ISR too slow or too low in priority | Buffer in the ISR, raise its priority, shorten other ISRs. |
| Deadline missed elsewhere | Long critical section | Shrink the masked window or switch to `BASEPRI`. |

## Output

For the target interrupt: the priority and enable sequence, an ISR body with the correct flag clearing and a hand-off buffer, a critical-section pattern, a HardFault handler with the frame and fault-register decode available on the core, and a latency measurement method.

Attribution

OutlineDrivenOutlineDriven
View sourceSee grades on GitHubMore from OutlineDriven →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Caveman

Terse caveman voice: answer first, fluff gone, every technical fact kept. Use for /caveman, "caveman mode", "talk like caveman", "be brief", "less tokens". Stays on until "stop caveman" or "normal mode".

1100021 votes

Hyperplan

Adversarial multi-agent planning skill. Self-orchestrates 5 hostile category members (unspecified-low, unspecified-high, deep, ultrabrain, artistry) via team-mode for ruthless cross-critique debate, distills only the defensible insights, then MANDATORILY hands the distilled insight bundle to the `plan` agent for executable plan formalization. Use when planning needs maximum rigor and surfacing of weak assumptions, blind spots, and over-engineering. Triggers: 'hyperplan', 'hpp', '/hyperplan', ...

698621 votes

Writing Skills

Create and manage Claude Code skills in HASH repository following Anthropic best practices. Use when creating new skills, modifying skill-rules.json, understanding trigger patterns, working with hooks, debugging skill activation, or implementing progressive disclosure. Covers skill structure, YAML frontmatter, trigger types (keywords, intent patterns), UserPromptSubmit hook, and the 500-line rule. Includes validation and debugging with SKILL_DEBUG. Examples include rust-error-stack, cargo-dep...

3931 votes

Mcp Code Execution

Routes multi-tool workflows through MCP servers for large datasets and pipelines. Use when Bash tool overhead is limiting throughput on data-heavy tasks.

3421 votes

catchup

Recovers the conversation and failed tool calls of a previous Codex, Amp, Claude Code, Antigravity, Cline, Copilot CLI, Cursor, DeepSeek Harness, Grok Build, Kimi, OpenCode, Pi Agent, or ZCode session. Use when the user says "catch up", "what did the last session do", "get me up to speed", "I switched agents", asks to recover/summarize a previous session before continuing, or asks to diagnose or report a catchup failure. Do NOT use for the current conversation, git history, or any non-agent log.

741 votes
View all in ai-agents →