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

Default implementation of the fatal-error sink. More...

#include "ra8_error_handler.h"
#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_log.h"
Include dependency graph for ra8_error_handler.c:

Go to the source code of this file.

Functions

static void internal_disable_irq (void)
 Architectural __disable_irq: PRIMASK write.
static void internal_bkpt (void)
 Architectural __BKPT(0) wrapper.
static void internal_wfi (void)
 Architectural __WFI wrapper used inside the halt loop.
void ra8_fatal_error (const char *tag, const char *message, uint32_t err)
 Fatal-error trap: log and halt the system.

Detailed Description

Default implementation of the fatal-error sink.

Default implementation of ra8_fatal_error(). This function is called for every assertion failure and every failed RA8_ERROR_CHECK. It:

  1. Masks all maskable interrupts (__disable_irq).
  2. Logs the error via the standard ra8_log_error_val() path.
  3. Triggers a debugger breakpoint via __BKPT(0) so that an attached J-Link halts with the call stack intact.
  4. Drops into an infinite loop with __WFI so the CPU sleeps between interrupts (even though all maskable ones are off).

The function is marked __attribute__((weak)) so that field builds can override it to trigger a watchdog reset or a safety-halt recovery sequence without editing this file.

Definition in file ra8_error_handler.c.

Function Documentation

◆ internal_bkpt()

void internal_bkpt ( void )
inlinestatic

Architectural __BKPT(0) wrapper.

bkpt #0 halts execution when a debugger is attached. Without a debugger the instruction faults to the HardFault handler, which is acceptable – by the time we reach this function we have already decided that continuing is unsafe.

Precondition
Caller has already decided the firmware cannot continue.
Build is not RA8_OFF_TARGET (no-op on the host).
Postcondition
Execution halts under debugger; otherwise faults to HardFault.
Returns only if debugger steps over the BKPT.
Note
Single instruction; trivially thread-safe.
Since
0.1.0

Definition at line 76 of file ra8_error_handler.c.

References RA8_INTERNAL.

Referenced by ra8_fatal_error().

◆ internal_disable_irq()

void internal_disable_irq ( void )
inlinestatic

Architectural __disable_irq: PRIMASK write.

Inline assembly that sets PRIMASK.PM, masking every maskable interrupt at the NVIC level. Kept as a static inline here so ra8_error_handler.c does not pull in a full CMSIS dependency – it is intentionally self-contained so a failure in CMSIS init cannot prevent the fault handler from running.

Precondition
None – callable from any context, including a fault handler.
Build is not RA8_OFF_TARGET (no-op on the host).
Postcondition
PRIMASK.PM = 1 on the target; no-op on the off-target host.
No other CPU register is touched (clobber list is memory).
Note
Trivially thread-safe – single CPSID instruction.
Since
0.1.0

Definition at line 51 of file ra8_error_handler.c.

References RA8_INTERNAL.

Referenced by ra8_fatal_error().

◆ internal_wfi()

void internal_wfi ( void )
inlinestatic

Architectural __WFI wrapper used inside the halt loop.

Issues a wfi so the CPU drops into sleep until the next exception. Used inside the post-fault halt loop so the MCU is not burning power spinning.

The whole definition – not just its body – sits inside the on-target guard because the sole call site is the firmware halt loop below, which is itself compiled only off the fake path. A host build that kept an empty definition would carry a function nothing calls, which -Wunused-function reports.

Precondition
Build is not RA8_OFF_TARGET (the host does not compile this).
Called from the halt loop after IRQs have been masked.
Postcondition
CPU enters WFI sleep until any exception wakes it.
No register state modified.
Note
Single architectural instruction; trivially thread-safe.
Since
0.1.0

Definition at line 106 of file ra8_error_handler.c.

References RA8_INTERNAL.

Referenced by ra8_fatal_error().

◆ ra8_fatal_error()

void ra8_fatal_error ( const char * tag,
const char * message,
uint32_t err )

Fatal-error trap: log and halt the system.

Report a fatal error, log it, and halt.

Disables interrupts, emits a best-effort error line plus the numeric err code, then traps via BKPT and an infinite loop (or __builtin_trap on the off-target host so unit tests fail loudly instead of spinning forever).

Parameters
[in]tagNUL-terminated module/component tag.
[in]messageNUL-terminated short failure description.
[in]errNumeric error code (typically a ra8_err_t value).
Precondition
tag and message are non-NULL, NUL-terminated.
Interrupt state is recoverable from disabled (we never return).
Postcondition
Interrupts are masked.
Function does not return; control is trapped or loops forever.
Note
Weak symbol; downstream apps may override with a richer halt path.
Since
0.1.0

Definition at line 133 of file ra8_error_handler.c.

References internal_bkpt(), internal_disable_irq(), internal_wfi(), ra8_log_error, and ra8_log_error_val.

Referenced by _sbrk().