ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_cache_store_mount.c
Go to the documentation of this file.
1
18
19#include <stdint.h>
20#include <string.h>
21
22#include "lx_api.h"
23#include "ra8_cache_store.h"
25#include "ra8_check.h"
26#include "ra8_err.h"
27
29static const char* const s_tag = "ra8_cache_store";
30
39static bool s_cs_lx_system_inited = false;
40
46typedef enum : uint32_t {
50
51/* ------------------------------------------------------------------------- */
52/* Shared low-level helpers (declared in ra8_cache_store_internal.h) */
53/* ------------------------------------------------------------------------- */
54
55RA8_PRIV uint32_t priv_cache_store_crc32(const uint8_t* data, uint32_t len)
56{
57 if (data == nullptr) {
58 return 0U;
59 }
60 if (len == 0U) {
61 return 0U;
62 }
63 uint32_t crc = (uint32_t)k_ra8_cs_crc32_seed;
64 for (uint32_t i = 0U; i < len; i++) {
65 crc ^= data[i];
66 for (uint8_t b = 0U; b < (uint8_t)k_ra8_cs_crc_bits; b++) {
67 bool lsb = (crc & 1U) != 0U;
68 crc >>= 1U;
69 if (lsb) {
70 crc ^= (uint32_t)k_ra8_cs_crc32_poly;
71 }
72 }
73 }
74 return crc ^ (uint32_t)k_ra8_cs_crc32_seed;
75}
76
78 uint32_t sector,
79 uint8_t* out512)
80{
81 RA8_CHECK_NULL_PTR(store, s_tag, "store");
82 RA8_CHECK_NULL_PTR(out512, s_tag, "out512");
83 UINT rc = lx_nor_flash_sector_read(store->flash, (ULONG)sector, out512);
84 if (rc == (UINT)LX_SUCCESS) {
85 return k_ra8_ok;
86 }
87 if (rc == (UINT)LX_SECTOR_NOT_FOUND) {
89 }
91}
92
94 uint32_t sector,
95 const uint8_t* in512)
96{
97 RA8_CHECK_NULL_PTR(store, s_tag, "store");
98 RA8_CHECK_NULL_PTR(in512, s_tag, "in512");
99 /* LevelX writes take a mutable buffer pointer but do not modify it. */
100 UINT rc = lx_nor_flash_sector_write(store->flash, (ULONG)sector, (VOID*)(uintptr_t)in512);
101 if (rc != (UINT)LX_SUCCESS) {
103 }
104 return k_ra8_ok;
105}
106
108{
109 RA8_CHECK_NULL_PTR(store, s_tag, "store");
110 RA8_CHECK_NULL_PTR(store->flash, s_tag, "flash");
111 UINT rc = lx_nor_flash_sector_release(store->flash, (ULONG)sector);
112 if (rc != (UINT)LX_SUCCESS) {
114 }
115 return k_ra8_ok;
116}
117
118RA8_PRIV int32_t priv_cache_store_index_find(const ra8_cache_store_t* store, uint32_t key)
119{
120 if (store == nullptr) {
121 return -1;
122 }
123 if (store->index == nullptr) {
124 return -1;
125 }
126 for (uint16_t i = 0U; i < store->index_cap; i++) {
127 const ra8_cache_store_entry_t* e = &store->index[i];
128 if ((e->flags & (uint8_t)k_ra8_cache_store_flag_in_use) == 0U) {
129 continue;
130 }
131 if (e->key == key) {
132 return (int32_t)i;
133 }
134 }
135 return -1;
136}
137
139 uint32_t key,
140 uint32_t start_sector,
141 uint16_t sector_count,
142 uint32_t byte_len,
143 bool pinned)
144{
145 if (store == nullptr) {
146 return -1;
147 }
148 if (store->index == nullptr) {
149 return -1;
150 }
151 for (uint16_t i = 0U; i < store->index_cap; i++) {
152 ra8_cache_store_entry_t* e = &store->index[i];
153 if ((e->flags & (uint8_t)k_ra8_cache_store_flag_in_use) != 0U) {
154 continue;
155 }
156 uint8_t flags = (uint8_t)k_ra8_cache_store_flag_in_use;
157 if (pinned) {
158 flags |= (uint8_t)k_ra8_cache_store_flag_pinned;
159 }
160 *e = (ra8_cache_store_entry_t){.key = key,
161 .start_sector = start_sector,
162 .byte_len = byte_len,
163 .sector_count = sector_count,
164 .flags = flags,
165 .reserved = 0U};
166 return (int32_t)i;
167 }
168 return -1;
169}
170
171/* ------------------------------------------------------------------------- */
172/* Superblock */
173/* ------------------------------------------------------------------------- */
174
176{
177 RA8_CHECK_NULL_PTR(store, s_tag, "store");
178 RA8_CHECK_NULL_PTR(store->staging, s_tag, "staging");
179 ra8_cs_super_t sb = {.magic = (uint32_t)k_ra8_cs_super_magic,
180 .version = (uint32_t)k_ra8_cs_format_version,
181 .seq = store->next_seq,
182 .clean = clean,
183 .entry_count = 0U,
184 .live_sectors = store->live_sectors,
185 .next_seq = store->next_seq,
186 .log_start = store->log_start,
187 .data_capacity = store->data_capacity,
188 .logical_sectors = store->logical_sectors,
189 .crc = 0U};
190 for (uint16_t i = 0U; i < store->index_cap; i++) {
191 if ((store->index[i].flags & (uint8_t)k_ra8_cache_store_flag_in_use) != 0U) {
192 sb.entry_count++;
193 }
194 }
195 sb.crc = priv_cache_store_crc32((const uint8_t*)&sb, (uint32_t)(sizeof(sb) - sizeof(sb.crc)));
196 (void)memset(store->staging, 0, (size_t)k_ra8_cache_store_sector_bytes);
197 (void)memcpy(store->staging, &sb, sizeof(sb));
198 return priv_cache_store_sector_write(store, 0U, store->staging);
199}
200
220{
221 RA8_CHECK_NULL_PTR(store, s_tag, "store");
222 RA8_CHECK_NULL_PTR(out_sb, s_tag, "out_sb");
223 if (priv_cache_store_sector_read(store, 0U, store->staging) != k_ra8_ok) {
224 (void)memset(out_sb, 0, sizeof(*out_sb));
225 return k_ra8_ok;
226 }
227 (void)memcpy(out_sb, store->staging, sizeof(*out_sb));
228 return k_ra8_ok;
229}
230
247{
248 if (sb == nullptr) {
249 return false;
250 }
251 if (sb->magic != (uint32_t)k_ra8_cs_super_magic) {
252 return false;
253 }
254 uint32_t want =
255 priv_cache_store_crc32((const uint8_t*)sb, (uint32_t)(sizeof(*sb) - sizeof(sb->crc)));
256 if (sb->crc != want) {
257 return false;
258 }
259 if (sb->clean != (uint32_t)k_ra8_cs_clean) {
260 return false;
261 }
262 return true;
263}
264
265/* ------------------------------------------------------------------------- */
266/* Directory checkpoint save / load */
267/* ------------------------------------------------------------------------- */
268
286RA8_INTERNAL static uint32_t
287internal_dir_pack_sector(ra8_cache_store_t* store, uint16_t* slot, uint8_t* out512)
288{
289 if (store == nullptr) {
290 return 0U;
291 }
292 if (out512 == nullptr) {
293 return 0U;
294 }
295 (void)memset(out512, 0, (size_t)k_ra8_cache_store_sector_bytes);
296 uint32_t packed = 0U;
297 for (uint32_t e = 0U; e < (uint32_t)k_ra8_cs_dir_per_sector; e++) {
298 for (; *slot < store->index_cap; (*slot)++) {
299 if ((store->index[*slot].flags & (uint8_t)k_ra8_cache_store_flag_in_use) != 0U) {
300 break;
301 }
302 }
303 if (*slot >= store->index_cap) {
304 break;
305 }
306 const ra8_cache_store_entry_t* src = &store->index[*slot];
307 ra8_cs_dir_ent_t ent = {.key = src->key,
308 .start_sector = src->start_sector,
309 .byte_len = src->byte_len,
310 .sector_count = src->sector_count,
311 .flags =
312 (uint16_t)(src->flags & (uint8_t)k_ra8_cache_store_flag_pinned)};
313 (void)memcpy(&out512[(size_t)e * (uint32_t)k_ra8_cs_dir_ent_bytes], &ent, sizeof(ent));
314 (*slot)++;
315 packed++;
316 }
317 return packed;
318}
319
321{
322 RA8_CHECK_NULL_PTR(store, s_tag, "store");
323 RA8_CHECK_NULL_PTR(out_entry_count, s_tag, "out_entry_count");
324 uint32_t count = 0U;
325 uint16_t slot = 0U;
326 for (uint16_t d = 0U; d < store->checkpoint_dirs; d++) {
327 count += internal_dir_pack_sector(store, &slot, store->staging);
328 RA8_RETURN_ON_ERROR(priv_cache_store_sector_write(store, 1U + (uint32_t)d, store->staging),
329 s_tag,
330 "dir");
331 }
332 *out_entry_count = count;
333 return k_ra8_ok;
334}
335
354 const uint8_t* in512,
355 uint32_t* loaded,
356 uint32_t entry_count)
357{
358 if (store == nullptr) {
359 return;
360 }
361 if (in512 == nullptr) {
362 return;
363 }
364 for (uint32_t e = 0U; e < (uint32_t)k_ra8_cs_dir_per_sector; e++) {
365 if (*loaded >= entry_count) {
366 break;
367 }
368 ra8_cs_dir_ent_t ent = {};
369 (void)memcpy(&ent, &in512[(size_t)e * (uint32_t)k_ra8_cs_dir_ent_bytes], sizeof(ent));
370 bool pinned = (ent.flags & (uint16_t)k_ra8_cache_store_flag_pinned) != 0U;
371 (void)priv_cache_store_index_add(store,
372 ent.key,
373 ent.start_sector,
374 ent.sector_count,
375 ent.byte_len,
376 pinned);
377 store->live_sectors += ent.sector_count;
378 (*loaded)++;
379 }
380}
381
399RA8_INTERNAL static ra8_err_t internal_dir_load(ra8_cache_store_t* store, uint32_t entry_count)
400{
401 RA8_CHECK_NULL_PTR(store, s_tag, "store");
402 RA8_CHECK_NULL_PTR(store->staging, s_tag, "staging");
403 if (entry_count > (uint32_t)store->index_cap) {
405 }
406 store->live_sectors = 0U;
407 uint32_t loaded = 0U;
408 for (uint16_t d = 0U; d < store->checkpoint_dirs; d++) {
409 if (loaded >= entry_count) {
410 break;
411 }
412 RA8_RETURN_ON_ERROR(priv_cache_store_sector_read(store, 1U + (uint32_t)d, store->staging),
413 s_tag,
414 "dir");
415 internal_dir_unpack_sector(store, store->staging, &loaded, entry_count);
416 }
417 return k_ra8_ok;
418}
419
420/* ------------------------------------------------------------------------- */
421/* Append-log scan (unclean-shutdown replay) */
422/* ------------------------------------------------------------------------- */
423
442RA8_INTERNAL static bool
444{
445 if (priv_cache_store_sector_read(store, s, store->staging) != k_ra8_ok) {
446 return false;
447 }
448 ra8_cs_entry_hdr_t h = {};
449 (void)memcpy(&h, store->staging, sizeof(h));
450 if (h.magic != (uint32_t)k_ra8_cs_entry_magic) {
451 return false;
452 }
453 if (h.start_sector != s) {
454 return false;
455 }
456 if (h.sector_count == 0U) {
457 return false;
458 }
459 if (((uint64_t)s + (uint64_t)h.sector_count) > (uint64_t)store->logical_sectors) {
460 return false;
461 }
462 uint32_t want =
463 priv_cache_store_crc32((const uint8_t*)&h, (uint32_t)(sizeof(h) - sizeof(h.hdr_crc)));
464 if (h.hdr_crc != want) {
465 return false;
466 }
467 *out_hdr = h;
468 return true;
469}
470
485RA8_INTERNAL static void
487{
488 bool pinned = (h->flags & (uint16_t)k_ra8_cache_store_flag_pinned) != 0U;
489 if (priv_cache_store_index_find(store, h->key) >= 0) {
490 return; /* write-once: a duplicate key on flash is ignored (keep the first). */
491 }
493 h->key,
494 h->start_sector,
495 h->sector_count,
496 h->byte_len,
497 pinned) < 0) {
498 return; /* index full: stop indexing further entries. */
499 }
500 store->live_sectors += h->sector_count;
501 if (h->seq > *max_seq) {
502 *max_seq = h->seq;
503 }
504}
505
523{
524 RA8_CHECK_NULL_PTR(store, s_tag, "store");
525 RA8_CHECK_NULL_PTR(store->staging, s_tag, "staging");
526 store->live_sectors = 0U;
527 uint32_t max_seq = 0U;
528 uint32_t s = store->log_start;
529 for (uint32_t guard = store->log_start; guard < store->logical_sectors; guard++) {
530 if (s >= store->logical_sectors) {
531 break;
532 }
533 ra8_cs_entry_hdr_t h = {};
534 if (!internal_hdr_read(store, s, &h)) {
535 s += 1U;
536 continue;
537 }
538 internal_scan_accept(store, &h, &max_seq);
539 s += h.sector_count;
540 }
541 store->next_seq = max_seq + 1U;
542 return k_ra8_ok;
543}
544
545/* ------------------------------------------------------------------------- */
546/* init */
547/* ------------------------------------------------------------------------- */
548
566{
567 RA8_CHECK_NULL_PTR(cfg, s_tag, "cfg");
568 RA8_CHECK_NULL_PTR(cfg->nor_flash, s_tag, "nor_flash");
569 if (cfg->nor_driver_init == nullptr) {
570 ra8_log_error(s_tag, "nor_driver_init");
571 return k_ra8_err_null_ptr;
572 }
573 RA8_CHECK_NULL_PTR(cfg->index, s_tag, "index");
574 RA8_CHECK_NULL_PTR(cfg->staging, s_tag, "staging");
575 if (cfg->index_cap == 0U) {
577 }
578 if (cfg->staging_bytes < (uint32_t)k_ra8_cache_store_sector_bytes) {
580 }
583 }
584 return k_ra8_ok;
585}
586
603 const ra8_cache_store_cfg_t* cfg)
604{
605 RA8_CHECK_NULL_PTR(store, s_tag, "store");
606 RA8_CHECK_NULL_PTR(cfg, s_tag, "cfg");
607 uint32_t dirs = ((uint32_t)cfg->index_cap + (uint32_t)k_ra8_cs_dir_per_sector - 1U) /
608 (uint32_t)k_ra8_cs_dir_per_sector;
609 store->checkpoint_dirs = (uint16_t)dirs;
610 store->log_start = 1U + dirs;
611 store->logical_sectors = cfg->logical_sectors;
612 if (cfg->logical_sectors < (store->log_start + (uint32_t)k_ra8_cache_store_min_sectors)) {
614 }
615 uint32_t op = (cfg->overprovision_pct != 0U) ? (uint32_t)cfg->overprovision_pct
617 uint32_t usable = cfg->logical_sectors - store->log_start;
618 store->data_capacity =
619 (usable * ((uint32_t)k_ra8_cs_pct_full - op)) / (uint32_t)k_ra8_cs_pct_full;
620 if (store->data_capacity == 0U) {
621 store->data_capacity = 1U;
622 }
623 return k_ra8_ok;
624}
625
642 const ra8_cache_store_cfg_t* cfg)
643{
644 RA8_CHECK_NULL_PTR(store, s_tag, "store");
645 RA8_CHECK_NULL_PTR(cfg, s_tag, "cfg");
647 (void)lx_nor_flash_initialize();
649 }
650 /* LevelX takes a mutable CHAR* name but never writes it. */
651 CHAR* nm = (cfg->name != nullptr) ? (CHAR*)(uintptr_t)cfg->name : (CHAR*)(uintptr_t)"ra8_cache";
652 if (cfg->format) {
653 if (lx_nor_flash_format(store->flash, nm, cfg->nor_driver_init, LX_NULL) != (UINT)LX_SUCCESS) {
655 }
656 }
657 if (lx_nor_flash_open(store->flash, nm, cfg->nor_driver_init) != (UINT)LX_SUCCESS) {
659 }
660 /* Stamp an empty clean superblock at format time so a fresh mount loads the
661 * (empty) checkpoint instead of scanning the whole -- as-yet unmapped -- log
662 * region, which on LevelX would allocate a physical sector per read. */
663 if (cfg->format) {
665 s_tag,
666 "format super");
667 }
668 return k_ra8_ok;
669}
670
689{
690 RA8_CHECK_NULL_PTR(store, s_tag, "store");
691 RA8_CHECK_NULL_PTR(sb, s_tag, "sb");
692 if (internal_super_is_clean(sb)) {
693 store->next_seq = sb->next_seq;
694 store->flash_state = (uint8_t)k_ra8_cs_clean;
695 return internal_dir_load(store, sb->entry_count);
696 }
697 store->flash_state = (uint8_t)k_ra8_cs_dirty;
698 return internal_scan_log(store);
699}
700
720{
721 RA8_CHECK_NULL_PTR(store, s_tag, "store");
722 RA8_CHECK_NULL_PTR(store->staging, s_tag, "staging");
723 ra8_cs_super_t sb = {};
724 RA8_RETURN_ON_ERROR(internal_super_read(store, &sb), s_tag, "super");
725 return internal_recover(store, &sb);
726}
727
744 const ra8_cache_store_cfg_t* cfg)
745{
746 if (store == nullptr) {
747 return;
748 }
749 if (cfg == nullptr) {
750 return;
751 }
752 *store = (ra8_cache_store_t){};
753 store->flash = cfg->nor_flash;
754 store->index = cfg->index;
755 store->staging = cfg->staging;
756 store->index_cap = cfg->index_cap;
757 for (uint16_t i = 0U; i < store->index_cap; i++) {
758 store->index[i] = (ra8_cache_store_entry_t){};
759 }
760 store->next_seq = 1U;
761 store->live_sectors = 0U;
762}
763
784 const ra8_cache_store_cfg_t* cfg)
785{
786 RA8_CHECK_NULL_PTR(store, s_tag, "store");
787 RA8_CHECK_NULL_PTR(cfg, s_tag, "cfg");
788 RA8_RETURN_ON_ERROR(internal_geometry(store, cfg), s_tag, "geometry");
789 RA8_RETURN_ON_ERROR(internal_open_levelx(store, cfg), s_tag, "levelx open");
790 RA8_RETURN_ON_ERROR(internal_mount(store), s_tag, "mount");
791 return k_ra8_ok;
792}
793
795{
796 RA8_CHECK_NULL_PTR(store, s_tag, "store");
798 internal_init_fields(store, cfg);
799 RA8_RETURN_ON_ERROR(internal_bringup(store, cfg), s_tag, "bringup");
800 store->inited = true;
801 return k_ra8_ok;
802}
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
#define RA8_PRIV
Module-private helper: shared across TUs but only inside one library.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Persistent key(CRC32)->blob cache for compiled .rabook containers,built on the vendored,...
@ k_ra8_cache_store_flag_pinned
Never-evict (open book / metadata).
@ k_ra8_cache_store_flag_in_use
Slot holds a live entry.
@ k_ra8_cache_store_sector_bytes
LevelX logical-sector size (bytes).
@ k_ra8_cache_store_overprov_pct
Default GC headroom margin (%).
@ k_ra8_cache_store_min_sectors
Minimum usable logical-sector span.
@ k_ra8_cache_store_max_overprov
Reject nonsensical margins above.
Internal on-media format + cross-TU helpers for ra8_cache_store (#201).
@ k_ra8_cs_format_version
On-flash layout revision.
@ k_ra8_cs_crc32_poly
Reflected CRC-32/ISO-HDLC polynomial.
@ k_ra8_cs_dir_per_sector
Directory entries per 512-byte sector.
@ k_ra8_cs_crc32_seed
CRC-32 pre/post conditioning.
@ k_ra8_cs_entry_magic
Entry-header tag 'R','C','S','E'.
@ k_ra8_cs_super_magic
Superblock tag 'R','C','S','1'.
@ k_ra8_cs_dir_ent_bytes
Serialized ra8_cs_dir_ent_t size.
@ k_ra8_cs_dirty
Session open or crashed -> mount must replay the log.
@ k_ra8_cs_clean
Clean shutdown -> the checkpoint directory is valid.
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_super_is_clean(const ra8_cs_super_t *sb)
True when sb is a valid, clean-shutdown superblock.
ra8_cs_shift_t
Small fixed quantities for CRC folding and dir packing.
@ k_ra8_cs_crc_bits
Bits folded per input byte.
@ k_ra8_cs_pct_full
Whole-percent denominator for the margin.
static bool s_cs_lx_system_inited
One-shot latch so LevelX's global open-list is initialised once.
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).
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).
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.
static ra8_err_t internal_mount(ra8_cache_store_t *store)
Mount an open partition: read sector 0, then recover the index.
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.
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.
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.
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 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).
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_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.
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.
int32_t priv_cache_store_index_find(const ra8_cache_store_t *store, uint32_t key)
Find the index slot holding key.
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 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_recover(ra8_cache_store_t *store, const ra8_cs_super_t *sb)
Rebuild the index from a parsed superblock: checkpoint load or replay.
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_scan_log(ra8_cache_store_t *store)
Replay the append log to rebuild the index after an unclean shutdown.
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 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_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.
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_hw_init_failed
Hardware peripheral failed to initialise.
Definition ra8_err.h:290
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ 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_null_ptr
Pointer was NULL where a valid pointer was required.
Definition ra8_err.h:478
@ k_ra8_err_not_found
Requested item not found (lookup / search missed).
Definition ra8_err.h:173
@ 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
void * memset(void *dst, int value, size_t n)
Fill memory with a constant byte value.
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
#define ra8_log_error(tag, message)
RA8 log error.
Definition ra8_log.h:335
unsigned int UINT
ThreadX-compatible unsigned int (host stub).
char CHAR
ThreadX-compatible CHAR (host stub).
unsigned long ULONG
ThreadX-compatible unsigned long (host stub).
Injected dependencies + geometry for ra8_cache_store_init.
ra8_cache_store_nor_init_fn nor_driver_init
Injected physical-flash bind.
uint8_t * staging
Caller-owned >=1-sector scratch.
bool format
Format (wipe) before open.
uint32_t staging_bytes
Bytes at staging (>= sector).
struct LX_NOR_FLASH_STRUCT * nor_flash
Caller-owned LevelX control block.
const char * name
LevelX partition name (may be NULL).
ra8_cache_store_entry_t * index
Caller-owned index array.
uint16_t index_cap
Index slots (max live entries).
uint8_t overprovision_pct
GC headroom margin (0 => default).
uint32_t logical_sectors
Usable LevelX logical-sector span.
One RAM index slot: key -> {header sector, run length, payload len}.
uint32_t byte_len
Payload length in bytes.
uint32_t start_sector
Logical sector of the entry header.
uint8_t flags
ra8_cache_store_flag_t bit set.
uint16_t sector_count
Run length (header + payload sectors).
uint32_t key
Content key (source CRC-32); valid iff in-use.
Caller-owned store handle.
bool inited
True between init and close.
uint32_t data_capacity
Overprovisioned live-sector budget.
uint32_t log_start
First append-log sector.
uint16_t checkpoint_dirs
Directory sectors for the checkpoint.
uint32_t live_sectors
Sectors currently held by live entries.
uint8_t * staging
Caller-owned >=1-sector scratch.
ra8_cache_store_entry_t * index
Caller-owned index slot array.
uint16_t index_cap
Number of index slots.
uint32_t next_seq
Monotonic append sequence number.
struct LX_NOR_FLASH_STRUCT * flash
LevelX control block (borrowed).
uint8_t flash_state
RAM shadow of sector 0 (dirty/clean).
uint32_t logical_sectors
Usable LevelX logical-sector span.
One serialized directory entry in the checkpoint region (16 bytes).
uint16_t flags
Persisted flags (pinned bit).
uint32_t key
Content key.
uint32_t start_sector
Entry header logical sector.
uint32_t byte_len
Payload length in bytes.
uint16_t sector_count
Run length (header + payload).
On-flash entry header at a run's first logical sector.
uint16_t flags
Persisted flags (pinned bit).
uint32_t magic
k_ra8_cs_entry_magic.
uint32_t start_sector
This header's own logical sector (self-anchor).
uint32_t seq
Append sequence number (monotonic).
uint32_t byte_len
Payload length in bytes.
uint32_t key
Content key (source CRC-32).
uint32_t hdr_crc
CRC-32 over the six fields above.
uint16_t sector_count
Run length (header + payload sectors).
On-flash superblock at logical sector 0 (also the checkpoint commit).
uint32_t entry_count
Directory entries in the checkpoint.
uint32_t crc
CRC-32 over the ten fields above.
uint32_t clean
ra8_cs_clean_t shutdown marker.
uint32_t next_seq
Next append sequence number.
uint32_t magic
k_ra8_cs_super_magic.