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

ra8_cache_store mount/recovery path + shared on-flash helpers (#201). More...

#include <stdint.h>
#include <string.h>
#include "lx_api.h"
#include "ra8_cache_store.h"
#include "ra8_cache_store_internal.h"
#include "ra8_check.h"
#include "ra8_err.h"
Include dependency graph for ra8_cache_store_mount.c:

Go to the source code of this file.

Enumerations

enum  ra8_cs_shift_t : uint32_t {
  k_ra8_cs_crc_bits = 8U ,
  k_ra8_cs_pct_full = 100U
}
 Small fixed quantities for CRC folding and dir packing. More...

Functions

uint32_t priv_cache_store_crc32 (const uint8_t *data, uint32_t len)
 Fold a byte block into a CRC-32/ISO-HDLC value (seeded + finalised).
ra8_err_t priv_cache_store_sector_read (const ra8_cache_store_t *store, uint32_t sector, uint8_t *out512)
 Read one LevelX logical sector into the store staging buffer region.
ra8_err_t priv_cache_store_sector_write (ra8_cache_store_t *store, uint32_t sector, const uint8_t *in512)
 Write one LevelX logical sector from a one-sector source buffer.
ra8_err_t priv_cache_store_sector_release (ra8_cache_store_t *store, uint32_t sector)
 Release a LevelX logical sector back to the free pool.
int32_t priv_cache_store_index_find (const ra8_cache_store_t *store, uint32_t key)
 Find the index slot holding key.
int32_t priv_cache_store_index_add (ra8_cache_store_t *store, uint32_t key, uint32_t start_sector, uint16_t sector_count, uint32_t byte_len, bool pinned)
 Claim a free index slot and populate it for key.
ra8_err_t priv_cache_store_super_write (ra8_cache_store_t *store, uint32_t clean)
 Write the superblock (sector 0) with the given clean marker.
static ra8_err_t internal_super_read (ra8_cache_store_t *store, ra8_cs_super_t *out_sb)
 Read + parse the superblock (sector 0) into out_sb.
static bool internal_super_is_clean (const ra8_cs_super_t *sb)
 True when sb is a valid, clean-shutdown superblock.
static uint32_t internal_dir_pack_sector (ra8_cache_store_t *store, uint16_t *slot, uint8_t *out512)
 Pack up to one sector of in-use index entries into out512.
ra8_err_t priv_cache_store_dir_save (ra8_cache_store_t *store, uint32_t *out_entry_count)
 Serialize the live index into the on-flash checkpoint directory.
static void internal_dir_unpack_sector (ra8_cache_store_t *store, const uint8_t *in512, uint32_t *loaded, uint32_t entry_count)
 Unpack one directory sector into the index, up to entry_count total.
static ra8_err_t internal_dir_load (ra8_cache_store_t *store, uint32_t entry_count)
 Load entry_count directory entries from the checkpoint into the index.
static bool internal_hdr_read (ra8_cache_store_t *store, uint32_t s, ra8_cs_entry_hdr_t *out_hdr)
 Read + validate the entry header at logical sector s.
static void internal_scan_accept (ra8_cache_store_t *store, const ra8_cs_entry_hdr_t *h, uint32_t *max_seq)
 Fold one validated header into the index, tracking the max sequence.
static ra8_err_t internal_scan_log (ra8_cache_store_t *store)
 Replay the append log to rebuild the index after an unclean shutdown.
static ra8_err_t internal_validate_cfg (const ra8_cache_store_cfg_t *cfg)
 Validate the init config's required members and sizes.
static ra8_err_t internal_geometry (ra8_cache_store_t *store, const ra8_cache_store_cfg_t *cfg)
 Derive the store geometry (checkpoint span, log start, budget).
static ra8_err_t internal_open_levelx (ra8_cache_store_t *store, const ra8_cache_store_cfg_t *cfg)
 Bring the injected LevelX NOR partition up (format on request, open).
static ra8_err_t internal_recover (ra8_cache_store_t *store, const ra8_cs_super_t *sb)
 Rebuild the index from a parsed superblock: checkpoint load or replay.
static ra8_err_t internal_mount (ra8_cache_store_t *store)
 Mount an open partition: read sector 0, then recover the index.
static void internal_init_fields (ra8_cache_store_t *store, const ra8_cache_store_cfg_t *cfg)
 Bind the caller-owned buffers into the store and reset its counters.
static ra8_err_t internal_bringup (ra8_cache_store_t *store, const ra8_cache_store_cfg_t *cfg)
 Derive geometry, open the LevelX partition, and mount the index.
ra8_err_t ra8_cache_store_init (ra8_cache_store_t *store, const ra8_cache_store_cfg_t *cfg)
 Bind a LevelX NOR flash instance and mount (or format) the store.

Variables

static const char *const s_tag = "ra8_cache_store"
 Module log tag.
static bool s_cs_lx_system_inited = false
 One-shot latch so LevelX's global open-list is initialised once.

Detailed Description

ra8_cache_store mount/recovery path + shared on-flash helpers (#201).

Tag
[Ring 4 / Storage] {World: NS}

Owns ra8_cache_store_init and the crash-recovery machinery: superblock read/write, directory-checkpoint save/load, and the append-log scan that replays after an unclean shutdown. Also defines the low-level helpers (CRC-32, LevelX sector read/write/release, index find/add) shared with the runtime TU. Runs LevelX through its public lx_nor_flash_* API only.

Definition in file ra8_cache_store_mount.c.

Enumeration Type Documentation

◆ ra8_cs_shift_t

enum ra8_cs_shift_t : uint32_t

Small fixed quantities for CRC folding and dir packing.

Since
0.1.0
Enumerator
k_ra8_cs_crc_bits 

Bits folded per input byte.

k_ra8_cs_pct_full 

Whole-percent denominator for the margin.

Definition at line 46 of file ra8_cache_store_mount.c.

Function Documentation

◆ internal_bringup()

ra8_err_t internal_bringup ( ra8_cache_store_t * store,
const ra8_cache_store_cfg_t * cfg )
static

Derive geometry, open the LevelX partition, and mount the index.

The three-step bring-up after the store buffers are bound: geometry, LevelX open (with the format-time clean superblock), then mount.

Parameters
[in,out]storeStore with its buffers already bound.
[in]cfgValidated config.
Returns
Error code.
Return values
k_ra8_okGeometry set, partition open, index mounted.
k_ra8_err_null_ptrstore or cfg NULL.
k_ra8_err_invalid_sizelogical_sectors too small for the layout.
k_ra8_err_hw_init_failedLevelX open/format/I-O error.
k_ra8_err_invalid_stateCheckpoint directory inconsistent.
Precondition
store buffers are bound (internal_init_fields ran).
cfg passed internal_validate_cfg.
Postcondition
On k_ra8_ok the store is ready except for inited.
On error the store is not usable.
Note
Not thread-safe; single-threaded bring-up.
Since
0.1.0

Definition at line 783 of file ra8_cache_store_mount.c.

References internal_geometry(), internal_mount(), internal_open_levelx(), k_ra8_ok, RA8_CHECK_NULL_PTR, RA8_INTERNAL, RA8_RETURN_ON_ERROR, and s_tag.

Referenced by ra8_cache_store_init().

◆ internal_dir_load()

ra8_err_t internal_dir_load ( ra8_cache_store_t * store,
uint32_t entry_count )
static

Load entry_count directory entries from the checkpoint into the index.

Reads each checkpoint directory sector and hands it to internal_dir_unpack_sector until the recorded entry count is loaded.

Parameters
[in,out]storeStore whose index is rebuilt.
[in]entry_countEntries the superblock recorded.
Returns
Error code.
Return values
k_ra8_okDirectory loaded; live_sectors accumulated.
k_ra8_err_invalid_stateentry_count exceeds the index capacity.
k_ra8_err_hw_init_failedLevelX read error.
Precondition
store->checkpoint_dirs directory sectors exist on flash.
entry_count <= store->index_cap.
Postcondition
On k_ra8_ok the index holds every checkpoint entry.
store->live_sectors equals the loaded run total.
Note
Not thread-safe; shares the store staging buffer.
Since
0.1.0

Definition at line 399 of file ra8_cache_store_mount.c.

References ra8_cache_store_t::checkpoint_dirs, ra8_cache_store_t::index_cap, internal_dir_unpack_sector(), k_ra8_err_invalid_state, k_ra8_ok, ra8_cache_store_t::live_sectors, priv_cache_store_sector_read(), RA8_CHECK_NULL_PTR, RA8_INTERNAL, RA8_RETURN_ON_ERROR, s_tag, and ra8_cache_store_t::staging.

Referenced by internal_recover().

◆ internal_dir_pack_sector()

uint32_t internal_dir_pack_sector ( ra8_cache_store_t * store,
uint16_t * slot,
uint8_t * out512 )
static

Pack up to one sector of in-use index entries into out512.

Zeroes the sector, then serializes the next run of in-use slots (advancing slot past them) until the sector is full or the index is exhausted.

Parameters
[in]storeStore whose index is serialized.
[in,out]slotCursor into the index; advanced past packed slots.
[out]out512One-sector destination buffer.
Returns
Number of entries packed into this sector.
Return values
0No more in-use entries (or a NULL argument).
Precondition
store->index covers store->index_cap slots.
out512 covers one sector.
Postcondition
*slot points past the last packed entry.
out512 holds <= k_ra8_cs_dir_per_sector serialized entries.
Note
Not thread-safe; the store serialises access.
Since
0.1.0

Definition at line 287 of file ra8_cache_store_mount.c.

References ra8_cache_store_entry_t::byte_len, ra8_cache_store_entry_t::flags, ra8_cache_store_t::index, ra8_cache_store_t::index_cap, k_ra8_cache_store_flag_in_use, k_ra8_cache_store_flag_pinned, k_ra8_cache_store_sector_bytes, k_ra8_cs_dir_ent_bytes, k_ra8_cs_dir_per_sector, ra8_cache_store_entry_t::key, memcpy(), memset(), ra8_cache_store_entry_t::sector_count, and ra8_cache_store_entry_t::start_sector.

Referenced by priv_cache_store_dir_save().

◆ internal_dir_unpack_sector()

void internal_dir_unpack_sector ( ra8_cache_store_t * store,
const uint8_t * in512,
uint32_t * loaded,
uint32_t entry_count )
static

Unpack one directory sector into the index, up to entry_count total.

Deserializes each ra8_cs_dir_ent_t in in512, adds it to the index, accumulates its run into live_sectors, and advances loaded, until the sector is exhausted or entry_count entries are loaded.

Parameters
[in,out]storeStore whose index gains entries.
[in]in512One directory sector read from flash.
[in,out]loadedRunning count of entries loaded so far.
[in]entry_countTotal entries the checkpoint recorded.
Returns
Nothing.
Precondition
store->index covers store->index_cap slots.
in512 covers one sector; loaded is writable.
Postcondition
*loaded <= entry_count and grows by the entries in this sector.
store->live_sectors grows by the loaded runs.
Note
Not thread-safe; the store serialises access.
Since
0.1.0

Definition at line 353 of file ra8_cache_store_mount.c.

References ra8_cs_dir_ent_t::byte_len, ra8_cs_dir_ent_t::flags, k_ra8_cache_store_flag_pinned, k_ra8_cs_dir_ent_bytes, k_ra8_cs_dir_per_sector, ra8_cs_dir_ent_t::key, ra8_cache_store_t::live_sectors, memcpy(), priv_cache_store_index_add(), RA8_INTERNAL, ra8_cs_dir_ent_t::sector_count, and ra8_cs_dir_ent_t::start_sector.

Referenced by internal_dir_load().

◆ internal_geometry()

ra8_err_t internal_geometry ( ra8_cache_store_t * store,
const ra8_cache_store_cfg_t * cfg )
static

Derive the store geometry (checkpoint span, log start, budget).

Derives the checkpoint span from index_cap, the log-start sector, and the overprovisioned live-sector budget from the margin.

Parameters
[out]storeStore whose geometry fields are set.
[in]cfgValidated config.
Returns
Error code.
Return values
k_ra8_okGeometry derived and stored.
k_ra8_err_invalid_sizelogical_sectors too small for the layout.
Precondition
store and cfg are non-NULL.
cfg passed internal_validate_cfg.
Postcondition
On k_ra8_ok, log_start < logical_sectors and data_capacity > 0.
On error store geometry is left partially set (init aborts).
Note
Not thread-safe; the store serialises access.
Since
0.1.0

Definition at line 602 of file ra8_cache_store_mount.c.

References ra8_cache_store_t::checkpoint_dirs, ra8_cache_store_t::data_capacity, ra8_cache_store_cfg_t::index_cap, k_ra8_cache_store_min_sectors, k_ra8_cache_store_overprov_pct, k_ra8_cs_dir_per_sector, k_ra8_cs_pct_full, k_ra8_err_invalid_size, k_ra8_ok, ra8_cache_store_t::log_start, ra8_cache_store_cfg_t::logical_sectors, ra8_cache_store_t::logical_sectors, ra8_cache_store_cfg_t::overprovision_pct, RA8_CHECK_NULL_PTR, RA8_INTERNAL, and s_tag.

Referenced by internal_bringup().

◆ internal_hdr_read()

bool internal_hdr_read ( ra8_cache_store_t * store,
uint32_t s,
ra8_cs_entry_hdr_t * out_hdr )
static

Read + validate the entry header at logical sector s.

Reads sector s and accepts it only as a self-anchored, CRC-sealed, in-bounds entry header; any failed check means no run starts here (an empty/torn sector or a stray payload sector).

Parameters
[in]storeStore to read from.
[in]sCandidate header sector.
[out]out_hdrReceives the parsed header when valid.
Returns
Whether a complete, self-consistent header lives at s.
Return values
trueA valid header anchored at s was read.
falseThe sector missed, or the record failed a check.
Precondition
store->staging covers one sector.
out_hdr is writable.
Postcondition
On true, out_hdr->start_sector == s.
On false, no run is claimed at s.
Note
Not thread-safe; shares the store staging buffer.
Since
0.1.0

Definition at line 443 of file ra8_cache_store_mount.c.

References ra8_cs_entry_hdr_t::hdr_crc, k_ra8_cs_entry_magic, k_ra8_ok, ra8_cache_store_t::logical_sectors, ra8_cs_entry_hdr_t::magic, memcpy(), priv_cache_store_crc32(), priv_cache_store_sector_read(), ra8_cs_entry_hdr_t::sector_count, ra8_cache_store_t::staging, and ra8_cs_entry_hdr_t::start_sector.

Referenced by internal_scan_log().

◆ internal_init_fields()

void internal_init_fields ( ra8_cache_store_t * store,
const ra8_cache_store_cfg_t * cfg )
static

Bind the caller-owned buffers into the store and reset its counters.

Zeroes the handle, records the LevelX control block, index, and staging, clears every index slot, and seeds the sequence + live counters. Sets no geometry (internal_geometry does that next).

Parameters
[out]storeStore handle to populate.
[in]cfgValidated config.
Returns
Nothing.
Precondition
cfg passed internal_validate_cfg (buffers non-NULL, index_cap > 0).
store is the caller-owned handle.
Postcondition
store->index is fully cleared and the counters are seeded.
store->inited is false (init sets it last).
Note
Not thread-safe; the store serialises access.
Since
0.1.0

Definition at line 743 of file ra8_cache_store_mount.c.

References ra8_cache_store_t::flash, ra8_cache_store_cfg_t::index, ra8_cache_store_t::index, ra8_cache_store_cfg_t::index_cap, ra8_cache_store_t::index_cap, ra8_cache_store_t::live_sectors, ra8_cache_store_t::next_seq, ra8_cache_store_cfg_t::nor_flash, RA8_INTERNAL, ra8_cache_store_cfg_t::staging, and ra8_cache_store_t::staging.

Referenced by ra8_cache_store_init().

◆ internal_mount()

ra8_err_t internal_mount ( ra8_cache_store_t * store)
static

Mount an open partition: read sector 0, then recover the index.

Reads the superblock (read-only) and hands it to internal_recover. Because init stamps a clean superblock at format time, a fresh or cleanly closed store loads its checkpoint; only a genuine unclean shutdown replays the log.

Parameters
[in,out]storeOpen store to mount.
Returns
Error code.
Return values
k_ra8_okIndex recovered; flash_state set.
k_ra8_err_hw_init_failedLevelX I/O error.
k_ra8_err_invalid_stateCheckpoint directory inconsistent.
Precondition
The LevelX partition is open.
store geometry and staging are set.
Postcondition
On k_ra8_ok the index reflects flash; no flash sector was written.
On error the store is not usable.
Note
Not thread-safe; shares the store staging buffer.
Since
0.1.0

Definition at line 719 of file ra8_cache_store_mount.c.

References internal_recover(), internal_super_read(), RA8_CHECK_NULL_PTR, RA8_INTERNAL, RA8_RETURN_ON_ERROR, s_tag, and ra8_cache_store_t::staging.

Referenced by internal_bringup().

◆ internal_open_levelx()

ra8_err_t internal_open_levelx ( ra8_cache_store_t * store,
const ra8_cache_store_cfg_t * cfg )
static

Bring the injected LevelX NOR partition up (format on request, open).

Initialises the LevelX system once (latched), optionally formats, then opens the partition through the injected driver.

Parameters
[in,out]storeStore holding the LevelX control block pointer.
[in]cfgValidated config (driver-init seam, name, format flag).
Returns
Error code.
Return values
k_ra8_okPartition open.
k_ra8_err_hw_init_failedLevelX format or open failed.
Precondition
cfg->nor_driver_init populates the LevelX control block.
store->flash points at caller-owned LevelX storage.
Postcondition
On k_ra8_ok the partition is open for sector I/O.
On error the partition is not usable.
Note
Not thread-safe; single-threaded bring-up.
Since
0.1.0

Definition at line 641 of file ra8_cache_store_mount.c.

References ra8_cache_store_t::flash, ra8_cache_store_cfg_t::format, k_ra8_cs_clean, k_ra8_err_hw_init_failed, k_ra8_ok, ra8_cache_store_cfg_t::name, ra8_cache_store_cfg_t::nor_driver_init, priv_cache_store_super_write(), RA8_CHECK_NULL_PTR, RA8_INTERNAL, RA8_RETURN_ON_ERROR, s_cs_lx_system_inited, and s_tag.

Referenced by internal_bringup().

◆ internal_recover()

ra8_err_t internal_recover ( ra8_cache_store_t * store,
const ra8_cs_super_t * sb )
static

Rebuild the index from a parsed superblock: checkpoint load or replay.

A clean, valid superblock loads its checkpoint directory; anything else replays the append log. Sets flash_state to match.

Parameters
[in,out]storeStore whose index is rebuilt.
[in]sbParsed superblock from sector 0.
Returns
Error code.
Return values
k_ra8_okIndex rebuilt.
k_ra8_err_invalid_stateCheckpoint directory inconsistent.
k_ra8_err_hw_init_failedLevelX I/O error.
Precondition
sb was populated by internal_super_read.
The LevelX partition is open.
Postcondition
On k_ra8_ok the index reflects flash and flash_state is set.
No flash sector is written.
Note
Not thread-safe; shares the store staging buffer.
Since
0.1.0

Definition at line 688 of file ra8_cache_store_mount.c.

References ra8_cs_super_t::entry_count, ra8_cache_store_t::flash_state, internal_dir_load(), internal_scan_log(), internal_super_is_clean(), k_ra8_cs_clean, k_ra8_cs_dirty, ra8_cache_store_t::next_seq, ra8_cs_super_t::next_seq, RA8_CHECK_NULL_PTR, RA8_INTERNAL, and s_tag.

Referenced by internal_mount().

◆ internal_scan_accept()

void internal_scan_accept ( ra8_cache_store_t * store,
const ra8_cs_entry_hdr_t * h,
uint32_t * max_seq )
static

Fold one validated header into the index, tracking the max sequence.

Adds the entry when its key is new; a duplicate key or a full index is skipped so the scan stays bounded.

Parameters
[in,out]storeStore whose index gains the entry.
[in]hValidated entry header.
[in,out]max_seqRunning maximum append sequence number.
Returns
Nothing.
Precondition
h passed internal_hdr_read.
max_seq is writable.
Postcondition
The run is indexed and store->live_sectors grows by its length.
*max_seq >= h.seq.
Note
Not thread-safe; the store serialises access.
Since
0.1.0

Definition at line 486 of file ra8_cache_store_mount.c.

References ra8_cs_entry_hdr_t::byte_len, ra8_cs_entry_hdr_t::flags, k_ra8_cache_store_flag_pinned, ra8_cs_entry_hdr_t::key, ra8_cache_store_t::live_sectors, priv_cache_store_index_add(), priv_cache_store_index_find(), ra8_cs_entry_hdr_t::sector_count, ra8_cs_entry_hdr_t::seq, and ra8_cs_entry_hdr_t::start_sector.

Referenced by internal_scan_log().

◆ internal_scan_log()

ra8_err_t internal_scan_log ( ra8_cache_store_t * store)
static

Replay the append log to rebuild the index after an unclean shutdown.

Walks [log_start, logical_sectors); a valid header claims its run (skip its payload), anything else advances one sector. A torn tail (payload written, header not) has no valid header and is discarded.

Parameters
[in,out]storeStore to rebuild.
Returns
Error code.
Return values
k_ra8_okIndex rebuilt from surviving entries.
k_ra8_err_null_ptrstore NULL.
Precondition
store geometry (log_start, logical_sectors) is set.
store->staging covers one sector.
Postcondition
store->live_sectors / store->next_seq reflect the survivors.
Partially-appended entries are not indexed.
Note
Not thread-safe; shares the store staging buffer.
Since
0.1.0

Definition at line 522 of file ra8_cache_store_mount.c.

References internal_hdr_read(), internal_scan_accept(), k_ra8_ok, ra8_cache_store_t::live_sectors, ra8_cache_store_t::log_start, ra8_cache_store_t::logical_sectors, ra8_cache_store_t::next_seq, RA8_CHECK_NULL_PTR, RA8_INTERNAL, s_tag, ra8_cs_entry_hdr_t::sector_count, and ra8_cache_store_t::staging.

Referenced by internal_recover().

◆ internal_super_is_clean()

bool internal_super_is_clean ( const ra8_cs_super_t * sb)
static

True when sb is a valid, clean-shutdown superblock.

Nested single-condition checks (magic, CRC, clean marker) so there is no compound decision to MC/DC.

Parameters
[in]sbParsed superblock candidate.
Returns
Whether the checkpoint directory may be trusted.
Return values
trueMagic + CRC valid and the clean marker is set.
falseAny check failed.
Precondition
sb points at a fully-read record.
The caller confirmed the sector was present.
Postcondition
sb is unmodified.
No I/O is performed.
Note
Thread-safe: pure over its argument (no I/O).
Since
0.1.0

Definition at line 246 of file ra8_cache_store_mount.c.

References ra8_cs_super_t::clean, ra8_cs_super_t::crc, k_ra8_cs_clean, k_ra8_cs_super_magic, ra8_cs_super_t::magic, priv_cache_store_crc32(), and RA8_INTERNAL.

Referenced by internal_recover().

◆ internal_super_read()

ra8_err_t internal_super_read ( ra8_cache_store_t * store,
ra8_cs_super_t * out_sb )
static

Read + parse the superblock (sector 0) into out_sb.

An unreadable sector 0 (the rare LevelX allocation-failure miss) is treated as an invalid superblock – out_sb is zeroed so the caller falls back to a log replay. On a formatted device LevelX returns a real record (a clean one written at format time, or 0xFF on a raw device), so this never needs a separate "absent" case.

Parameters
[in]storeStore to read from.
[out]out_sbReceives the parsed (or zeroed) superblock.
Returns
Error code.
Return values
k_ra8_okSector 0 parsed, or zeroed on an unreadable miss.
Precondition
store->staging covers one sector.
out_sb is writable.
Postcondition
*out_sb is always populated (real record or all-zero).
No flash sector is written.
Note
Not thread-safe; shares the store staging buffer.
Since
0.1.0

Definition at line 219 of file ra8_cache_store_mount.c.

References k_ra8_ok, memcpy(), memset(), priv_cache_store_sector_read(), RA8_CHECK_NULL_PTR, RA8_INTERNAL, s_tag, and ra8_cache_store_t::staging.

Referenced by internal_mount().

◆ internal_validate_cfg()

ra8_err_t internal_validate_cfg ( const ra8_cache_store_cfg_t * cfg)
static

Validate the init config's required members and sizes.

Checks each required pointer and the size / margin bounds in turn, before any flash is touched.

Parameters
[in]cfgConfig to validate.
Returns
Error code.
Return values
k_ra8_okConfig is usable.
k_ra8_err_null_ptrA required pointer member is NULL.
k_ra8_err_invalid_sizeindex_cap zero or staging_bytes too small.
k_ra8_err_invalid_argoverprovision_pct out of range.
Precondition
cfg is non-NULL.
The caller wants the store bound to cfg->nor_flash.
Postcondition
No state is modified (pure validation).
On k_ra8_ok every dependency needed by init is present.
Note
Thread-safe: pure validation (no I/O).
Since
0.1.0

Definition at line 565 of file ra8_cache_store_mount.c.

References ra8_cache_store_cfg_t::index, ra8_cache_store_cfg_t::index_cap, k_ra8_cache_store_max_overprov, k_ra8_cache_store_sector_bytes, k_ra8_err_invalid_arg, k_ra8_err_invalid_size, k_ra8_err_null_ptr, k_ra8_ok, ra8_cache_store_cfg_t::nor_driver_init, ra8_cache_store_cfg_t::nor_flash, ra8_cache_store_cfg_t::overprovision_pct, RA8_CHECK_NULL_PTR, RA8_INTERNAL, ra8_log_error, s_tag, ra8_cache_store_cfg_t::staging, and ra8_cache_store_cfg_t::staging_bytes.

Referenced by ra8_cache_store_init().

◆ priv_cache_store_crc32()

uint32_t priv_cache_store_crc32 ( const uint8_t * data,
uint32_t len )

Fold a byte block into a CRC-32/ISO-HDLC value (seeded + finalised).

Standalone bitwise reflected CRC over one contiguous block: seeds and XOR-finalises with k_ra8_cs_crc32_seed internally, so the caller passes raw bytes and gets the final CRC. Used to seal every on-flash record.

Parameters
[in]dataBytes to fold (may be NULL only when len is 0).
[in]lenByte count.
Returns
The finalised CRC-32 over data.
Return values
uint32_tCRC over the len bytes; the empty-input CRC when len==0.
Precondition
data covers len readable bytes, or len is 0.
The caller wants ISO-HDLC (zlib-compatible) conditioning.
Postcondition
data is unmodified.
The result depends only on the input bytes (pure function).
Note
Thread-safe: pure over its arguments.
Since
0.1.0

Definition at line 55 of file ra8_cache_store_mount.c.

References k_ra8_cs_crc32_poly, k_ra8_cs_crc32_seed, k_ra8_cs_crc_bits, and RA8_PRIV.

Referenced by internal_hdr_read(), internal_super_is_clean(), internal_write_entry(), and priv_cache_store_super_write().

◆ priv_cache_store_dir_save()

ra8_err_t priv_cache_store_dir_save ( ra8_cache_store_t * store,
uint32_t * out_entry_count )

Serialize the live index into the on-flash checkpoint directory.

Packs every in-use slot as an ra8_cs_dir_ent_t across the directory region [1, log_start), then returns the count so the caller can put it in the superblock. Does not touch sector 0.

Parameters
[in,out]storeStore whose index is serialized.
[out]out_entry_countReceives the number of entries written.
Returns
Error code.
Return values
k_ra8_okDirectory written.
k_ra8_err_hw_init_failedLevelX write error.
Precondition
store->checkpoint_dirs directory sectors were reserved at init.
out_entry_count is writable.
Postcondition
On k_ra8_ok, *out_entry_count in-use entries are on flash.
The superblock is untouched (caller commits it).
Note
Not thread-safe; shares the store staging buffer.
Since
0.1.0

Definition at line 320 of file ra8_cache_store_mount.c.

References ra8_cache_store_t::checkpoint_dirs, internal_dir_pack_sector(), k_ra8_ok, priv_cache_store_sector_write(), RA8_CHECK_NULL_PTR, RA8_PRIV, RA8_RETURN_ON_ERROR, s_tag, and ra8_cache_store_t::staging.

Referenced by internal_checkpoint().

◆ priv_cache_store_index_add()

int32_t priv_cache_store_index_add ( ra8_cache_store_t * store,
uint32_t key,
uint32_t start_sector,
uint16_t sector_count,
uint32_t byte_len,
bool pinned )

Claim a free index slot and populate it for key.

Claims the first free slot and records the entry's location, run length, and flags.

Parameters
[in,out]storeStore whose index gains an entry.
[in]keyContent key.
[in]start_sectorEntry header logical sector.
[in]sector_countRun length (header + payload).
[in]byte_lenPayload length in bytes.
[in]pinnedPersist the pinned flag.
Returns
Slot index, or -1 when the index is full.
Return values
-1No free slot.
Precondition
store->index covers store->index_cap slots.
key is not already present (caller checked).
Postcondition
On success the slot is in-use with the given fields.
On failure the index is unchanged.
Note
Not thread-safe; the store serialises access.
Since
0.1.0

Definition at line 138 of file ra8_cache_store_mount.c.

References ra8_cache_store_entry_t::flags, ra8_cache_store_t::index, ra8_cache_store_t::index_cap, k_ra8_cache_store_flag_in_use, k_ra8_cache_store_flag_pinned, and RA8_PRIV.

Referenced by internal_dir_unpack_sector(), internal_scan_accept(), and ra8_cache_store_put().

◆ priv_cache_store_index_find()

int32_t priv_cache_store_index_find ( const ra8_cache_store_t * store,
uint32_t key )

Find the index slot holding key.

Linear scan of the in-use index slots for a matching key.

Parameters
[in]storeStore to search.
[in]keyContent key.
Returns
Slot index, or -1 when key is not present.
Return values
-1No in-use slot matches key.
Precondition
store->index covers store->index_cap slots.
The index reflects the live set.
Postcondition
The store is unmodified (pure lookup).
A non-negative result indexes an in-use slot with key == @p key.
Note
Thread-safe with respect to a quiescent store (pure read).
Since
0.1.0

Definition at line 118 of file ra8_cache_store_mount.c.

References ra8_cache_store_entry_t::flags, ra8_cache_store_t::index, ra8_cache_store_t::index_cap, k_ra8_cache_store_flag_in_use, ra8_cache_store_entry_t::key, and RA8_PRIV.

Referenced by internal_put_check(), internal_scan_accept(), ra8_cache_store_evict(), ra8_cache_store_get(), and ra8_cache_store_pin().

◆ priv_cache_store_sector_read()

ra8_err_t priv_cache_store_sector_read ( const ra8_cache_store_t * store,
uint32_t sector,
uint8_t * out512 )

Read one LevelX logical sector into the store staging buffer region.

Wraps lx_nor_flash_sector_read, mapping the LevelX status onto an ra8_err_t.

Parameters
[in]storeStore whose LevelX flash is read.
[in]sectorLogical sector index.
[out]out512Destination of at least one sector.
Returns
Error code.
Return values
k_ra8_okSector read.
k_ra8_err_not_foundSector is unmapped/released (LevelX miss).
k_ra8_err_hw_init_failedLevelX read error.
Precondition
store->flash is an open LevelX NOR partition.
out512 covers one sector.
Postcondition
On k_ra8_ok, out512 holds the sector bytes.
On any error out512 content is unspecified.
Note
Not thread-safe; the store serialises access.
Since
0.1.0

Definition at line 77 of file ra8_cache_store_mount.c.

References ra8_cache_store_t::flash, k_ra8_err_hw_init_failed, k_ra8_err_not_found, k_ra8_ok, RA8_CHECK_NULL_PTR, RA8_PRIV, and s_tag.

Referenced by internal_dir_load(), internal_hdr_read(), internal_read_at(), and internal_super_read().

◆ priv_cache_store_sector_release()

ra8_err_t priv_cache_store_sector_release ( ra8_cache_store_t * store,
uint32_t sector )

Release a LevelX logical sector back to the free pool.

Wraps lx_nor_flash_sector_release, returning the logical sector to the free pool.

Parameters
[in,out]storeStore whose LevelX flash is released.
[in]sectorLogical sector index.
Returns
Error code.
Return values
k_ra8_okSector released (or already free).
k_ra8_err_hw_init_failedLevelX release error.
Precondition
store->flash is an open LevelX NOR partition.
sector is within the partition.
Postcondition
On k_ra8_ok, a later read of sector misses until rewritten.
The sector becomes available for a future allocation.
Note
Not thread-safe; the store serialises access.
Since
0.1.0

Definition at line 107 of file ra8_cache_store_mount.c.

References ra8_cache_store_t::flash, k_ra8_err_hw_init_failed, k_ra8_ok, RA8_CHECK_NULL_PTR, RA8_PRIV, and s_tag.

Referenced by internal_release_run().

◆ priv_cache_store_sector_write()

ra8_err_t priv_cache_store_sector_write ( ra8_cache_store_t * store,
uint32_t sector,
const uint8_t * in512 )

Write one LevelX logical sector from a one-sector source buffer.

Wraps lx_nor_flash_sector_write, mapping a LevelX failure onto a hardware error.

Parameters
[in,out]storeStore whose LevelX flash is written.
[in]sectorLogical sector index.
[in]in512Source of exactly one sector.
Returns
Error code.
Return values
k_ra8_okSector written.
k_ra8_err_hw_init_failedLevelX write error (e.g. no free sectors).
Precondition
store->flash is an open LevelX NOR partition.
in512 covers one sector.
Postcondition
On k_ra8_ok, a later priv_cache_store_sector_read returns in512.
On any error the sector mapping is unchanged.
Note
Not thread-safe; the store serialises access.
Since
0.1.0

Definition at line 93 of file ra8_cache_store_mount.c.

References ra8_cache_store_t::flash, k_ra8_err_hw_init_failed, k_ra8_ok, RA8_CHECK_NULL_PTR, RA8_PRIV, and s_tag.

Referenced by internal_write_entry(), priv_cache_store_dir_save(), and priv_cache_store_super_write().

◆ priv_cache_store_super_write()

ra8_err_t priv_cache_store_super_write ( ra8_cache_store_t * store,
uint32_t clean )

Write the superblock (sector 0) with the given clean marker.

Snapshots the store's live geometry (entry_count, live_sectors, next_seq, ...) plus clean into ra8_cs_super_t, seals it with a CRC, and writes sector 0 – the commit point of a checkpoint.

Parameters
[in,out]storeStore to snapshot.
[in]cleanra8_cs_clean_t marker to stamp.
Returns
Error code.
Return values
k_ra8_okSuperblock written.
k_ra8_err_hw_init_failedLevelX write error.
Precondition
store->inited is true (or mid-init with geometry set).
store->staging covers one sector.
Postcondition
On k_ra8_ok, sector 0 holds a valid superblock with clean.
On any error sector 0 is unchanged.
Note
Not thread-safe; shares the store staging buffer.
Since
0.1.0

Definition at line 175 of file ra8_cache_store_mount.c.

References ra8_cs_super_t::crc, ra8_cache_store_t::data_capacity, ra8_cs_super_t::entry_count, ra8_cache_store_entry_t::flags, ra8_cache_store_t::index, ra8_cache_store_t::index_cap, k_ra8_cache_store_flag_in_use, k_ra8_cache_store_sector_bytes, k_ra8_cs_format_version, k_ra8_cs_super_magic, ra8_cache_store_t::live_sectors, ra8_cache_store_t::log_start, ra8_cache_store_t::logical_sectors, memcpy(), memset(), ra8_cache_store_t::next_seq, priv_cache_store_crc32(), priv_cache_store_sector_write(), RA8_CHECK_NULL_PTR, RA8_PRIV, s_tag, and ra8_cache_store_t::staging.

Referenced by internal_checkpoint(), internal_mark_dirty(), and internal_open_levelx().

◆ ra8_cache_store_init()

ra8_err_t ra8_cache_store_init ( ra8_cache_store_t * store,
const ra8_cache_store_cfg_t * cfg )
nodiscard

Bind a LevelX NOR flash instance and mount (or format) the store.

Opens the injected LevelX NOR partition (formatting first when cfg->format), then recovers the key index:

  • a clean shutdown marker plus a valid on-flash directory checkpoint is loaded directly (fast path);
  • otherwise the append log is replayed (scanned) to rebuild the index and discard any entry whose append never completed. The store is then marked dirty on flash so a later crash forces a replay.
Parameters
[out]storeZero-initialised handle to populate.
[in]cfgInjected dependencies + geometry (see the struct).
Returns
Error code.
Return values
k_ra8_okStore mounted (or formatted) and ready.
k_ra8_err_null_ptrstore, cfg, or a required cfg member NULL.
k_ra8_err_invalid_sizestaging_bytes too small, index_cap zero, or logical_sectors too small for the layout.
k_ra8_err_invalid_argoverprovision_pct out of range.
k_ra8_err_hw_init_failedLevelX open/format failed.
k_ra8_err_invalid_stateOn-flash checkpoint/superblock is corrupt.
Precondition
store, cfg, and every non-optional cfg member are non-NULL.
cfg->nor_driver_init brings a working LevelX NOR flash up.
Postcondition
On k_ra8_ok, store->inited is true and the index reflects flash.
On any error the store is left uninitialised.
Note
Not thread-safe.
See also
ra8_cache_store_close
Since
0.1.0

Definition at line 794 of file ra8_cache_store_mount.c.

References ra8_cache_store_t::inited, internal_bringup(), internal_init_fields(), internal_validate_cfg(), k_ra8_ok, RA8_CHECK_NULL_PTR, RA8_RETURN_ON_ERROR, and s_tag.

Referenced by cache_store_demo_run(), and internal_demo_phase_remount().

Variable Documentation

◆ s_cs_lx_system_inited

bool s_cs_lx_system_inited = false
static

One-shot latch so LevelX's global open-list is initialised once.

lx_nor_flash_initialize() clears LevelX's opened-flash registry; calling it more than once would disturb an already-open partition. The store calls it behind this latch on the first init.

Warning
Written only by ra8_cache_store_init; not for other modules.
Since
0.1.0

Definition at line 39 of file ra8_cache_store_mount.c.

Referenced by internal_open_levelx().

◆ s_tag

const char* const s_tag = "ra8_cache_store"
static

Module log tag.

Definition at line 29 of file ra8_cache_store_mount.c.