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

"MPU boot map brought up through the ra8_mpu HAL" self-test (#576) More...

#include <stddef.h>
#include <stdint.h>
#include "ra8_board_ek_ra8d2.h"
#include "ra8_boot_entry.h"
#include "ra8_cgc.h"
#include "ra8_err.h"
#include "ra8_log.h"
#include "ra8_mpu.h"
#include "ra8_system_regs.h"
Include dependency graph for main.c:

Go to the source code of this file.

Enumerations

enum  mpu_boot_config_t : uint32_t {
  k_mpu_boot_baud = 115200U ,
  k_mpu_boot_sckdivcr_exp = 0x32233432U ,
  k_mpu_boot_shram_base = 0x22100000U ,
  k_mpu_boot_shram_size = 0x000A0000U
}
 Compile-time scalar parameters for the MPU-via-HAL self-test. More...
enum  mpu_boot_region_idx_t : uint8_t { k_mpu_boot_idx_shram = 4U }
 Named indices into the canonical boot map region table. More...
enum  mpu_boot_result_t : uint8_t {
  k_mpu_boot_result_pass = 0U ,
  k_mpu_boot_result_fail_mpu = 1U ,
  k_mpu_boot_result_fail_map = 2U ,
  k_mpu_boot_result_fail_mmio = 3U
}
 Verdict of the self-test, naming which step failed (if any). More...

Functions

static void mpu_boot_wfi_forever (void)
 Park the Cortex-M85 forever in a WFI idle loop.
static bool mpu_boot_test_enabled (void)
 Step 1 – prove the MPU was enabled by the HAL boot path.
static bool mpu_boot_test_map (void)
 Step 2 – prove the canonical boot map (incl.
static bool mpu_boot_test_device_mmio (void)
 Step 3 – prove Device-nGnRE peripheral MMIO is accessible (region 3).
static mpu_boot_result_t mpu_boot_run_selftest (void)
 Run all three self-test steps in order, naming the first failure.
static bool mpu_boot_setup (void)
 Bring up the clock tree and the VCOM console for the banner.
static void mpu_boot_emit (const uint8_t *line, size_t len)
 Emit one banner line over the VCOM console and flush it.
void main (void)
 Application entry: prove the MPU boot map came up via the HAL.

Variables

static const uint8_t k_mpu_boot_pass_banner [] = "mpu_boot_map_hal: mpu-via-hal PASS\r\n"
 Deterministic one-shot HIL success banner (uart_scrape gate).
static const uint8_t k_mpu_boot_fail_setup [] = "mpu_boot_map_hal: setup FAIL\r\n"
 Failure banner: clock / console bring-up failed before the self-test.
static const uint8_t k_mpu_boot_fail_mpu [] = "mpu_boot_map_hal: mpu-disabled FAIL\r\n"
 Failure banner: ra8_mpu_is_enabled() reported the MPU is off.
static const uint8_t k_mpu_boot_fail_map [] = "mpu_boot_map_hal: boot-map FAIL\r\n"
 Failure banner: the boot map region table was not the canonical map.
static const uint8_t k_mpu_boot_fail_mmio [] = "mpu_boot_map_hal: device-MMIO FAIL\r\n"
 Failure banner: the Device-nGnRE MMIO (region 3) readback mismatched.

Detailed Description

"MPU boot map brought up through the ra8_mpu HAL" self-test (#576)

Tag
[Ring 6 / APP] {World: S}

Single-core (Cortex-M85) demonstrator for issue #576. The app's build defines RA8_BOOT_ENABLE_CACHE_MPU (see CMakeLists.txt) and ships a per-app system_init.c whose SystemInit() installs the boot MPU memory-attribute map through the ra8_mpu HAL (ra8_mpu_apply_boot_map()) instead of the raw MAIR/RBAR/RLAR/CTRL pokes the shared board boot uses. It is the HAL-path twin of cache_mpu_hil (raw-poke path); the two boot files diff cleanly and can be compared on HIL.

Self-test (each step independent; runs once, then the core parks in WFI):

  1. MPU enabled via the HAL. ra8_mpu_is_enabled() must report the MPU is on – i.e. ra8_mpu_apply_boot_map() ran during boot and enabled it – without this app poking the MPU register block directly.
  2. Canonical boot map. ra8_mpu_boot_map() must expose the 5-region map, and region 4 must be the 640 KiB (non-power-of-two) Normal-non-cacheable shared M85<->M33 bank at 0x22100000 – the region a size-checked setter cannot express and the reason the boot map needs a dedicated HAL entry point.
  3. Device-nGnRE MMIO (MPU region 3, peripherals @ 0x40000000). Read the live SYSTEM SCKDIVCR register and confirm it reads back the value ra8_cgc_init() programmed (0x32233432) – proving the HAL-programmed peripheral region is mapped Device (not cached) and accessible.

On success the app emits "mpu_boot_map_hal: mpu-via-hal PASS\r\n" over the J-Link OB VCOM console (SCI8, PD02/PD03 @ 115200 8N1) and mirrors the verdict over ra8_log. On any mismatch it emits a distinct ... FAIL line (never containing "PASS") and parks in WFI so ra8_emulator's idle detector stops the run after the one-shot banner is scraped.

Author
Brighton Sikarskie
Date
2026-08-02
Since
0.1.0

Definition in file main.c.

Enumeration Type Documentation

◆ mpu_boot_config_t

enum mpu_boot_config_t : uint32_t

Compile-time scalar parameters for the MPU-via-HAL self-test.

Groups the console baud and the golden constants the self-test checks: the expected boot-map region count, the shared-SRAM region geometry, and the SYSTEM SCKDIVCR readback.

Since
0.1.0
Enumerator
k_mpu_boot_baud 

VCOM console line rate (8N1).

k_mpu_boot_sckdivcr_exp 

SCKDIVCR readback after ra8_cgc_init().

k_mpu_boot_shram_base 

Region 4 base (shared M85<->M33 SRAM).

k_mpu_boot_shram_size 

Region 4 size (640 KiB, not a power of 2).

Definition at line 66 of file main.c.

◆ mpu_boot_region_idx_t

enum mpu_boot_region_idx_t : uint8_t

Named indices into the canonical boot map region table.

Since
0.1.0
Enumerator
k_mpu_boot_idx_shram 

Shared M85<->M33 SRAM region.

Definition at line 78 of file main.c.

◆ mpu_boot_result_t

enum mpu_boot_result_t : uint8_t

Verdict of the self-test, naming which step failed (if any).

Drives the banner main() emits; k_mpu_boot_result_pass is the only value that produces the PASS line.

Since
0.1.0
Enumerator
k_mpu_boot_result_pass 

All three steps passed.

k_mpu_boot_result_fail_mpu 

MPU was not enabled by the HAL.

k_mpu_boot_result_fail_map 

Boot map region table was wrong.

k_mpu_boot_result_fail_mmio 

Device-MMIO (region 3) step failed.

Definition at line 89 of file main.c.

Function Documentation

◆ main()

void main ( void )

Application entry: prove the MPU boot map came up via the HAL.

The application entry point Reset_Handler hands control to.

Brings up logging, the clock tree, and the VCOM console, runs the three-step self-test (MPU enabled, canonical boot map, Device MMIO), emits the matching PASS / FAIL banner over the console and ra8_log, then parks in WFI.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit installed the boot map via ra8_mpu_apply_boot_map().
Postcondition
Exactly one banner (PASS or a step-specific FAIL) has been emitted.
The core is parked in WFI.
Note
Single-threaded; no RTOS and no IRQ sources in this template.
Since
0.1.0

Definition at line 373 of file main.c.

References k_mpu_boot_fail_map, k_mpu_boot_fail_mmio, k_mpu_boot_fail_mpu, k_mpu_boot_fail_setup, k_mpu_boot_pass_banner, k_mpu_boot_result_fail_map, k_mpu_boot_result_fail_mmio, k_mpu_boot_result_fail_mpu, k_mpu_boot_result_pass, mpu_boot_emit(), mpu_boot_run_selftest(), mpu_boot_setup(), mpu_boot_wfi_forever(), ra8_log_info, and ra8_log_init().

◆ mpu_boot_emit()

void mpu_boot_emit ( const uint8_t * line,
size_t len )
static

Emit one banner line over the VCOM console and flush it.

Writes line then drains the SCI8 TX so the bytes clock out before the core parks. A no-op if line is NULL or empty.

Parameters
[in]linePointer to the ASCII banner bytes (no NUL sent). Must be non-NULL for output.
[in]lenNumber of bytes to send; 0 sends nothing.
Returns
Nothing.
Precondition
line points to at least len readable bytes when len > 0.
mpu_boot_setup was attempted during bring-up.
Postcondition
The bytes have been handed to SCI8 and the TX FIFO drained (if up).
No application state is modified.
Note
Not thread-safe; single-threaded boot context.
Since
0.1.0

Definition at line 346 of file main.c.

References ra8_board_uart_console_flush(), and ra8_board_uart_console_write().

Referenced by main().

◆ mpu_boot_run_selftest()

mpu_boot_result_t mpu_boot_run_selftest ( void )
static

Run all three self-test steps in order, naming the first failure.

Steps are independent and short-circuit: the first failing step determines the verdict so main() can emit a step-specific FAIL banner.

Returns
The self-test verdict.
Return values
k_mpu_boot_result_passAll three steps passed.
k_mpu_boot_result_fail_mpuThe MPU-enabled step failed.
k_mpu_boot_result_fail_mapThe boot-map step failed.
k_mpu_boot_result_fail_mmioThe Device-MMIO step failed.
Precondition
The cache + MPU boot path is active (set by RA8_BOOT_ENABLE_CACHE_MPU).
ra8_cgc_init() has run (Device-MMIO step needs the programmed divider).
Postcondition
No persistent state is modified.
Exactly one verdict is returned.
Note
Not thread-safe; single-threaded boot context.
Since
0.1.0

Definition at line 282 of file main.c.

References k_mpu_boot_result_fail_map, k_mpu_boot_result_fail_mmio, k_mpu_boot_result_fail_mpu, k_mpu_boot_result_pass, mpu_boot_test_device_mmio(), mpu_boot_test_enabled(), and mpu_boot_test_map().

Referenced by main().

◆ mpu_boot_setup()

bool mpu_boot_setup ( void )
static

Bring up the clock tree and the VCOM console for the banner.

ra8_cgc_init() programmes the clock tree (and thereby the SCKDIVCR the Device-MMIO step checks); the EK-RA8D2 debug console (SCI8 on PD02/PD03 @ k_mpu_boot_baud) then comes up over the J-Link OB VCOM bridge.

Returns
Whether the clock + console are ready to carry the banner.
Return values
trueCGC and SCI8 console are up.
falseA bring-up step failed.
Precondition
Called once during M85 bring-up, before the self-test.
ra8_log_init() has run (failures are narrated over ITM).
Postcondition
On true SCI8 is enabled and PD02/PD03 route to it.
On false no console state persists.
Note
Not thread-safe; single-threaded boot context.
Since
0.1.0

Definition at line 315 of file main.c.

References k_mpu_boot_baud, k_ra8_ok, ra8_board_uart_console_init(), and ra8_cgc_init().

Referenced by main().

◆ mpu_boot_test_device_mmio()

bool mpu_boot_test_device_mmio ( void )
static

Step 3 – prove Device-nGnRE peripheral MMIO is accessible (region 3).

Reads the live SYSTEM SCKDIVCR register (peripheral window @ 0x40000000, mapped Device-nGnRE by boot-map region 3) and checks it equals the divider word ra8_cgc_init() programmed. A correct readback proves the HAL-programmed peripheral region is reachable and uncached.

Returns
Whether the SYSTEM register read back the post-init value.
Return values
trueSCKDIVCR read back 0x32233432.
falseThe read returned 0 (dead bus) or a value other than expected.
Precondition
ra8_cgc_init() has programmed SCKDIVCR earlier this boot.
The boot map maps the peripheral window Device-nGnRE (region 3).
Postcondition
No register is modified (pure read).
On true the peripheral MMIO path is proven accessible and uncached.
Note
Not thread-safe; single-threaded boot context.
Since
0.1.0

Definition at line 249 of file main.c.

References k_mpu_boot_sckdivcr_exp, and ra8_sys_sckdivcr().

Referenced by mpu_boot_run_selftest().

◆ mpu_boot_test_enabled()

bool mpu_boot_test_enabled ( void )
static

Step 1 – prove the MPU was enabled by the HAL boot path.

Queries ra8_mpu_is_enabled(). A true result means the per-app SystemInit() called ra8_mpu_apply_boot_map() and the MPU is live – all without this app touching the MPU register block directly.

Returns
Whether the MPU is enabled.
Return values
truera8_mpu_is_enabled() reported the MPU on.
falseThe MPU is off (apply_boot_map did not run or failed).
Precondition
The cache + MPU boot path is active (RA8_BOOT_ENABLE_CACHE_MPU).
ra8_mpu_apply_boot_map() ran during SystemInit().
Postcondition
No state is modified (pure query).
On true the MPU is proven enabled.
Note
Not thread-safe; single-threaded boot context.
Since
0.1.0

Definition at line 181 of file main.c.

References ra8_mpu_is_enabled().

Referenced by mpu_boot_run_selftest().

◆ mpu_boot_test_map()

bool mpu_boot_test_map ( void )
static

Step 2 – prove the canonical boot map (incl.

the non-pow2 region 4).

Reads the driver-owned boot map via ra8_mpu_boot_map() and checks it has k_ra8_mpu_boot_region_count regions and that region 4 is the 640 KiB Normal-non-cacheable shared M85<->M33 SRAM bank at 0x22100000 – the region a size-checked setter cannot express, which is why the boot map needs its own HAL entry point.

Returns
Whether the boot map matches the canonical layout.
Return values
trueThe map has 5 regions and region 4 is the expected shared bank.
falseThe count or region-4 descriptor did not match.
Precondition
ra8_mpu_boot_map() returns the driver-owned const table.
Postcondition
No state is modified (pure read of immutable data).
On true the boot map is proven to carry the non-power-of-two region.
Note
Not thread-safe; single-threaded boot context.
Since
0.1.0

Definition at line 206 of file main.c.

References ra8_mpu_region_t::attr_idx, ra8_mpu_region_t::base, k_mpu_boot_idx_shram, k_mpu_boot_shram_base, k_mpu_boot_shram_size, k_ra8_mpu_attr_idx_1, k_ra8_mpu_boot_region_count, ra8_mpu_boot_map(), and ra8_mpu_region_t::size.

Referenced by mpu_boot_run_selftest().

◆ mpu_boot_wfi_forever()

void mpu_boot_wfi_forever ( void )
static

Park the Cortex-M85 forever in a WFI idle loop.

Reached after the one-shot banner has been emitted (pass or fail). The WFI lets ra8_emulator's idle detector stop the run cleanly and models the low-power posture on silicon.

Returns
This function never returns.
Precondition
The self-test verdict has been emitted over the console.
No further forward progress is required of the M85.
Postcondition
The core makes no further architectural progress.
Any pending console bytes have already been flushed by the caller.
Note
Not thread-safe; single-threaded boot context.
Since
0.1.0

Definition at line 155 of file main.c.

Referenced by main().

Variable Documentation

◆ k_mpu_boot_fail_map

const uint8_t k_mpu_boot_fail_map[] = "mpu_boot_map_hal: boot-map FAIL\r\n"
static

Failure banner: the boot map region table was not the canonical map.

Distinct from the PASS banner and free of "PASS".

Since
0.1.0

Definition at line 128 of file main.c.

Referenced by main().

◆ k_mpu_boot_fail_mmio

const uint8_t k_mpu_boot_fail_mmio[] = "mpu_boot_map_hal: device-MMIO FAIL\r\n"
static

Failure banner: the Device-nGnRE MMIO (region 3) readback mismatched.

Distinct from the PASS banner and free of "PASS".

Since
0.1.0

Definition at line 136 of file main.c.

Referenced by main().

◆ k_mpu_boot_fail_mpu

const uint8_t k_mpu_boot_fail_mpu[] = "mpu_boot_map_hal: mpu-disabled FAIL\r\n"
static

Failure banner: ra8_mpu_is_enabled() reported the MPU is off.

Distinct from the PASS banner and free of "PASS".

Since
0.1.0

Definition at line 120 of file main.c.

Referenced by main().

◆ k_mpu_boot_fail_setup

const uint8_t k_mpu_boot_fail_setup[] = "mpu_boot_map_hal: setup FAIL\r\n"
static

Failure banner: clock / console bring-up failed before the self-test.

Distinct from the PASS banner and free of "PASS".

Since
0.1.0

Definition at line 112 of file main.c.

Referenced by main().

◆ k_mpu_boot_pass_banner

const uint8_t k_mpu_boot_pass_banner[] = "mpu_boot_map_hal: mpu-via-hal PASS\r\n"
static

Deterministic one-shot HIL success banner (uart_scrape gate).

Emitted only on the all-pass path. Contains "PASS" and is not a substring of any FAIL banner.

Warning
Do not modify; hil.conf HIL_EXPECT matches it verbatim.
Since
0.1.0

Definition at line 104 of file main.c.

Referenced by main().