nx_blob_store_mcu.nx
buildroot/runtime/nx_blob_store_mcu.nx
about
nx_blob_store_mcu.nx -- MCU-tier variant of blob_store class.
EM-6 milestone of NISHI_ECOSYSTEM_EVOLUTION_ROADMAP.md. Same API
shape as L0 nx_blob_store but with footprint tuned for MCU-class
devices (capacity 4, max blob 256 bytes). Declared as variant
of class `blob_store`, so the SA-arc selector can pick THIS for
MCU-tier targets and the regular nx_blob_store for laptop-class+.
This is the FIRST class to carry multiple variants (`blob_store`
V1 + V1_MCU), exercising the cross-tier selection path the SA
arc architecture promised but had no real test for until now.
V1 footprint envelope:
- Capacity: 4 entries (vs 256 in regular L0)
- Max blob size: 256 bytes (vs 16 MiB in regular L0)
- Index footprint: ~80 B struct + 4 * (32+8) = 240 B
- Total RAM (excluding blob bodies): ~320 B
- Blob bodies still mmap'd separately (caller-allocated)
This fits comfortably on Arduino Uno (2 KB SRAM), STM32F0 family,
nRF52 series, ESP8266, and most Cortex-M0+ devices. AVR backend
(EM-10) will produce binary that consumes < 1 KB.
API mirrors nx_blob_store with `_mcu` suffix to coexist without
symbol collision. Future variant-resolver work can use the
substrate's manifest system to dispatch by tier without caller
awareness.
genealogy_id: cardinal_2026-05-20_ecosystem_evolution +
nx_blob_store_v1 lineage
lineage_id: substrate_blob_store_mcu_v1
nx_capability_manifest:
variant_class: blob_store
variant_id: blob_store_v1_mcu_inline
requires_isa: [rv32i, rv32imac, rv64imac, x86_64, cortex_m, armv7a, aarch64, avr]
requires_syscalls: [mmap]
requires_ram_min_b: 512
tier_floor: NX_TIER_INF_MCU
tier_ceiling: NX_TIER_INF_MOBILE
dependencies 3 imports · 1 importers
imports: nx_syscalls.nxnx_sha256.nxnx_blob_store.nx
imported by: nx_blob_store_mcu_test.nx
structs
| 88 | struct NxBlobEntryMcu |
| 97 | struct NxBlobStoreMcu |
consts
| 60 | const NX_BLOB_STORE_MCU_CAPACITY: i64 = 4 |
| 61 | const NX_BLOB_STORE_MCU_MAX_BLOB_BYTES: i64 = 256 |
| 64 | const NX_BLOB_MCU_OK: i64 = 0 |
| 65 | const NX_BLOB_MCU_BAD_INPUT: i64 = 1 |
| 66 | const NX_BLOB_MCU_FULL: i64 = 2 |
| 67 | const NX_BLOB_MCU_NOT_FOUND: i64 = 3 |
| 68 | const NX_BLOB_MCU_TOO_BIG: i64 = 4 |
| 69 | const NX_BLOB_MCU_TAMPER: i64 = 5 |
| 70 | const NX_BLOB_MCU_N_VERDICTS: i64 = 6 |
| 79 | const NX_BLOB_STORE_MCU_CANARY_PRE: i64 = 0x4E58424C4D435550 // "NXBLMCUP" |
| 80 | const NX_BLOB_STORE_MCU_CANARY_POST: i64 = 0x4E58424C4D43554E // "NXBLMCUN" |
functions
| 72 | func nx_blob_mcu_verdict_is_valid(v: i64) -> i64 called by 1: main |
| 107 | func _mcu_load_i64_le(buf: *u8, off: i64) -> i64 called by 1: _mcu_hash_bytes_to_struct |
| 126 | func _mcu_hash_bytes_to_struct(bytes: *u8, len: i64, out: *NxBlobHash) -> i64 |
| 136 | func _mcu_entry_hash_eq(e: *NxBlobEntryMcu, h: *NxBlobHash) -> i64 called by 1: _mcu_find_entry_idx |
| 144 | func _mcu_find_entry_idx(s: *NxBlobStoreMcu, h: *NxBlobHash) -> i64 called by 3: nx_blob_store_mcu_putnx_blob_store_mcu_getnx_blob_store_mcu_has calls 1: _mcu_entry_hash_eq |
| 157 | func _mcu_alloc_entry(h: *NxBlobHash, src: *u8, len: i64) -> *NxBlobEntryMcu |
| 175 | func nx_blob_store_mcu_new() -> *NxBlobStoreMcu |
| 191 | func nx_blob_store_mcu_is_valid(s: *NxBlobStoreMcu) -> i64 |
| 202 | func nx_blob_store_mcu_put( called by 1: main calls 4: nx_blob_store_mcu_is_valid_mcu_hash_bytes_to_struct_mcu_find_entry_idx_mcu_alloc_entry |
| 229 | func nx_blob_store_mcu_get( |
| 253 | func nx_blob_store_mcu_has(store: *NxBlobStoreMcu, hash: *NxBlobHash) -> i64 |
| 261 | func nx_blob_store_mcu_count(store: *NxBlobStoreMcu) -> i64 |