ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
main.c
Go to the documentation of this file.
1
43
44#include <stdint.h>
45#include <string.h>
46
47#include "ra8_boot_entry.h"
48#include "ra8_cgc.h"
49#include "ra8_check.h"
50#include "ra8_err.h"
51#include "ra8_flash.h"
52#include "ra8_ftl.h"
53#include "ra8_io.h"
54#include "ra8_log.h"
55#include "ra8_port_constants.h"
56#include "ra8_port_utils.h"
57#include "ra8_sci.h"
58#include "ra8_time.h"
59
64typedef enum : uintptr_t {
67
87
90 (ra8_port_pin_t)(((uint16_t)k_ra8_port_13 << (uint16_t)k_demo_pin_shift) | (uint16_t)k_ra8_pin_2);
93 (ra8_port_pin_t)(((uint16_t)k_ra8_port_13 << (uint16_t)k_demo_pin_shift) | (uint16_t)k_ra8_pin_3);
94
102static uint16_t s_map[(size_t)k_demo_ftl_logical];
104static uint8_t s_scratch[(size_t)k_demo_block];
106static uint8_t s_ckbuf[(size_t)k_demo_block];
110
112static const char* const s_tag = "ra8_ftl_demo";
113
131static void demo_print(const char* msg)
132{
133 (void)ra8_io_stream_puts(&s_uart, msg);
134}
135
155static void demo_report_map(uint32_t lbn, uint16_t phys)
156{
157 demo_print("ra8_ftl_demo: logical ");
158 (void)ra8_io_stream_put_u32(&s_uart, lbn);
159 demo_print(" now at physical ");
160 (void)ra8_io_stream_put_u32(&s_uart, (uint32_t)phys);
161 demo_print("\r\n");
162}
163
180static void demo_setup_or_halt(void)
181{
182 uint32_t cpuclk0_hz = 0U;
183 uint32_t pclka_hz = 0U;
184 if ((ra8_cgc_init() != k_ra8_ok) ||
187 (ra8_time_init(cpuclk0_hz) != k_ra8_ok) ||
190 while (true) {
191 }
192 }
193 const ra8_sci_cfg_t sci_cfg = {.baud = (uint32_t)k_demo_uart_baud,
194 .data_bits = k_ra8_sci_data_8,
195 .parity = k_ra8_sci_parity_none,
196 .stop_bits = k_ra8_sci_stop_1,
197 .pclk_hz = pclka_hz};
198 if (ra8_sci_init((uint8_t)k_demo_uart_chan, &sci_cfg) != k_ra8_ok) {
199 while (true) {
200 }
201 }
202}
203
225{
226 const ra8_flash_cfg_t fcfg = {.mrcfreq_mhz = (uint16_t)k_demo_mrcfreq_mhz,
227 .mrefreq_mhz = (uint8_t)k_demo_mrefreq_mhz,
228 .prefetch_en = true,
229 .ecc_encoder_enable = true,
230 .ecc_decoder_enable = true};
231 RA8_RETURN_ON_ERROR(ra8_flash_init(&fcfg), s_tag, "flash init");
233 &s_mstate,
234 (uintptr_t)k_demo_mram_base,
235 (uint32_t)k_demo_total_blocks,
236 false),
237 s_tag,
238 "mram blockdev init");
239 return k_ra8_ok;
240}
241
268static ra8_err_t demo_write_verify(uint32_t lbn, uint32_t tag, uint16_t* out_phys)
269{
270 RA8_CHECK_NULL_PTR(out_phys, s_tag, "out_phys must not be nullptr");
271 uint8_t blk[(size_t)k_demo_block];
272 for (uint32_t i = 0; i < (uint32_t)k_demo_block; ++i) {
273 blk[i] = (uint8_t)((i * (uint32_t)k_demo_seed_mul) + (lbn * (uint32_t)k_demo_lbn_mul) + tag);
274 }
276 s_tag,
277 "write");
278 uint8_t got[(size_t)k_demo_block];
280 s_tag,
281 "read");
282 if (memcmp(got, blk, sizeof(blk)) != 0) {
284 }
285 return ra8_ftl_phys_of(&s_ftl, lbn, out_phys);
286}
287
313static ra8_err_t demo_wear_phase(uint32_t* migrations, uint16_t* last_phys)
314{
315 RA8_CHECK_NULL_PTR(migrations, s_tag, "migrations must not be nullptr");
316 RA8_CHECK_NULL_PTR(last_phys, s_tag, "last_phys must not be nullptr");
318 &s_bd,
319 s_map,
320 (uint32_t)k_demo_ftl_logical,
321 s_pblocks,
322 (uint32_t)k_demo_ftl_phys,
323 s_scratch),
324 s_tag,
325 "ftl init");
327 uint32_t moves = 0U;
328 uint16_t prev = (uint16_t)k_ra8_ftl_unmapped;
329 for (uint32_t k = 0; k < (uint32_t)k_demo_writes; ++k) {
330 uint16_t cur = 0U;
331 const ra8_err_t e =
332 demo_write_verify((uint32_t)k_demo_test_lbn, (uint32_t)k_demo_tag_base + k, &cur);
333 if (e != k_ra8_ok) {
334 return e;
335 }
336 demo_report_map((uint32_t)k_demo_test_lbn, cur);
337 if ((prev != (uint16_t)k_ra8_ftl_unmapped) && (cur != prev)) {
338 moves += 1U;
339 }
340 prev = cur;
341 }
342 *migrations = moves;
343 *last_phys = prev;
344 return k_ra8_ok;
345}
346
369{
370 uint32_t need = 0U;
371 RA8_RETURN_ON_ERROR(ra8_ftl_checkpoint_size(&s_ftl, &need), s_tag, "checkpoint size");
372 if (need > (uint32_t)k_demo_block) {
374 }
376 s_tag,
377 "checkpoint save");
380 s_tag,
381 "meta erase");
384 s_tag,
385 "meta write");
386 return k_ra8_ok;
387}
388
412{
413 (void)memset(&s_ftl, 0, sizeof(s_ftl));
414 (void)memset(s_map, 0, sizeof(s_map));
415 (void)memset(s_pblocks, 0, sizeof(s_pblocks));
416 (void)memset(&s_present, 0, sizeof(s_present));
418 &s_bd,
419 s_map,
420 (uint32_t)k_demo_ftl_logical,
421 s_pblocks,
422 (uint32_t)k_demo_ftl_phys,
423 s_scratch),
424 s_tag,
425 "ftl reinit");
427 uint8_t got[(size_t)k_demo_block];
430 s_tag,
431 "naive read");
432 for (uint32_t i = 0; i < (uint32_t)k_demo_block; ++i) {
433 if (got[i] != (uint8_t)k_ra8_io_erase_value_ones) {
435 }
436 }
437 return k_ra8_ok;
438}
439
465static ra8_err_t demo_restore(uint32_t want_tag, uint16_t want_phys)
466{
469 s_tag,
470 "meta read");
472 s_tag,
473 "checkpoint load");
474 uint8_t want[(size_t)k_demo_block] = {};
475 for (uint32_t i = 0; i < (uint32_t)k_demo_block; ++i) {
476 want[i] = (uint8_t)((i * (uint32_t)k_demo_seed_mul) +
477 ((uint32_t)k_demo_test_lbn * (uint32_t)k_demo_lbn_mul) + want_tag);
478 }
479 uint8_t got[(size_t)k_demo_block];
482 s_tag,
483 "restored read");
484 if (memcmp(got, want, sizeof(want)) != 0) {
486 }
487 uint16_t phys = 0U;
489 s_tag,
490 "restored map");
491 if (phys != want_phys) {
493 }
494 return k_ra8_ok;
495}
496
514static void demo_report_wear(void)
515{
516 uint32_t hi = 0U;
517 uint32_t lo = 0U;
518 if (ra8_ftl_wear_stats(&s_ftl, &hi, &lo) != k_ra8_ok) {
519 demo_print("ra8_ftl_demo: wear stats unavailable\r\n");
520 return;
521 }
522 demo_print("ra8_ftl_demo: wear erase-count max ");
523 (void)ra8_io_stream_put_u32(&s_uart, hi);
524 demo_print(" min ");
525 (void)ra8_io_stream_put_u32(&s_uart, lo);
526 demo_print("\r\n");
527}
528
548static ra8_err_t demo_run(void)
549{
550 uint32_t migrations = 0U;
551 uint16_t last_phys = 0U;
552 RA8_RETURN_ON_ERROR(demo_wear_phase(&migrations, &last_phys), s_tag, "wear phase");
554 if (migrations == 0U) {
555 return k_ra8_err_invalid_state; /* no relocation observed -- wear-levelling failed */
556 }
557 RA8_RETURN_ON_ERROR(demo_checkpoint(), s_tag, "checkpoint");
558 RA8_RETURN_ON_ERROR(demo_reopen_naive(), s_tag, "reopen naive");
559 demo_print("ra8_ftl_demo: naive re-open lost the mapping (reads erase value)\r\n");
561 demo_restore((uint32_t)k_demo_tag_base + (uint32_t)k_demo_writes - (uint32_t)k_demo_one_block,
562 last_phys),
563 s_tag,
564 "restore");
565 return k_ra8_ok;
566}
567
583void main(void)
584{
585 ra8_log_init();
588 (void)ra8_io_log_attach(&s_uart); /* route ra8_log into the UART stream too */
589 demo_print("ra8_ftl_demo: boot\r\n");
590
591 ra8_err_t e = demo_open();
592 if (e == k_ra8_ok) {
593 e = demo_run();
594 }
595 if (e == k_ra8_ok) {
596 demo_print("ra8_ftl_demo: wear-level + power-cycle-survive on extra MRAM PASS\r\n");
597 } else {
598 demo_print("ra8_ftl_demo: FAIL\r\n");
599 }
600 (void)ra8_sci_flush((uint8_t)k_demo_uart_chan);
601 while (true) {
602 }
603}
void main(void)
Secure fallback main entry point.
Definition main.c:37
demo_const_t
Console + volume + payload knobs (no magic numbers).
Definition main.c:56
@ k_demo_uart_baud
Console baud.
Definition main.c:58
@ k_demo_uart_chan
SCI8 J-Link OB console.
Definition main.c:57
@ k_demo_pin_shift
Port byte position in ra8_port_pin_t.
Definition main.c:62
@ k_demo_seed_mul
Test-pattern multiplier.
Definition main.c:63
static ra8_io_stream_uart_state_t s_ust
Definition main.c:89
static ra8_io_stream_t s_uart
UART output stream + its sink state.
Definition main.c:88
static uint8_t s_scratch[(size_t) k_ra8_compress_scratch_bytes]
Compressor scratch (one miniz tdefl_compressor) in SRAM.
Definition main.c:96
static ra8_io_blockdev_t s_bd
Block-device handle + its RAM backend state.
Definition main.c:52
static const ra8_port_pin_t k_demo_txd
SCI8 console TXD = PD02.
Definition main.c:50
static void demo_print(const char *msg)
Print a NUL-terminated string on the demo's UART stream.
Definition main.c:100
static const ra8_port_pin_t k_demo_rxd
SCI8 console RXD = PD03.
Definition main.c:53
static void demo_setup_or_halt(void)
Bring up CGC + SysTick + the SCI8 console; halt forever on any failure.
Definition main.c:123
static ra8_err_t demo_run(void)
Bring up the OSPI block device, then run the shared FAT round-trip.
Definition main.c:178
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.
Definition main.c:268
static void demo_report_wear(void)
Print the FTL wear spread (max/min erase counts across physical blocks).
Definition main.c:514
static ra8_io_blockdev_mram_state_t s_mstate
Definition main.c:97
demo_addr_t
Extra-MRAM window base address.
Definition main.c:64
@ k_demo_mram_base
Extra-MRAM OTP window base (0x02E07600).
Definition main.c:65
static uint8_t s_ckbuf[(size_t) k_demo_block]
One-block checkpoint buffer (the reserved MRAM slot holds this).
Definition main.c:106
static ra8_ftl_pblock_t s_pblocks[(size_t) k_demo_ftl_phys]
Definition main.c:103
static uint16_t s_map[(size_t) k_demo_ftl_logical]
FTL caller storage: map, per-physical metadata, copy scratch.
Definition main.c:102
static ra8_io_blockdev_t s_present
Definition main.c:100
@ k_demo_test_lbn
Logical block written repeatedly.
Definition main.c:77
@ k_demo_mrefreq_mhz
Extra-MRAM advertised clock (MHz).
Definition main.c:82
@ k_demo_tag_base
First generation tag.
Definition main.c:85
@ k_demo_block
Bytes per block.
Definition main.c:79
@ k_demo_meta_lba
Reserved raw block for the checkpoint.
Definition main.c:75
@ k_demo_writes
Repeated overwrites of the test block.
Definition main.c:78
@ k_demo_lbn_mul
Test-pattern logical-block bias.
Definition main.c:84
@ k_demo_ftl_logical
Logical blocks the FTL presents.
Definition main.c:74
@ k_demo_ftl_phys
Physical blocks handed to the FTL.
Definition main.c:73
@ k_demo_mrcfreq_mhz
Code-MRAM advertised clock (MHz).
Definition main.c:81
@ k_demo_total_blocks
Whole extra MRAM (12 KiB).
Definition main.c:72
@ k_demo_one_block
Single-block transfer count.
Definition main.c:76
static void demo_report_map(uint32_t lbn, uint16_t phys)
Print logical L now at physical P for one relocation observation.
Definition main.c:155
static ra8_err_t demo_open(void)
Bring up the MRAM controller and bind the raw MRAM block device.
Definition main.c:224
static ra8_err_t demo_reopen_naive(void)
Act 3a: model a reset and prove the naive re-open lost the mapping.
Definition main.c:411
static ra8_ftl_t s_ftl
FTL handle + the presented free-overwrite block device.
Definition main.c:99
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.
Definition main.c:313
static ra8_err_t demo_restore(uint32_t want_tag, uint16_t want_phys)
Act 3b: reload the checkpoint and prove data + mapping survived.
Definition main.c:465
static ra8_err_t demo_checkpoint(void)
Act 2: serialise the FTL mapping into the reserved MRAM block.
Definition main.c:368
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Boot entry points shared between a vector table and its startup code.
High-level Clock Generation Circuit driver.
ra8_err_t ra8_cgc_get_clock_hz(ra8_clock_id_t id, uint32_t *out_hz)
Query the current frequency of a clock-tree domain.
Definition ra8_cgc.c:132
@ k_ra8_clock_id_cpuclk0
Cortex-M85 CPUCLK0.
Definition ra8_cgc.h:70
@ k_ra8_clock_id_pclka
PCLKA.
Definition ra8_cgc.h:73
ra8_err_t ra8_cgc_init(void)
Configure the clock tree to a safe default.
Definition ra8_cgc.c:727
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_RETURN_ON_ERROR(err, tag, message)
Early return on error, propagating the code upward.
Definition ra8_check.h:184
#define RA8_CHECK_NULL_PTR(ptr, tag, message)
Reject nullptr pointer, returning k_ra8_err_null_ptr.
Definition ra8_check.h:243
Error Code Definitions for ra8-firmware.
@ k_ra8_err_checksum_mismatch
Stored / transmitted checksum does not match computed value.
Definition ra8_err.h:465
@ k_ra8_err_invalid_state
Module in wrong state for requested operation.
Definition ra8_err.h:161
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_invalid_size
Invalid size parameter (too large, too small, or misaligned).
Definition ra8_err.h:167
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Code MRAM + Extra MRAM + Option-Setting driver – DANGEROUS, brick-capable.
ra8_err_t ra8_flash_init(const ra8_flash_cfg_t *cfg)
Initialise the MRAM controller for safe read access.
Definition ra8_flash.c:386
@ k_ra8_flash_extra_start
First legal Program target (FSBL setting).
void * memset(void *dst, int value, size_t n)
Fill memory with a constant byte value.
int memcmp(const void *a, const void *b, size_t n)
Compare bytes in two memory areas.
Flash Translation Layer – free overwrite over erase-before-write media.
@ k_ra8_ftl_unmapped
map[] sentinel: logical block unwritten.
Definition ra8_ftl.h:119
ra8_err_t ra8_ftl_checkpoint_load(ra8_ftl_t *ftl, const uint8_t *buf, uint32_t buf_len)
Restore FTL mapping state from a checkpoint produced by save.
ra8_err_t ra8_ftl_checkpoint_save(const ra8_ftl_t *ftl, uint8_t *buf, uint32_t buf_len)
Serialise the FTL's mapping state into a caller buffer.
ra8_err_t ra8_ftl_wear_stats(const ra8_ftl_t *ftl, uint32_t *max_out, uint32_t *min_out)
Report the highest per-physical-block erase count seen so far.
Definition ra8_ftl.c:769
ra8_err_t ra8_ftl_init(ra8_ftl_t *bd, const ra8_io_blockdev_t *raw, uint16_t *map, uint32_t logical_blocks, ra8_ftl_pblock_t *pblocks, uint32_t physical_blocks, uint8_t *scratch)
Initialise an FTL over an erase-before-write block device.
Definition ra8_ftl.c:724
ra8_err_t ra8_ftl_checkpoint_size(const ra8_ftl_t *ftl, uint32_t *size_out)
Report the buffer size a checkpoint of this FTL requires, in bytes.
ra8_err_t ra8_ftl_as_blockdev(ra8_ftl_t *ftl, ra8_io_blockdev_t *out)
Expose an initialised FTL as a free-overwrite ra8_io_blockdev_t.
Definition ra8_ftl.c:757
ra8_err_t ra8_ftl_phys_of(const ra8_ftl_t *ftl, uint32_t lbn, uint16_t *phys_out)
Report the physical block currently backing a logical block.
Definition ra8_ftl.c:793
@ k_ra8_psel_sci_async
00100b: SCI async serial (UART).
ra8_io – unified peripheral-agnostic I/O fabric (umbrella header).
ra8_err_t ra8_io_blockdev_read(const ra8_io_blockdev_t *bd, uint32_t lba, uint32_t count, uint8_t *buf)
Read count logical blocks starting at lba into buf.
@ k_ra8_io_erase_value_ones
Block reads back as 0xFF after erase.
ra8_err_t ra8_io_blockdev_write(const ra8_io_blockdev_t *bd, uint32_t lba, uint32_t count, const uint8_t *buf)
Write count logical blocks from buf starting at lba.
ra8_err_t ra8_io_blockdev_erase(const ra8_io_blockdev_t *bd, uint32_t lba, uint32_t count)
Erase count blocks starting at lba to the medium's erase value.
ra8_err_t ra8_io_blockdev_mram_init(ra8_io_blockdev_t *bd, ra8_io_blockdev_mram_state_t *state, uintptr_t base_addr, uint32_t block_count, bool read_only)
Bind a hard-fenced MRAM block-device backend into a caller handle.
ra8_err_t ra8_io_log_attach(ra8_io_stream_t *s)
Route ra8_log output to a bound ra8_io stream.
Definition ra8_io_log.c:61
ra8_err_t ra8_io_stream_puts(ra8_io_stream_t *s, const char *str)
Write a NUL-terminated string (without the NUL) to the bound sink.
ra8_err_t ra8_io_stream_put_u32(ra8_io_stream_t *s, uint32_t value)
Write value as unsigned decimal ASCII (no leading zeros).
ra8_err_t ra8_io_stream_uart_init(ra8_io_stream_t *s, ra8_io_stream_uart_state_t *state, uint8_t channel)
Bind a UART stream sink into a caller-owned stream handle.
Lightweight Logging Interface for ra8-firmware.
void ra8_log_init(void)
Initialise the logging backend.
Definition ra8_log.c:379
Typed Port / Pin Constants for the RA8D2 IOPORT Module.
ra8_port_pin_t
Packed (port << 8) | pin pin identifier.
@ k_ra8_port_13
RA8 port 13.
@ k_ra8_pin_2
RA8 pin 2.
@ k_ra8_pin_3
RA8 pin 3.
High-level GPIO helpers on top of the PORT + PFS register layer.
ra8_err_t ra8_pfs_route_peripheral(ra8_port_pin_t pin, ra8_psel_t psel, const char *owner)
Route a pin to a non-IRQ peripheral function via PFS.PSEL.
Definition gpio.c:238
Full-featured Serial Communications Interface driver.
@ k_ra8_sci_stop_1
RA8 SCI stop 1.
Definition ra8_sci.h:81
@ k_ra8_sci_parity_none
RA8 SCI parity none.
Definition ra8_sci.h:71
ra8_err_t ra8_sci_init(uint8_t channel, const ra8_sci_cfg_t *cfg)
Initialise an SCI channel using the descriptor.
Definition ra8_sci.c:410
@ k_ra8_sci_data_8
RA8 SCI data 8.
Definition ra8_sci.h:91
ra8_err_t ra8_sci_flush(uint8_t channel)
Block until the channel's transmit shift register is empty.
Definition ra8_sci.c:543
SysTick-based tick counter, delay and timestamp helpers.
ra8_err_t ra8_time_init(uint32_t cpu_hz)
Initialise SysTick for a 1 kHz tick interrupt.
Definition ra8_time.c:59
Initialisation descriptor for ra8_flash_init.
Caller-owned metadata for one physical erase block.
Definition ra8_ftl.h:162
Caller-allocated FTL handle binding the wrapper to the raw device.
Definition ra8_ftl.h:190
Caller-owned private state for an MRAM block device.
Caller-allocated block-device handle binding a backend to its context.
Caller-allocated byte-stream handle binding a sink to its context.
Caller-owned private state for a UART stream sink.
Configuration descriptor for ra8_sci_init.
Definition ra8_sci.h:103