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

Wear-levelled block I/O + power-cycle survival over the FTL (#258). More...

#include <stdint.h>
#include <string.h>
#include "ra8_boot_entry.h"
#include "ra8_cgc.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_flash.h"
#include "ra8_ftl.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 dependency graph for main.c:

Go to the source code of this file.

Enumerations

enum  demo_addr_t : uintptr_t { k_demo_mram_base = k_ra8_flash_extra_start }
 Extra-MRAM window base address. More...
enum  demo_const_t : uint32_t {
  k_demo_uart_chan = 8U ,
  k_demo_uart_baud = 115200U ,
  k_demo_total_blocks = 24U ,
  k_demo_ftl_phys = 23U ,
  k_demo_ftl_logical = 8U ,
  k_demo_meta_lba = 23U ,
  k_demo_one_block = 1U ,
  k_demo_test_lbn = 2U ,
  k_demo_writes = 12U ,
  k_demo_block = 512U ,
  k_demo_pin_shift = 8U ,
  k_demo_mrcfreq_mhz = 200U ,
  k_demo_mrefreq_mhz = 100U ,
  k_demo_seed_mul = 17U ,
  k_demo_lbn_mul = 5U ,
  k_demo_tag_base = 1U
}
 Console + FTL geometry + workload knobs. More...

Functions

static void demo_print (const char *msg)
 Print a NUL-terminated string on the demo's UART stream.
static void demo_report_map (uint32_t lbn, uint16_t phys)
 Print logical L now at physical P for one relocation observation.
static void demo_setup_or_halt (void)
 Bring up CGC + SysTick + the SCI8 console; halt forever on any failure.
static ra8_err_t demo_open (void)
 Bring up the MRAM controller and bind the raw MRAM block device.
static ra8_err_t demo_write_verify (uint32_t lbn, uint32_t tag, uint16_t *out_phys)
 Write one generation of the test pattern and read it back verified.
static ra8_err_t demo_wear_phase (uint32_t *migrations, uint16_t *last_phys)
 Act 1: init the FTL and hammer one logical block to show migration.
static ra8_err_t demo_checkpoint (void)
 Act 2: serialise the FTL mapping into the reserved MRAM block.
static ra8_err_t demo_reopen_naive (void)
 Act 3a: model a reset and prove the naive re-open lost the mapping.
static ra8_err_t demo_restore (uint32_t want_tag, uint16_t want_phys)
 Act 3b: reload the checkpoint and prove data + mapping survived.
static void demo_report_wear (void)
 Print the FTL wear spread (max/min erase counts across physical blocks).
static ra8_err_t demo_run (void)
 Run the three acts and report a single PASS/FAIL verdict.
void main (void)
 Firmware entry point.

Variables

static const ra8_port_pin_t k_demo_txd
 SCI8 console TXD = PD02.
static const ra8_port_pin_t k_demo_rxd
 SCI8 console RXD = PD03.
static ra8_io_blockdev_t s_bd
 Raw MRAM block-device handle + its backend state.
static ra8_io_blockdev_mram_state_t s_mstate
static ra8_ftl_t s_ftl
 FTL handle + the presented free-overwrite block device.
static ra8_io_blockdev_t s_present
static uint16_t s_map [(size_t) k_demo_ftl_logical]
 FTL caller storage: map, per-physical metadata, copy scratch.
static ra8_ftl_pblock_t s_pblocks [(size_t) k_demo_ftl_phys]
static uint8_t s_scratch [(size_t) k_demo_block]
static uint8_t s_ckbuf [(size_t) k_demo_block]
 One-block checkpoint buffer (the reserved MRAM slot holds this).
static ra8_io_stream_t s_uart
 UART output stream + its sink state.
static ra8_io_stream_uart_state_t s_ust
static const char *const s_tag = "ra8_ftl_demo"
 Module log tag.

Detailed Description

Wear-levelled block I/O + power-cycle survival over the FTL (#258).

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

Demonstrates the Flash Translation Layer (ra8_ftl.h) end to end over the RA8D2's on-chip extra MRAM – a non-volatile, erase-before-write medium. The FTL turns that erase-before-write device into a clean free-overwrite block device and spreads wear by relocating each logical-block write to a fresh, least-worn physical block (copy-on-write).

The extra-MRAM window is 24 logical blocks (12 KiB). This demo hands the FTL the first 23 physical blocks (presenting 8 logical blocks, so 15 spare for relocation headroom) and reserves the last physical block as a non-volatile slot for the FTL mapping checkpoint.

The run is three acts:

  1. Wear-levelling – write ONE logical block repeatedly and, after each write, query ra8_ftl_phys_of to show the backing physical block index migrating while the logical address stays fixed. Each write is read back and byte-verified.
  2. Checkpoint – serialise the FTL mapping (ra8_ftl_checkpoint_save) and store the blob in the reserved MRAM block (the FTL keeps no on-media metadata of its own, so this is what lets the mapping survive a reset).
  3. Power-cycle survival – model a reset: discard the FTL handle and its caller tables (SRAM is volatile) while the MRAM retains its bytes. A naive re-init has lost the mapping (the logical block reads back the erase value), so ra8_ftl_checkpoint_load reloads the checkpoint from MRAM and the data – and the exact physical mapping – reappears.

ra8_emulator models the MACI program/erase sequence (board_periph_mram.c), so the whole run is observable headless over the SCI8 console. A successful run ends with: ra8_ftl_demo: wear-level + power-cycle-survive on extra MRAM PASS.

Definition in file main.c.

Enumeration Type Documentation

◆ demo_addr_t

enum demo_addr_t : uintptr_t

Extra-MRAM window base address.

Warning
One-time-programmable OTP option-setting memory (HUM Ch 59.7.4.5 Table 59.15 p 3592), not rewritable data-flash: the wear-level erase/rewrite cycle cannot work on real silicon. A rewritable-medium retarget is #315.
Enumerator
k_demo_mram_base 

Extra-MRAM OTP window base (0x02E07600).

Definition at line 64 of file main.c.

◆ demo_const_t

enum demo_const_t : uint32_t

Console + FTL geometry + workload knobs.

Enumerator
k_demo_uart_chan 

SCI8 J-Link OB console.

k_demo_uart_baud 

Console baud.

k_demo_total_blocks 

Whole extra MRAM (12 KiB).

k_demo_ftl_phys 

Physical blocks handed to the FTL.

k_demo_ftl_logical 

Logical blocks the FTL presents.

k_demo_meta_lba 

Reserved raw block for the checkpoint.

k_demo_one_block 

Single-block transfer count.

k_demo_test_lbn 

Logical block written repeatedly.

k_demo_writes 

Repeated overwrites of the test block.

k_demo_block 

Bytes per block.

k_demo_pin_shift 

Port byte position in ra8_port_pin_t.

k_demo_mrcfreq_mhz 

Code-MRAM advertised clock (MHz).

k_demo_mrefreq_mhz 

Extra-MRAM advertised clock (MHz).

k_demo_seed_mul 

Test-pattern index multiplier.

k_demo_lbn_mul 

Test-pattern logical-block bias.

k_demo_tag_base 

First generation tag.

Definition at line 69 of file main.c.

Function Documentation

◆ demo_checkpoint()

ra8_err_t demo_checkpoint ( void )
static

Act 2: serialise the FTL mapping into the reserved MRAM block.

Confirms the checkpoint fits one 512-byte block, serialises it with ra8_ftl_checkpoint_save, erases the reserved raw block, and programs the checkpoint into it – the persistent metadata that lets the mapping outlive the volatile SRAM tables.

Returns
ra8_err_t Error code.
Return values
k_ra8_okThe checkpoint is stored in MRAM.
k_ra8_err_invalid_sizeThe checkpoint does not fit one block.
(other)The first failing save / erase / write code.
Precondition
demo_wear_phase returned k_ra8_ok; s_ftl is initialised.
k_demo_meta_lba is outside the FTL's physical range.
Postcondition
On success raw block k_demo_meta_lba holds a loadable checkpoint.
No FTL mapping state is mutated.
Note
Not thread-safe; single-caller boot context.
Since
0.1.0

Definition at line 368 of file main.c.

References k_demo_block, k_demo_meta_lba, k_demo_one_block, k_ra8_err_invalid_size, k_ra8_ok, ra8_ftl_checkpoint_save(), ra8_ftl_checkpoint_size(), ra8_io_blockdev_erase(), ra8_io_blockdev_write(), RA8_RETURN_ON_ERROR, s_bd, s_ckbuf, s_ftl, and s_tag.

Referenced by demo_run().

◆ demo_open()

ra8_err_t demo_open ( void )
static

Bring up the MRAM controller and bind the raw MRAM block device.

Initialises the MRAM controller (ra8_flash_init) and binds an erase-before-write block device over the whole 24-block extra-MRAM window; the FTL manages the first 23 blocks and the demo owns block 23 for the checkpoint.

Returns
ra8_err_t Error code.
Return values
k_ra8_okThe raw MRAM block device s_bd is ready.
(other)The first failing bring-up step's error code.
Precondition
demo_setup_or_halt has run (clocks + console up).
The extra-MRAM region is present and writable.
Postcondition
On success s_bd reads/writes/erases the fenced MRAM window.
On any non-ok return s_bd is left unbound.
Note
Not thread-safe; single-caller boot context.
Since
0.1.0

Definition at line 224 of file main.c.

References k_demo_mram_base, k_demo_mrcfreq_mhz, k_demo_mrefreq_mhz, k_demo_total_blocks, k_ra8_ok, ra8_flash_init(), ra8_io_blockdev_mram_init(), RA8_RETURN_ON_ERROR, s_bd, s_mstate, and s_tag.

Referenced by main().

◆ demo_print()

void demo_print ( const char * msg)
static

Print a NUL-terminated string on the demo's UART stream.

Thin wrapper over ra8_io_stream_puts bound to s_uart.

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 131 of file main.c.

References ra8_io_stream_puts(), and s_uart.

◆ demo_reopen_naive()

ra8_err_t demo_reopen_naive ( void )
static

Act 3a: model a reset and prove the naive re-open lost the mapping.

Zeroes the FTL handle and its caller tables (volatile SRAM lost) while the MRAM device state is retained, re-initialises the FTL over the retained backing store, and reads the test block back: with the mapping gone it must read the erase value, confirming the checkpoint is required for survival.

Returns
ra8_err_t Error code.
Return values
k_ra8_okThe mapping was lost as expected (all erase).
k_ra8_err_invalid_stateThe block did not read back as erase value.
(other)The first failing re-init / read call's code.
Precondition
demo_checkpoint returned k_ra8_ok.
The MRAM backing store retains its bytes (non-volatile).
Postcondition
On success s_ftl is freshly initialised and s_present is rebound.
The FTL mapping tables are in their cold-start state.
Note
Not thread-safe; single-caller boot context.
Since
0.1.0

Definition at line 411 of file main.c.

References k_demo_block, k_demo_ftl_logical, k_demo_ftl_phys, k_demo_one_block, k_demo_test_lbn, k_ra8_err_invalid_state, k_ra8_io_erase_value_ones, k_ra8_ok, memset(), ra8_ftl_as_blockdev(), ra8_ftl_init(), ra8_io_blockdev_read(), RA8_RETURN_ON_ERROR, s_bd, s_ftl, s_map, s_pblocks, s_present, s_scratch, and s_tag.

Referenced by demo_run().

◆ demo_report_map()

void demo_report_map ( uint32_t lbn,
uint16_t phys )
static

Print logical L now at physical P for one relocation observation.

Composes a diagnostic line from three stream calls so the migrating physical index is visible per write without a printf dependency.

Parameters
[in]lbnLogical block number.
[in]physPhysical block index currently backing lbn.
Returns
None.
Precondition
s_uart was initialised.
phys is a valid physical index (< k_demo_ftl_phys).
Postcondition
One diagnostic line is queued on the UART stream.
No other state changes.
Note
Blocking polled TX; not interrupt-safe.
Since
0.1.0

Definition at line 155 of file main.c.

References demo_print(), ra8_io_stream_put_u32(), and s_uart.

Referenced by demo_wear_phase().

◆ demo_report_wear()

void demo_report_wear ( void )
static

Print the FTL wear spread (max/min erase counts across physical blocks).

Best-effort diagnostic: queries ra8_ftl_wear_stats and prints the max and min per-block erase counts so a healthy (tight) spread is visible. A query failure is reported but does not fail the demo.

Returns
None.
Precondition
s_ftl is initialised.
s_uart is initialised.
Postcondition
One wear line is queued on the UART stream.
No FTL state is mutated.
Note
Not thread-safe; single-caller boot context.
Since
0.1.0

Definition at line 514 of file main.c.

References demo_print(), k_ra8_ok, ra8_ftl_wear_stats(), ra8_io_stream_put_u32(), s_ftl, and s_uart.

Referenced by demo_run().

◆ demo_restore()

ra8_err_t demo_restore ( uint32_t want_tag,
uint16_t want_phys )
static

Act 3b: reload the checkpoint and prove data + mapping survived.

Reads the checkpoint back from the reserved MRAM block, restores it with ra8_ftl_checkpoint_load, and verifies both that the test block's last generation reappears byte-for-byte and that its physical index matches the pre-reset value want_phys.

Parameters
[in]want_tagGeneration tag of the last pre-reset write.
[in]want_physPhysical index the test block had before the reset.
Returns
ra8_err_t Error code.
Return values
k_ra8_okData and mapping were restored intact.
k_ra8_err_checksum_mismatchThe restored bytes differed.
k_ra8_err_invalid_stateThe restored physical index differed.
(other)The first failing read / load call's code.
Precondition
demo_reopen_naive returned k_ra8_ok; s_ftl is freshly initialised.
want_phys is the physical index reported before the reset.
Postcondition
On success the test block reads back its pre-reset contents.
No MRAM data block is mutated.
Note
Not thread-safe; single-caller boot context.
Since
0.1.0

Definition at line 465 of file main.c.

References k_demo_block, k_demo_lbn_mul, k_demo_meta_lba, k_demo_one_block, k_demo_seed_mul, k_demo_test_lbn, k_ra8_err_checksum_mismatch, k_ra8_err_invalid_state, k_ra8_ok, memcmp(), ra8_ftl_checkpoint_load(), ra8_ftl_phys_of(), ra8_io_blockdev_read(), RA8_RETURN_ON_ERROR, s_bd, s_ckbuf, s_ftl, s_present, and s_tag.

Referenced by demo_run().

◆ demo_run()

ra8_err_t demo_run ( void )
static

Run the three acts and report a single PASS/FAIL verdict.

Sequences wear-levelling, checkpoint, naive re-open, and restore, short-circuiting on the first failure so the verdict reflects the first failing act.

Returns
ra8_err_t Error code (k_ra8_ok iff every act passed).
Return values
k_ra8_okThe full wear-level + power-cycle-survive flow passed.
(other)The first failing act's error code.
Precondition
demo_open returned k_ra8_ok.
The console + MRAM device are ready.
Postcondition
Diagnostic lines for each act are queued on the UART stream.
s_ftl reflects the restored mapping on success.
Note
Not thread-safe; single-caller boot context.
Since
0.1.0

Definition at line 548 of file main.c.

References demo_checkpoint(), demo_print(), demo_reopen_naive(), demo_report_wear(), demo_restore(), demo_wear_phase(), k_demo_one_block, k_demo_tag_base, k_demo_writes, k_ra8_err_invalid_state, k_ra8_ok, RA8_RETURN_ON_ERROR, and s_tag.

◆ demo_setup_or_halt()

void 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 time base, routes the SCI8 console pins, and opens the SCI8 UART.

Returns
None.
Precondition
SystemInit configured VTOR / FPU / priority grouping.
Runs single-threaded during early boot.
Postcondition
On success SCI8 is open at k_demo_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 180 of file main.c.

References k_demo_rxd, k_demo_txd, k_demo_uart_baud, k_demo_uart_chan, 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, ra8_cgc_get_clock_hz(), ra8_cgc_init(), ra8_pfs_route_peripheral(), ra8_sci_init(), and ra8_time_init().

◆ demo_wear_phase()

ra8_err_t demo_wear_phase ( uint32_t * migrations,
uint16_t * last_phys )
static

Act 1: init the FTL and hammer one logical block to show migration.

Initialises the FTL over the raw MRAM device (23 physical blocks, 8 logical presented), binds the presented device, then overwrites k_demo_test_lbn k_demo_writes times. Each write is verified and its new physical index reported; the count of physical relocations and the final physical index are returned.

Parameters
[out]migrationsReceives the number of physical relocations observed.
[out]last_physReceives the final physical index of the test block.
Returns
ra8_err_t Error code.
Return values
k_ra8_okAll writes round-tripped and the block relocated.
k_ra8_err_null_ptrmigrations or last_phys was NULL.
(other)The first failing init / write / verify call's code.
Precondition
demo_open returned k_ra8_ok; s_bd is bound.
migrations and last_phys are writable.
Postcondition
On success s_present is bound and the test block is live.
*migrations >= 1 whenever spare blocks allow relocation.
Note
Not thread-safe; single-caller boot context.
Since
0.1.0

Definition at line 313 of file main.c.

References demo_report_map(), demo_write_verify(), k_demo_ftl_logical, k_demo_ftl_phys, k_demo_tag_base, k_demo_test_lbn, k_demo_writes, k_ra8_ftl_unmapped, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_ftl_as_blockdev(), ra8_ftl_init(), RA8_RETURN_ON_ERROR, s_bd, s_ftl, s_map, s_pblocks, s_present, s_scratch, and s_tag.

Referenced by demo_run().

◆ demo_write_verify()

ra8_err_t demo_write_verify ( uint32_t lbn,
uint32_t tag,
uint16_t * out_phys )
static

Write one generation of the test pattern and read it back verified.

Fills a block with a deterministic pattern keyed by lbn and tag, writes it through the FTL-presented device (copy-on-write relocation), reads it back and byte-compares, then reports the new physical mapping through ra8_ftl_phys_of.

Parameters
[in]lbnLogical block number to write.
[in]tagGeneration tag distinguishing successive overwrites.
[out]out_physReceives the physical block now backing lbn.
Returns
ra8_err_t Error code.
Return values
k_ra8_okThe block round-tripped and mapped.
k_ra8_err_null_ptrout_phys was NULL.
k_ra8_err_checksum_mismatchThe read-back bytes differed.
(other)The first failing FTL / device call's code.
Precondition
The FTL device s_present is bound.
lbn < k_demo_ftl_logical.
Postcondition
On success *out_phys is the live physical index for lbn.
No resource is leaked on any return path.
Note
Not thread-safe; single-caller boot context.
Since
0.1.0

Definition at line 268 of file main.c.

References k_demo_block, k_demo_lbn_mul, k_demo_one_block, k_demo_seed_mul, k_ra8_err_checksum_mismatch, memcmp(), RA8_CHECK_NULL_PTR, ra8_ftl_phys_of(), ra8_io_blockdev_read(), ra8_io_blockdev_write(), RA8_RETURN_ON_ERROR, s_ftl, s_present, and s_tag.

Referenced by demo_wear_phase().

◆ main()

void main ( void )

Firmware entry point.

The application entry point Reset_Handler hands control to.

Initialises logging + console, brings up the MRAM volume, runs the wear-levelling + power-cycle-survival flow, and prints a single PASS/FAIL verdict.

Precondition
SystemInit configured VTOR / FPU / priority grouping.
The extra-MRAM region is present (modelled in ra8_emulator, real on silicon).
Postcondition
Exactly one PASS or FAIL verdict line has been queued on SCI8.
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 583 of file main.c.

References demo_open(), demo_print(), demo_run(), demo_setup_or_halt(), k_demo_uart_chan, k_ra8_ok, ra8_io_log_attach(), ra8_io_stream_uart_init(), ra8_log_init(), ra8_sci_flush(), s_uart, and s_ust.

Variable Documentation

◆ k_demo_rxd

const ra8_port_pin_t k_demo_rxd
static
Initial value:
=
(ra8_port_pin_t)(((uint16_t)k_ra8_port_13 << (uint16_t)k_demo_pin_shift) | (uint16_t)k_ra8_pin_3)
@ k_demo_pin_shift
Port byte position in ra8_port_pin_t.
Definition main.c:62
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 RXD = PD03.

Definition at line 92 of file main.c.

◆ k_demo_txd

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

SCI8 console TXD = PD02.

Definition at line 89 of file main.c.

◆ s_bd

ra8_io_blockdev_t s_bd
static

Raw MRAM block-device handle + its backend state.

Definition at line 96 of file main.c.

◆ s_ckbuf

uint8_t s_ckbuf[(size_t) k_demo_block]
static

One-block checkpoint buffer (the reserved MRAM slot holds this).

Definition at line 106 of file main.c.

Referenced by demo_checkpoint(), and demo_restore().

◆ s_ftl

ra8_ftl_t s_ftl
static

FTL handle + the presented free-overwrite block device.

Definition at line 99 of file main.c.

Referenced by demo_checkpoint(), demo_reopen_naive(), demo_report_wear(), demo_restore(), demo_wear_phase(), and demo_write_verify().

◆ s_map

uint16_t s_map[(size_t) k_demo_ftl_logical]
static

FTL caller storage: map, per-physical metadata, copy scratch.

Definition at line 102 of file main.c.

Referenced by demo_reopen_naive(), and demo_wear_phase().

◆ s_mstate

Definition at line 97 of file main.c.

Referenced by demo_open(), and internal_demo_open().

◆ s_pblocks

ra8_ftl_pblock_t s_pblocks[(size_t) k_demo_ftl_phys]
static

Definition at line 103 of file main.c.

Referenced by demo_reopen_naive(), and demo_wear_phase().

◆ s_present

ra8_io_blockdev_t s_present
static

Definition at line 100 of file main.c.

Referenced by demo_reopen_naive(), demo_restore(), demo_wear_phase(), and demo_write_verify().

◆ s_scratch

uint8_t s_scratch[(size_t) k_demo_block]
static

Definition at line 104 of file main.c.

◆ s_tag

const char* const s_tag = "ra8_ftl_demo"
static

Module log tag.

Definition at line 112 of file main.c.

◆ s_uart

ra8_io_stream_t s_uart
static

UART output stream + its sink state.

Definition at line 108 of file main.c.

◆ s_ust

Definition at line 109 of file main.c.