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

ra8_io fabric capstone: two block-dev backends swapped behind one interface, a VFS open/read/write/close round-trip, and stdio retargeted to both a UART and a RAM stream (epic #155, issue #264). More...

#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "ra8_attributes.h"
#include "ra8_boot_entry.h"
#include "ra8_cgc.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_io.h"
#include "ra8_log.h"
#include "ra8_port_constants.h"
#include "ra8_port_utils.h"
#include "ra8_sci.h"
#include "ra8_time.h"
#include "ra8_xspi.h"
Include dependency graph for main.c:

Go to the source code of this file.

Data Structures

struct  swap_backend_t
 One row of the drop-in block-device swap table. More...

Enumerations

enum  swap_const_t : uint32_t {
  k_swap_uart_chan = 8U ,
  k_swap_uart_baud = 115200U ,
  k_swap_pin_shift = 8U ,
  k_swap_ram_blocks = 256U ,
  k_swap_xspi_inst = 0U ,
  k_swap_xspi_base = 0U ,
  k_swap_xspi_blocks = 512U ,
  k_swap_payload = 96U ,
  k_swap_log_cap = 512U ,
  k_swap_backends = 2U
}
 Console, volume, and payload knobs (no magic numbers). More...
enum  swap_pattern_t : uint32_t {
  k_swap_pat_mul = 7U ,
  k_swap_pat_add = 3U ,
  k_swap_pat_xor = 0x5AU
}
 Deterministic payload-pattern coefficients (no magic numbers). More...

Functions

static void internal_swap_uart_print (const char *msg)
 Print a NUL-terminated string on the UART console stream.
static void internal_swap_fill (uint32_t len)
 Fill s_payload with the deterministic linear byte pattern.
static ra8_err_t internal_swap_vfs_write (const char *path, uint32_t len)
 Open a VFS path for writing, write len bytes, and close it.
static ra8_err_t internal_swap_vfs_read_verify (const char *path, uint32_t len)
 Re-open a VFS path for reading and byte-compare against s_payload.
static ra8_err_t internal_swap_run_one (const swap_backend_t *b, uint32_t len, ra8_io_stream_t *log)
 Run the identical FAT/VFS round-trip over one pre-bound block device.
static ra8_err_t internal_swap_replay_capture (uint32_t *out_used)
 Replay the RAM-captured stdio out of the UART console.
static ra8_err_t internal_swap_run_all (const char **out_failed)
 Bind both block-device backends and run the swap over the table.
static void internal_demo_setup_or_halt (void)
 Bring up CGC + SysTick + the SCI8 console; halt forever on any failure.
void main (void)
 Firmware entry point.

Variables

static const ra8_port_pin_t s_swap_txd
 SCI8 console transmit pin, PD02.
static const ra8_port_pin_t s_swap_rxd
 SCI8 console receive pin, PD03.
static uint8_t s_ram_disk [(size_t) k_swap_ram_blocks *(size_t) k_ra8_io_block_size_bytes]
 128 KiB RAM-disk backing buffer (in SRAM .bss).
static ra8_io_blockdev_t s_ram_bd
 RAM block-device handle + its backend state.
static ra8_io_blockdev_ram_state_t s_ram_state
static ra8_io_blockdev_t s_xspi_bd
 xSPI (OSPI NOR) block-device handle + its backend state.
static ra8_io_blockdev_xspi_state_t s_xspi_state
static ra8_fs_backend_t s_be
 Reusable ra8_fs bridge (one mount is live at a time; reused per row).
static ra8_io_stream_t s_uart
 UART output stream + its sink state (the serial console target).
static ra8_io_stream_uart_state_t s_uart_state
static ra8_io_stream_t s_ram_log
 In-RAM stdio capture stream + its sink state and backing buffer.
static ra8_io_stream_ram_state_t s_ram_log_state
static uint8_t s_ram_log_buf [k_swap_log_cap]
static uint8_t s_payload [k_swap_payload]
 Deterministic write payload + read-back scratch (no heap; NASA Rule 3).
static uint8_t s_readback [k_swap_payload]
static const char *const s_tag = "ra8_io_swap_demo"
 Module log tag.

Detailed Description

ra8_io fabric capstone: two block-dev backends swapped behind one interface, a VFS open/read/write/close round-trip, and stdio retargeted to both a UART and a RAM stream (epic #155, issue #264).

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

Where the sibling ra8_io_*_demo apps each bind ONE backend, this app is the capstone that shows off every ra8_io abstraction in a single binary:

  1. Drop-in block-device swap. One backend-agnostic engine (internal_swap_run_one) runs the IDENTICAL fabric round-trip – bridge the block device to ra8_fs, format + mount a FAT12 volume, register it in the VFS, write a file, read it back, byte-compare, then tear the mount down – over a table of swap_backend_t rows. Row 0 is an in-SRAM RAM block device (ra8_io_blockdev_ram, erase-to-zero, no erase-before-write); row 1 is the on-board Octo-SPI (xSPI) NOR flash (ra8_io_blockdev_xspi, an erase-before-write medium that reads back 0xFF after erase and does a whole-4-KiB-sector read-modify-write on every 512-byte block write). The engine names NO peripheral: the two capability-different media are proven interchangeable behind the one ra8_io_blockdev_t vtable.
  2. VFS open/read/write/close. Each backend is reached by name (ram:/DATA.BIN, xs:/DATA.BIN); the round-trip opens for write, writes, closes, re-opens for read, reads, closes, and compares – the streaming file API, not a whole-file shortcut.
  3. Targetable stdio (retarget to two sinks). The engine writes its progress through a ra8_io_stream_t. During the swap phase that stream is an in-RAM capture sink (ra8_io_stream_ram), so the SAME puts / put_u32 calls that would otherwise land on the serial console are captured into a byte buffer. Afterwards the captured bytes are replayed out of the UART sink (ra8_io_stream_uart), proving one writer, two destinations.

ra8_emulator models both the RAM region and the OSPI NOR array, so the run is headless and observable over the SCI8 / J-Link OB VCOM console: a successful run prints ra8_io_swap_demo: two-backend swap (ram + xs) PASS. The OSPI RMW is slow in the emulator, so give ra8_emulator a generous instruction budget (see this app's README). It lives under hw_pending because the xSPI leg writes the non-volatile on-board NOR and has not yet been captured on the bench; the RAM, VFS, and stdio legs are fully exercised in ra8_emulator and in the host unit test tests/mocks/src/test_app_ra8_io_swap_demo.c.

Definition in file main.c.

Enumeration Type Documentation

◆ swap_const_t

enum swap_const_t : uint32_t

Console, volume, and payload knobs (no magic numbers).

Collects every literal the app uses so the magic-number gate stays silent and the sizing reads symbolically. The RAM volume is kept small (in-SRAM .bss) and the xSPI volume matches the sibling ra8_io_xspi_demo window; the payload fits inside one NOR sector so the erase-before-write round-trip stays cheap.

Since
0.1.0
Enumerator
k_swap_uart_chan 

SCI8 J-Link OB console.

k_swap_uart_baud 

Console baud.

k_swap_pin_shift 

Port byte position in ra8_port_pin_t.

k_swap_ram_blocks 

128 KiB in-SRAM RAM disk (FAT12).

k_swap_xspi_inst 

xSPI controller instance index.

k_swap_xspi_base 

Flash byte offset of logical block 0.

k_swap_xspi_blocks 

256 KiB OSPI NOR window (FAT12).

k_swap_payload 

Bytes written + read back per backend.

k_swap_log_cap 

RAM stdio-capture buffer capacity.

k_swap_backends 

Number of block-device backends swapped.

Definition at line 80 of file main.c.

◆ swap_pattern_t

enum swap_pattern_t : uint32_t

Deterministic payload-pattern coefficients (no magic numbers).

The written bytes follow byte[i] = (i * mul + add) ^ xor so the read-back compare is a strong end-to-end check of the whole stack; a swapped or truncated buffer is caught byte-for-byte.

Since
0.1.0
Enumerator
k_swap_pat_mul 

Linear pattern multiplier.

k_swap_pat_add 

Linear pattern additive bias.

k_swap_pat_xor 

Linear pattern XOR mask.

Definition at line 103 of file main.c.

Function Documentation

◆ internal_demo_setup_or_halt()

void internal_demo_setup_or_halt ( void )
static

Bring up CGC + SysTick + the SCI8 console; halt forever on any failure.

Initialises clocks, reads CPU/PCLKA rates, starts the millisecond time base, routes the SCI8 console pins, and opens the SCI8 UART. Any failure spins forever so a debugger can inspect the halt (there is no console yet to report on).

Returns
None.
Precondition
SystemInit configured VTOR / FPU / priority grouping.
Runs single-threaded during early boot.
Postcondition
On success SCI8 is open at k_swap_uart_baud and the time base runs.
On any failure the function never returns (infinite halt loop).
Note
Not thread-safe; boot-context only.
Since
0.1.0

Definition at line 481 of file main.c.

References k_ra8_clock_id_cpuclk0, k_ra8_clock_id_pclka, k_ra8_ok, k_ra8_psel_sci_async, k_ra8_sci_data_8, k_ra8_sci_parity_none, k_ra8_sci_stop_1, k_swap_uart_baud, k_swap_uart_chan, ra8_cgc_get_clock_hz(), ra8_cgc_init(), RA8_INTERNAL, ra8_pfs_route_peripheral(), ra8_sci_init(), ra8_time_init(), s_swap_rxd, and s_swap_txd.

◆ internal_swap_fill()

void internal_swap_fill ( uint32_t len)
static

Fill s_payload with the deterministic linear byte pattern.

Writes byte[i] = (i * k_swap_pat_mul + k_swap_pat_add) ^ k_swap_pat_xor over the first len bytes so the read-back compare validates the whole fabric path with reproducible content.

Parameters
[in]lenNumber of bytes to fill (must be <= k_swap_payload).
Returns
None.
Precondition
len is at most k_swap_payload.
s_payload is file-scope storage (always allocated).
Postcondition
The first len bytes of s_payload hold the reproducible pattern.
No other state is modified.
Note
Not thread-safe; mutates the shared payload buffer.
Since
0.1.0

Definition at line 219 of file main.c.

References k_swap_pat_add, k_swap_pat_mul, k_swap_pat_xor, RA8_INTERNAL, and s_payload.

Referenced by internal_swap_run_one().

◆ internal_swap_replay_capture()

ra8_err_t internal_swap_replay_capture ( uint32_t * out_used)
static

Replay the RAM-captured stdio out of the UART console.

Reads the byte count captured by the in-RAM stdio sink and writes the captured bytes to the UART sink, bracketed by human-readable markers. This is the visible proof that the engine's identical stream calls were retargeted into RAM and can be re-emitted to a second destination.

Parameters
[out]out_usedReceives the captured byte count on success.
Returns
ra8_err_t Error code.
Return values
k_ra8_okThe capture was replayed and its length reported.
k_ra8_err_null_ptrout_used was NULL.
(other)The first failing stream step's code.
Precondition
out_used is non-NULL and s_ram_log captured the swap phase.
s_uart is initialised.
Postcondition
On success *out_used holds the replayed byte count.
The captured bytes have been queued on the UART stream.
Note
Not thread-safe; single-caller boot context.
Since
0.1.0

Definition at line 387 of file main.c.

References internal_swap_uart_print(), k_ra8_ok, RA8_CHECK_NULL_PTR, RA8_INTERNAL, ra8_io_stream_ram_used(), ra8_io_stream_write(), RA8_RETURN_ON_ERROR, RA8_VALIDATE_INIT, s_ram_log_buf, s_ram_log_state, s_tag, and s_uart.

Referenced by main().

◆ internal_swap_run_all()

ra8_err_t internal_swap_run_all ( const char ** out_failed)
static

Bind both block-device backends and run the swap over the table.

Binds the in-SRAM RAM device and the OSPI NOR device (the only two per-medium bring-up lines), builds the two-row swap_backend_t table, and runs internal_swap_run_one over each row with the in-RAM stdio sink as the progress log. Stops at the first failing backend and reports which one.

Parameters
[out]out_failedReceives the name of the first failing backend, or NULL when every backend passed.
Returns
ra8_err_t Error code.
Return values
k_ra8_okBoth backends round-tripped through the identical engine.
k_ra8_err_*The first failing bind / round-trip step's code.
Precondition
internal_demo_setup_or_halt has run and the stdio sinks are initialised.
out_failed is non-NULL.
Postcondition
On success *out_failed is NULL and both volumes round-tripped.
On failure *out_failed names the backend whose round-trip failed.
Note
Not thread-safe; single-caller boot context.
Since
0.1.0

Definition at line 424 of file main.c.

References internal_swap_run_one(), k_ra8_ok, k_ra8_xspi_lio_1s1s1s, k_swap_backends, k_swap_payload, k_swap_ram_blocks, k_swap_xspi_base, k_swap_xspi_blocks, k_swap_xspi_inst, swap_backend_t::name, RA8_CHECK_NULL_PTR, RA8_INTERNAL, ra8_io_blockdev_ram_init(), ra8_io_blockdev_xspi_init(), RA8_RETURN_ON_ERROR, ra8_xspi_init(), s_ram_bd, s_ram_disk, s_ram_log, s_ram_state, s_tag, s_xspi_bd, and s_xspi_state.

Referenced by main().

◆ internal_swap_run_one()

ra8_err_t internal_swap_run_one ( const swap_backend_t * b,
uint32_t len,
ra8_io_stream_t * log )
static

Run the identical FAT/VFS round-trip over one pre-bound block device.

The backend-agnostic engine, called once per swap_backend_t row. Bridges b->bd to ra8_fs, formats a FAT12 volume with b->label, mounts it, registers it in the VFS under b->name, writes then reads back len bytes at b->file, then unregisters and unmounts so the two shared mount slots are free for the next backend. Progress is emitted to log – the SAME calls land wherever log is bound.

Parameters
[in]bBackend row (device handle + FAT/VFS identity).
[in]lenPayload length to round-trip (<= k_swap_payload).
[out]logStream to write human-readable progress into.
Returns
ra8_err_t Error code.
Return values
k_ra8_okThe volume mounted and the payload round-tripped.
k_ra8_err_null_ptrb or log was NULL.
(other)The first failing fabric step's code.
Precondition
b, b->bd, and log are non-NULL and the device is reachable.
len is at most k_swap_payload.
Postcondition
On success b->file holds the verified payload, then the mount is torn down (VFS name released, ra8_fs unmounted).
No file handle or mount is left open on any return path.
Note
Not thread-safe; single-caller boot context.
Since
0.1.0

Definition at line 334 of file main.c.

References internal_swap_fill(), internal_swap_vfs_read_verify(), internal_swap_vfs_write(), k_ra8_fs_type_fat12, k_ra8_ok, ra8_fs_format_opts_t::label, RA8_CHECK_NULL_PTR, ra8_fs_format(), ra8_fs_mount(), ra8_fs_unmount(), ra8_io_blockdev_as_fs_backend(), ra8_io_stream_put_u32(), ra8_io_stream_puts(), ra8_io_vfs_mount(), ra8_io_vfs_unmount(), RA8_RETURN_ON_ERROR, s_be, s_tag, and ra8_fs_format_opts_t::type.

Referenced by internal_swap_run_all().

◆ internal_swap_uart_print()

void internal_swap_uart_print ( const char * msg)
static

Print a NUL-terminated string on the UART console stream.

Thin wrapper over ra8_io_stream_puts bound to s_uart so call sites do not repeat the sink handle. Used only for the boot banner, the replay of the RAM capture, and the final verdict lines.

Parameters
[in]msgNUL-terminated ASCII string (CR/LF supplied by the caller).
Returns
None.
Precondition
s_uart was initialised by ra8_io_stream_uart_init.
msg is non-NULL and NUL-terminated.
Postcondition
The bytes of msg are queued on the UART stream.
No other state changes.
Note
Blocking polled TX; not interrupt-safe.
Since
0.1.0

Definition at line 195 of file main.c.

References RA8_INTERNAL, ra8_io_stream_puts(), and s_uart.

Referenced by internal_swap_replay_capture(), and main().

◆ internal_swap_vfs_read_verify()

ra8_err_t internal_swap_vfs_read_verify ( const char * path,
uint32_t len )
static

Re-open a VFS path for reading and byte-compare against s_payload.

Read-back half of the round-trip: ra8_io_vfs_open(read) -> ra8_fs_read -> ra8_fs_close, then a single compound verdict on both the returned length and the byte content. The handle is closed on every path.

Parameters
[in]pathFull "<name>:/..." VFS path to read.
[in]lenExpected byte count (the length just written).
Returns
ra8_err_t Error code.
Return values
k_ra8_okLength and content both matched.
k_ra8_err_null_ptrpath was NULL.
k_ra8_err_checksum_mismatchThe read-back length or bytes differed.
(other)The first failing VFS / ra8_fs step's code.
Precondition
path is non-NULL and its volume is mounted.
len is at most k_swap_payload.
Postcondition
s_readback holds the bytes read from path.
No file handle is left open on any return path.
Note
Not thread-safe; mutates the shared read-back buffer.
Since
0.1.0

Definition at line 287 of file main.c.

References k_ra8_err_checksum_mismatch, k_ra8_err_invalid_size, k_ra8_fs_mode_read, k_ra8_ok, k_swap_payload, memcmp(), memset(), RA8_CHECK_NULL_PTR, RA8_CHECK_RANGE_TAG, ra8_fs_close(), ra8_fs_read(), RA8_INTERNAL, ra8_io_vfs_open(), RA8_RETURN_ON_ERROR, s_payload, s_readback, and s_tag.

Referenced by internal_swap_run_one().

◆ internal_swap_vfs_write()

ra8_err_t internal_swap_vfs_write ( const char * path,
uint32_t len )
static

Open a VFS path for writing, write len bytes, and close it.

Streaming write half of the round-trip: ra8_io_vfs_open(write) -> ra8_fs_write -> ra8_fs_close. The handle is closed on every path so no slot leaks even when the write itself fails.

Parameters
[in]pathFull "<name>:/..." VFS path to create/truncate.
[in]lenByte count to write from s_payload.
Returns
ra8_err_t Error code.
Return values
k_ra8_okThe payload was written and the handle closed.
k_ra8_err_null_ptrpath was NULL.
(other)The first failing VFS / ra8_fs step's code.
Precondition
path is non-NULL and its volume is mounted.
len is at most k_swap_payload.
Postcondition
On success path holds the s_payload bytes.
No file handle is left open on any return path.
Note
Not thread-safe; single-caller boot context.
Since
0.1.0

Definition at line 250 of file main.c.

References k_ra8_err_invalid_size, k_ra8_fs_mode_write, k_swap_payload, RA8_CHECK_NULL_PTR, RA8_CHECK_RANGE_TAG, ra8_fs_close(), ra8_fs_write(), RA8_INTERNAL, ra8_io_vfs_open(), RA8_RETURN_ON_ERROR, s_payload, and s_tag.

Referenced by internal_swap_run_one().

◆ main()

void main ( void )

Firmware entry point.

The application entry point Reset_Handler hands control to.

Brings up the console and both stdio sinks, retargets the engine's stdio to the in-RAM capture sink, runs the two-backend swap, replays the RAM capture out of the UART, and prints a single PASS/FAIL verdict per abstraction before parking in an infinite loop.

Precondition
SystemInit configured VTOR / FPU / priority grouping.
The OSPI NOR array is present (modelled in ra8_emulator, real on silicon).
Postcondition
A PASS or FAIL verdict line has been queued on SCI8 for each abstraction.
Control parks in an infinite loop; the function never returns.
Note
Single-threaded; runs to the park loop on the main stack.
Since
0.1.0

Definition at line 521 of file main.c.

References internal_demo_setup_or_halt(), internal_swap_replay_capture(), internal_swap_run_all(), internal_swap_uart_print(), k_ra8_ok, k_swap_log_cap, k_swap_uart_chan, ra8_io_log_attach(), ra8_io_stream_put_u32(), ra8_io_stream_ram_init(), ra8_io_stream_uart_init(), ra8_log_init(), ra8_sci_flush(), s_ram_log, s_ram_log_buf, s_ram_log_state, s_uart, and s_uart_state.

Variable Documentation

◆ s_be

ra8_fs_backend_t s_be
static

Reusable ra8_fs bridge (one mount is live at a time; reused per row).

Definition at line 159 of file main.c.

◆ s_payload

uint8_t s_payload[k_swap_payload]
static

Deterministic write payload + read-back scratch (no heap; NASA Rule 3).

Definition at line 170 of file main.c.

◆ s_ram_bd

ra8_io_blockdev_t s_ram_bd
static

RAM block-device handle + its backend state.

Definition at line 153 of file main.c.

Referenced by internal_swap_run_all().

◆ s_ram_disk

uint8_t s_ram_disk[(size_t) k_swap_ram_blocks *(size_t) k_ra8_io_block_size_bytes]
static

128 KiB RAM-disk backing buffer (in SRAM .bss).

Definition at line 151 of file main.c.

Referenced by internal_swap_run_all().

◆ s_ram_log

ra8_io_stream_t s_ram_log
static

In-RAM stdio capture stream + its sink state and backing buffer.

Definition at line 165 of file main.c.

Referenced by internal_swap_run_all(), and main().

◆ s_ram_log_buf

uint8_t s_ram_log_buf[k_swap_log_cap]
static

Definition at line 167 of file main.c.

Referenced by internal_swap_replay_capture(), and main().

◆ s_ram_log_state

ra8_io_stream_ram_state_t s_ram_log_state
static

Definition at line 166 of file main.c.

Referenced by internal_swap_replay_capture(), and main().

◆ s_ram_state

ra8_io_blockdev_ram_state_t s_ram_state
static

Definition at line 154 of file main.c.

Referenced by internal_swap_run_all().

◆ s_readback

uint8_t s_readback[k_swap_payload]
static

Definition at line 171 of file main.c.

◆ s_swap_rxd

const ra8_port_pin_t s_swap_rxd
static
Initial value:
=
(ra8_port_pin_t)(((uint16_t)k_ra8_port_13 << (uint16_t)k_swap_pin_shift) | (uint16_t)k_ra8_pin_3)
@ k_swap_pin_shift
Port byte position in ra8_port_pin_t.
Definition main.c:83
ra8_port_pin_t
Packed (port << 8) | pin pin identifier.
@ k_ra8_port_13
RA8 port 13.
@ k_ra8_pin_3
RA8 pin 3.

SCI8 console receive pin, PD03.

Encodes the board port and pin in the HAL's packed pin identifier.

Note
Immutable routing input used once during boot.
Since
0.1.0

Definition at line 147 of file main.c.

Referenced by internal_demo_setup_or_halt().

◆ s_swap_txd

const ra8_port_pin_t s_swap_txd
static
Initial value:
=
(ra8_port_pin_t)(((uint16_t)k_ra8_port_13 << (uint16_t)k_swap_pin_shift) | (uint16_t)k_ra8_pin_2)
@ k_ra8_pin_2
RA8 pin 2.

SCI8 console transmit pin, PD02.

Encodes the board port and pin in the HAL's packed pin identifier.

Note
Immutable routing input used once during boot.
Since
0.1.0

Definition at line 138 of file main.c.

Referenced by internal_demo_setup_or_halt().

◆ s_tag

const char* const s_tag = "ra8_io_swap_demo"
static

Module log tag.

Definition at line 174 of file main.c.

◆ s_uart

ra8_io_stream_t s_uart
static

UART output stream + its sink state (the serial console target).

Definition at line 162 of file main.c.

◆ s_uart_state

ra8_io_stream_uart_state_t s_uart_state
static

Definition at line 163 of file main.c.

Referenced by main().

◆ s_xspi_bd

ra8_io_blockdev_t s_xspi_bd
static

xSPI (OSPI NOR) block-device handle + its backend state.

Definition at line 156 of file main.c.

Referenced by internal_swap_run_all().

◆ s_xspi_state

ra8_io_blockdev_xspi_state_t s_xspi_state
static

Definition at line 157 of file main.c.