|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Single-region MPU read-only partition demo with fault recovery. More...
#include <stdint.h>#include "ra8_attributes.h"#include "ra8_board_ek_ra8d2.h"#include "ra8_boot_entry.h"#include "ra8_cgc.h"#include "ra8_err.h"#include "ra8_isr.h"#include "ra8_mpu.h"#include "ra8_time.h"Go to the source code of this file.
Enumerations | |
| enum | thumb_decode_t : uint16_t { k_thumb_hi5_shift = 11U , k_thumb_hi5_mask = 0x1FU , k_thumb2_prefix_11101 = 0x1DU , k_thumb2_prefix_11110 = 0x1EU , k_thumb2_prefix_11111 = 0x1FU } |
| Thumb-2 first-halfword decode constants. More... | |
| enum | mpu_simple_region_t : uint32_t { k_mpu_simple_region_size = 32U , k_mpu_simple_mair0_word = 0x000000FFU } |
| enum | mpu_simple_attr_t : uint8_t { k_mpu_simple_attr_normal_wb = 0xFFU , k_mpu_simple_probe_byte = 0x42U } |
| MAIR slot encoding + probe sentinel. More... | |
| enum | mpu_simple_timing_t : uint32_t { k_mpu_simple_period_ms = 1000U , k_mpu_simple_baud = 115200U } |
| Heartbeat cadence + UART line rate. More... | |
| enum | mpu_simple_frame_t : uint8_t { k_mpu_simple_frame_pc_idx = 6U } |
| Stacked-frame layout for an Armv8-M exception entry (no FP). More... | |
Functions | |
| static void | internal_mpu_simple_panic_halt (void) |
| Park the CPU after a fatal UART, clock, LED, or MPU setup failure. | |
| static void | internal_mpu_simple_setup_or_halt (void) |
| Bring CGC + SysTick + LEDs + the SCI8 console UART up. | |
| static ra8_err_t | internal_mpu_simple_probe (void) |
| Probe the RO region with a write – expected to fault on silicon. | |
| static void | internal_mpu_simple_fault_recover (uint32_t *frame) |
| Recovering MemManage handler. | |
| void | MemManage_Handler (void) |
| static void | internal_mpu_simple_emit_banner (void) |
| Emit the banner once after the recovering handler fires. | |
| void | main (void) |
| The application entry point Reset_Handler hands control to. | |
Variables | |
| static uint8_t | s_ro_buffer [k_mpu_simple_region_size] = {} |
| 32-byte aligned scratch buffer the RO region will cover. | |
| static volatile uint8_t | s_fault_pending = 0U |
| Set non-zero by the recovering MemManage handler so the main loop can emit the user-visible "fault handled" banner from thread context (the handler itself avoids UART I/O because SCI8 writes can block on TDR-empty). | |
| volatile uint32_t | g_mpu_simple_match = 0U |
| HIL liveness counter – incremented by main() on every loop iteration after the RO probe + fault-recovery sequence has completed at least once. | |
| volatile uint32_t | g_mpu_simple_fault_count = 0U |
| HIL diagnostic counter – incremented by the recovering MemManage handler every time the deliberate RO-write traps. | |
| static const ra8_mpu_region_t | s_regions [] |
| One-region RO descriptor covering s_ro_buffer. | |
| static const ra8_mpu_cfg_t | s_cfg |
| Aggregate MPU configuration handed to ra8_mpu_configure. | |
| static const uint8_t | s_mpu_simple_banner [] = "mpu: fault handled, recovered\r\n" |
| Greeting line for the "fault handled" banner. | |
Single-region MPU read-only partition demo with fault recovery.
Bare-metal counterpart to threadx_mpu_partition_demo – no RTOS, no thread context, just one MPU region. The app:
The "fault handled" banner is the success signal for the HIL alive-mode UART scanner: the negative regex in scripts/hil/check_alive.sh does not match this phrase, and HIL_FAULT_EXPECTED=1 still requires the non-zero CFSR that the handler intentionally leaves latched.
Bare EK-RA8D2; no expansion board.
Definition in file main.c.
| enum mpu_simple_attr_t : uint8_t |
| enum mpu_simple_frame_t : uint8_t |
| enum mpu_simple_region_t : uint32_t |
| enum mpu_simple_timing_t : uint32_t |
| enum thumb_decode_t : uint16_t |
Thumb-2 first-halfword decode constants.
|
static |
Emit the banner once after the recovering handler fires.
Writes the fixed positive-recovery marker from thread context after the exception handler has deferred reporting through its flag.
Definition at line 388 of file main.c.
References ra8_board_uart_console_write(), RA8_INTERNAL, and s_mpu_simple_banner.
Referenced by main().
|
static |
Recovering MemManage handler.
Strong override of the weak MemManage_Handler trampoline in vector_table.c. Walks the exception stack frame (selected by the EXC_RETURN.SPSEL bit in LR on entry), inspects the half-word the stacked PC points at to decide whether the faulting store is the 16-bit or 32-bit Thumb encoding, advances the stacked PC by 2 or 4 bytes accordingly, bumps the fault counter, sets the thread-context banner flag, and returns. The exception-return mechanism then resumes execution past the offending store, and internal_mpu_simple_probe reads back 0x00 (the original buffer contents) and reports k_ra8_err_hw_error – which is the success signal here, not a real failure.
The MMFSR half-word of CFSR is intentionally LEFT LATCHED so the HIL alive-mode probe with HIL_FAULT_EXPECTED=1 continues to see CFSR != 0 as its positive proof that the fault fired. CFSR self-clears on the next chip reset.
The handler is __attribute__((naked)) and written in inline assembly so the unbounded compiler-generated prologue cannot clobber LR before we read EXC_RETURN.SPSEL, and so the function can perform a real exception return via bx lr rather than a synthesised C return.
| [in,out] | frame | Cortex-M exception frame whose stacked PC is advanced. |
frame addresses a complete writable basic exception frame. Definition at line 316 of file main.c.
References g_mpu_simple_fault_count, k_mpu_simple_frame_pc_idx, k_thumb2_prefix_11101, k_thumb2_prefix_11110, k_thumb2_prefix_11111, k_thumb_hi5_mask, k_thumb_hi5_shift, RA8_INTERNAL, and s_fault_pending.
|
static |
Park the CPU after a fatal UART, clock, LED, or MPU setup failure.
Retains the failing register and diagnostic state in a permanent WFI loop.
Definition at line 147 of file main.c.
References RA8_INTERNAL.
Referenced by internal_mpu_simple_setup_or_halt(), and main().
|
staticnodiscard |
Probe the RO region with a write – expected to fault on silicon.
| k_ra8_ok | The host/off-target store completed and read back. |
| k_ra8_err_hw_error | Silicon recovery skipped the protected store. |
Definition at line 257 of file main.c.
References k_mpu_simple_probe_byte, k_ra8_err_hw_error, k_ra8_ok, RA8_INTERNAL, and s_ro_buffer.
Referenced by main().
|
static |
Bring CGC + SysTick + LEDs + the SCI8 console UART up.
Adds ra8_board_uart_console_init to the original setup so the recovering MemManage handler can emit a "fault handled" banner (via the main loop, not from exception context) that the HIL alive-mode UART scanner picks up. PCLKA must be post-PLL at the point ra8_board_uart_console_init runs, so ra8_cgc_init is called first and the BSP-private BRR computation reads the live PCLKA value.
Definition at line 201 of file main.c.
References internal_mpu_simple_panic_halt(), k_mpu_simple_baud, k_ra8_board_led1, k_ra8_board_led2, k_ra8_board_led3, k_ra8_clock_id_cpuclk0, k_ra8_ok, ra8_board_led_init(), ra8_board_uart_console_init(), ra8_cgc_get_clock_hz(), ra8_cgc_init(), RA8_INTERNAL, and ra8_time_init().
Referenced by main().
| void main | ( | void | ) |
The application entry point Reset_Handler hands control to.
Returns void, not int. This is a freestanding image: there is no hosted C environment, no process and nothing to report an exit status to. ISO C fixes main at int only for a hosted implementation; for a freestanding one (C23 5.1.2.1) the startup function's name and type are implementation-defined, and this is that definition. Reset_Handler discards no value because there is none to discard, and if main ever does return, startup halts the CPU rather than resuming anything.
The firmware lane is compiled -ffreestanding (see cmake/ra8_add_app.cmake) and the flag and this signature travel together: without it both GCC and clang reject a non-int main (-Wmain / -Wmain-return-type). Do not remove one without the other.
That coupling is why the declaration sits behind __STDC_HOSTED__ == 0, which -ffreestanding sets and a hosted build does not. The guard is not defensive dressing: this header is reachable from host builds (the unit tests compile ra8_core natively), and an unguarded void main(void); makes every hosted translation unit that includes it fail with conflicting types for 'main' against its own ISO int main. The declaration therefore exists exactly where its contract does.
Hosted first-party code – everything under tests/ and tools/ – uses the ISO int main(...) contract instead, because it genuinely does run under an OS that reads the exit status. scripts/checks/check_entry_points.py holds each domain to its own contract (#707).
Declared here, once, for the same reason SystemInit is: every vector_table.c used to restate it as a local extern int32_t main(void);, sixteen copies that no compiler ever compared against the definition – and roughly thirty of them had silently drifted out of agreement with the main they called.
The application entry point Reset_Handler hands control to.
Brings up CGC + BSP audio then plays blocks.
The application entry point Reset_Handler hands control to.
Brings up CGC + GPT triple, runs sweep.
The application entry point Reset_Handler hands control to.
Brings up clocks + UART + RMII pins, then ThreadX.
The application entry point Reset_Handler hands control to.
Brings up clocks + UART, then enters ThreadX.
The application entry point Reset_Handler hands control to.
Brings up LED, console, SDHI pins, then ThreadX.
The application entry point Reset_Handler hands control to.
Brings up CGC + USB-FS + UAC1, then enters the iso-IN feed loop forever.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
See file header.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
Definition at line 393 of file main.c.
References g_mpu_simple_match, internal_mpu_simple_emit_banner(), internal_mpu_simple_panic_halt(), internal_mpu_simple_probe(), internal_mpu_simple_setup_or_halt(), k_mpu_simple_period_ms, k_ra8_board_led1, k_ra8_board_led3, k_ra8_ok, ra8_board_led_on(), ra8_board_led_toggle(), ra8_delay_ms(), ra8_isr_globals_enable(), ra8_mpu_configure(), s_cfg, and s_fault_pending.
| volatile uint32_t g_mpu_simple_fault_count = 0U |
HIL diagnostic counter – incremented by the recovering MemManage handler every time the deliberate RO-write traps.
Expected steady-state value: 1 (the probe runs once before the main loop and the loop never re-arms it). Values > 1 indicate the handler failed to advance the stacked PC and the offending store re-executed on return.
Definition at line 135 of file main.c.
Referenced by internal_mpu_simple_fault_recover().
| volatile uint32_t g_mpu_simple_match = 0U |
HIL liveness counter – incremented by main() on every loop iteration after the RO probe + fault-recovery sequence has completed at least once.
Read externally by scripts/hil/jlink_memprobe.sh via SWD (when the app uses jlink_memprobe mode) and additionally readable when the harness uses HIL_MODE=alive with HIL_FAULT_EXPECTED=1 – in the latter case the alive check still passes (CycleCnt advances + PC is in code region + no negative UART banner) and this counter supplements the proof by demonstrating execution continued past the deliberately-triggered MPU fault.
Definition at line 121 of file main.c.
Referenced by main().
|
static |
Aggregate MPU configuration handed to ra8_mpu_configure.
|
static |
Set non-zero by the recovering MemManage handler so the main loop can emit the user-visible "fault handled" banner from thread context (the handler itself avoids UART I/O because SCI8 writes can block on TDR-empty).
Definition at line 101 of file main.c.
Referenced by internal_mpu_simple_fault_recover(), and main().
|
static |
Greeting line for the "fault handled" banner.
The negative regex in scripts/hil/check_alive.sh rejects FAIL|panic|NAK|ERROR|HardFault|MemFault|BusFault|UsageFault| stack overflow (case-insensitive, word-bounded). The lower- case word "fault" on its own (and "handled", "recovered") are all outside that set, so this banner reads as a positive signal to the HIL alive checker.
Definition at line 375 of file main.c.
Referenced by internal_mpu_simple_emit_banner().
|
static |
One-region RO descriptor covering s_ro_buffer.
Definition at line 155 of file main.c.
Referenced by emu_memmap_mram_base(), emu_memmap_regions(), and internal_map_regions().
|
static |
32-byte aligned scratch buffer the RO region will cover.
Definition at line 89 of file main.c.
Referenced by internal_mpu_simple_probe().