Skip to content

feat(uno): add CPU fault/panic exception handlers#494

Open
radutta99 wants to merge 7 commits into
mainfrom
user/radutta/fw-exception-handlers
Open

feat(uno): add CPU fault/panic exception handlers#494
radutta99 wants to merge 7 commits into
mainfrom
user/radutta/fw-exception-handlers

Conversation

@radutta99

Copy link
Copy Markdown
Contributor

Summary

Adds azihsm_fw_uno_fault, a no_std crate that installs the Uno firmware's single #[panic_handler] plus overrides for the ARMv7-M HardFault and DefaultHandler exceptions.

Motivation

The default cortex-m-rt HardFault handler is a silent infinite loop. So when a bus fault occurs — for example a stray write to a read-only peripheral STATUS register (exactly the SHA/AES bug fixed in #488) — it escalates to HardFault and hangs the core with no output, making it painful to diagnose. These handlers make any future fault self-report on the serial console.

What it does

HardFault reads the SCB fault-status registers and dumps:

  • decoded CFSR fault class (MemManage / BusFault / UsageFault, per-bit),
  • the faulting address BFAR / MMFAR when the matching *VALID bit is set,
  • the stacked ExceptionFrame (R0–R3, R12, LR, PC, xPSR) and MSP,
  • a dedicated stack-overflow path (HFSR.FORCED + CFSR.MSTKERR), where the frame is unreliable and only MSP is reported.

panic emits the panic location and message.

DefaultHandler reports the offending exception/IRQ number so an unexpected interrupt is no longer silent.

Output goes through a small UART sink that is always compiled (so diagnostics appear even in trace-disabled production builds) and is named transport-agnostically so it can later route to the HSP debug-log channel without touching call sites.

Features

  • semihosting — issue SYS_EXIT(-1) on fault so the emulator host stops.
  • fault-stackdump — dev-only raw stack hexdump appended to the HardFault report (default dump is the minimalist register/CFSR report, mirroring the mcr-hsm handlers).

Wiring

The app depends on the crate and force-links it via use azihsm_fw_uno_fault as _; (the panic-halt pattern); the panic handler is moved out of app/src/main.rs, and the semihosting feature is routed through the crate.

Scope

Deliberately a CPU-fault reporter. Cross-core crash notification, persistent crash dumps, and peripheral-error ISRs (present in the mcr-hsm exception-handlers crate) depend on infrastructure the Uno port does not yet have (Tcon mailbox, crashdump store) and are out of scope here.

Testing

Builds in all three configs (default/no-trace, trace-uart, trace-uart,fault-stackdump). Validated on the Manticore EVB by deliberately triggering faults with trace-uart enabled and confirming the decoded dump on COM6:

  • Bus fault (write to RO register): BusFault: IMPRECISERR … (BFAR unreliable), HFSR FORCED — i.e. the previously-silent hang now produces a full dump.
  • Undefined instruction (udf): UsageFault: UNDEFINSTR, with a precise PC pointing exactly at the faulting instruction in the disassembly.

Note: imprecise (buffered-store) bus faults leave BFAR/PC unreliable; setting ACTLR.DISDEFWBUF would make them precise — a possible follow-up.

Introduce `azihsm_fw_uno_fault`, a no_std crate that installs the
firmware's single `#[panic_handler]` plus overrides for the ARMv7-M
`HardFault` and `DefaultHandler` exceptions.

Previously the default cortex-m-rt HardFault handler was a silent
infinite loop, so a bus fault (e.g. a stray write to a read-only
peripheral STATUS register) escalated to HardFault and hung the core
with no output. The new HardFault handler reads the SCB fault-status
registers and dumps the decoded CFSR fault class, the faulting address
(BFAR/MMFAR when valid), the stacked register frame, and MSP, with a
dedicated stack-overflow path (HFSR.FORCED + CFSR.MSTKERR).

Output goes through a generic fault sink (the SoC UART today, a blocking
busy-poll MMIO path safe to call from fault context) that is compiled
unconditionally, so diagnostics appear even in production builds shipped
without a trace backend. The sink is named generically so it can later
route to the HSP debug-log channel without touching call sites.

- crates/fault: lib.rs (handlers), sink.rs (FaultWriter + print_fault!),
  decode.rs (CFSR bit decoding)
- Features: `semihosting` (SYS_EXIT on fault for the emulator),
  `fault-stackdump` (dev-only raw stack hexdump; default dump is the
  mcr-hsm-style minimalist register report)
- app: depend on the crate, force-link via `use ... as _;`, move the
  panic handler out of main.rs, route `semihosting` through the crate

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 27, 2026 18:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a dedicated no_std Uno firmware crate (azihsm_fw_uno_fault) that provides the firmware-wide panic handler plus HardFault and DefaultHandler overrides, emitting fault diagnostics through an always-compiled output sink. This replaces the previous app-local panic handler and wires feature flags through the app to support semihosting termination and an optional dev stack dump.

Changes:

  • Introduce azihsm_fw_uno_fault with panic + exception handlers and CFSR decoding.
  • Add a minimal “fault-time” sink (currently UART) plus print_fault!/println_fault! formatting macros.
  • Wire the new crate into the Uno firmware workspace and app (dependency + feature passthrough; remove app-local panic handler).

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
fw/plat/uno/fw/crates/fault/src/sink.rs Adds a UART-backed, always-compiled fault output sink and formatting macros.
fw/plat/uno/fw/crates/fault/src/lib.rs Implements panic, HardFault, and DefaultHandler reporting + optional stack dump.
fw/plat/uno/fw/crates/fault/src/decode.rs Decodes SCB CFSR bits into readable per-fault lines.
fw/plat/uno/fw/crates/fault/Cargo.toml Defines the new crate and its semihosting / fault-stackdump features.
fw/plat/uno/fw/Cargo.toml Registers the new crate as a workspace member + dependency.
fw/plat/uno/fw/app/src/main.rs Force-links the fault crate and removes the app-local panic handler.
fw/plat/uno/fw/app/Cargo.toml Adds the fault crate dependency and routes semihosting / fault-stackdump features.

Comment thread fw/plat/uno/fw/crates/fault/src/lib.rs
Comment thread fw/plat/uno/fw/crates/fault/src/lib.rs
radutta99 and others added 2 commits June 27, 2026 19:22
- Treat a BusFault stacking error (CFSR.STKERR) as well as MSTKERR as an
  "exception frame unreliable" condition: if exception-entry stacking
  fails with a BusFault that escalates to HardFault, the pushed register
  frame is invalid and formatting it could fault again.
- Align the stack_dump base address down to a 4-byte boundary before
  forming the *const u32, avoiding UB when sp is corrupted/misaligned.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 27, 2026 19:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Comment thread fw/plat/uno/fw/crates/fault/src/sink.rs
Comment thread fw/plat/uno/fw/crates/fault/src/lib.rs
radutta99 and others added 2 commits June 27, 2026 20:14
- FaultWriter now writes through semihosting SYS_WRITE0 when the
  `semihosting` feature is enabled, instead of the SoC UART. The emulator
  does not model the UART, where write_byte would spin forever on
  STATUS.TX_READY (or fault on unmapped MMIO), stalling the report before
  SYS_EXIT. Silicon builds keep writing the UART directly. Mirrors the
  trace backend's backend-uart / backend-semihosting selection.
- Pass u32::MAX (instead of `-1i32 as u32`) to sys_exit for clarity.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
cortex-m-rt requires these exception handlers to be unsafe fn; satisfy clippy::missing_safety_doc (-D warnings) with a # Safety section. Also note STKERR alongside MSTKERR in the HardFault doc.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 28, 2026 01:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Comment thread fw/plat/uno/fw/crates/fault/src/sink.rs
Comment thread fw/plat/uno/fw/crates/fault/src/lib.rs
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 28, 2026 01:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Comment thread fw/plat/uno/fw/crates/fault/src/sink.rs
Comment thread fw/plat/uno/fw/crates/fault/src/sink.rs
Use the UART driver write(&str) (filters non-printable bytes to 0xFE) instead of write_bytes() so control chars/embedded NUL do not garble fault logs. Reference the public \::FaultWriter re-export from the exported print_fault!/println_fault! macros instead of the private sink module, so downstream callers do not hit a privacy error.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants