ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
nmi_exception.c File Reference

RA8D2/RA8P1 NMI handler – record the ICU cause instead of a bare trap. More...

#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_exception.h"
#include "ra8_icu_regs.h"
Include dependency graph for nmi_exception.c:

Go to the source code of this file.

Functions

static void internal_ra8_board_nmi_report (const ra8_exception_frame_t *frame)
 Read the ICU NMI cause and hand off to the common fault record.
void NMI_Handler (void)
 Cortex-M85 NMI handler (vector table slot 2).

Detailed Description

RA8D2/RA8P1 NMI handler – record the ICU cause instead of a bare trap.

Tag
[Ring 1 / Boot] {World: S}
Note
RA8P1 board layer (issue #226): this chip-boot TU is byte-identical to the EK-RA8D2 copy. The RA8P1 (R7KA8P1KFLCAC) shares the RA8D2 core, ICU, and register map (see libs/ra8_core/inc/ra8_device.h), so the NMI handling is common; the HUM citations reference the RA8D2 manual (R01UH1065EJ), which documents the byte-identical NMISR register.

The RA8D2 funnels its non-maskable interrupt sources through the ICU: IWDT/WDT underflow or refresh error, the PVD1/PVD2 voltage monitors, main/sub oscillation-stop detection, the NMI pin, bus errors, common/local memory (SRAM ECC) errors, CPU lockup, FPU exception, MRAM MRC/MRE read errors, and the inter-processor NMI. Which sources reach the core is chosen in NMIER; the latched cause lives in NMISR.

Historically every per-app vector_table.c weak-aliased NMI_Handler to Default_Handler – a bare bkpt + wfi trap – so the single most safety-relevant interrupt on the chip (the watchdog biting, an ECC error, a brown-out) produced zero diagnostics. The strong handler in this file overrides that weak alias tree-wide, exactly the way the shared SecureFault_Handler does:

  1. A naked trampoline picks the stack pointer the NMI interrupted (MSP if EXC_RETURN[2] = 0, PSP otherwise) and tail-calls internal_ra8_board_nmi_report().
  2. That reads the ICU NMISR cause register and forwards frame + cause into ra8_exception_report_nmi(), which snapshots both – plus the SCB diagnostics – into the fixed-SRAM g_ra8_exception_last record, best-effort logs them, and parks the CPU at a named halt symbol.

NMISR is deliberately NOT acknowledged (no NMICLR write): the handler never returns, and leaving the status latched preserves the evidence for a post-mortem debugger attach.

Definition in file nmi_exception.c.

Function Documentation

◆ internal_ra8_board_nmi_report()

void internal_ra8_board_nmi_report ( const ra8_exception_frame_t * frame)
static

Read the ICU NMI cause and hand off to the common fault record.

Runs as the C half of the NMI trampoline below (external linkage is required for the asm tail-branch to name it). Reads NMISR exactly once and forwards it, with the interrupted context's stacked frame, into ra8_exception_report_nmi(). The register is read here – not in libs/ra8_core – because NMISR is an RA8D2 ICU register, outside the ARM-architectural scope of the core exception module.

Parameters
[in]frameStacked exception frame the NMI entry pushed (selected MSP/PSP resident); forwarded verbatim.
Returns
Never returns.
Precondition
The Cortex-M85 has taken the NMI exception (IPSR == 2).
The ICU register block at 0x40006000 is accessible (always on).
Postcondition
g_ra8_exception_last carries exc_number 2 plus the NMISR cause.
Control never returns; the CPU halts at a named symbol.
Note
Not thread-safe (single NMI context by construction).
See also
ra8_exception_report_nmi() The recording + halt path.
Since
0.1.0

Definition at line 84 of file nmi_exception.c.

References ra8_exception_report_nmi(), and ra8_icu_nmisr().

◆ NMI_Handler()

void NMI_Handler ( void )

Cortex-M85 NMI handler (vector table slot 2).

Strong definition overriding the weak NMI_Handler alias in every per-app vector_table.c. Naked trampoline in the exact shape of the HardFault/MemManage/BusFault/UsageFault/SecureFault trampolines: tst lr, #4 selects the interrupted stack (MSP when EXC_RETURN[2] = 0, else PSP) into r0 and control tail-branches into internal_ra8_board_nmi_report(), which appends the ICU cause. Naked asm is required: only assembly can read EXC_RETURN and the banked stack pointers before the compiler touches any register.

Precondition
The Cortex-M85 has taken the NMI exception.
The C runtime stack selected by EXC_RETURN[2] holds the frame.
Postcondition
Control transfers to internal_ra8_board_nmi_report() and never returns.
The interrupted context's frame pointer is in r0.
Note
Runs only in NMI context and is not thread-callable.
Since
0.1.0

Definition at line 115 of file nmi_exception.c.