Virtual EEPROM is a portable C11 library that emulates a linear EEPROM-style
byte array on top of erase-before-write flash memory. It is intended for
embedded systems that need predictable persistence semantics, explicit recovery
behavior, and a small firmware-friendly integration surface.
The library is designed around a few non-negotiable goals:
- No hidden global mutable state
- No heap allocation in the core library
- Clear, explicit lifecycle semantics
- Deterministic recovery after interrupted page migration
- Host-side validation through simulation and automated tests
The public API presents a logical byte-addressable storage region. Internally, the library persists data as fixed-size block records, where the block size is equal to the configured flash program unit. This keeps the flash model honest while allowing the external interface to remain simple.
Each active flash page contains a self-consistent logical snapshot. When the page fills, the library migrates the latest committed block image into a scratch page, commits the new page, and retires the old page. That approach favors correctness and recoverability over peak write throughput, which is the right trade-off for a first production-quality implementation.
Additional design detail is documented in [architecture.md](/T:/Git Repos/Virtual EEPROM & Flash Memory Emulation/docs/architecture.md), [flash_layout.md](/T:/Git Repos/Virtual EEPROM & Flash Memory Emulation/docs/flash_layout.md), and [decisions.md](/T:/Git Repos/Virtual EEPROM & Flash Memory Emulation/docs/decisions.md).
- Heap-free core library using caller-owned instance memory
- Opaque device handle with injected flash callbacks
- Explicit
veeprom_mount()andveeprom_format()behavior - No implicit formatting of blank media
- Synchronous writes with recovery-aware page migration
- Host simulator with deterministic fault injection
- Unit, integration, recovery, endurance, and install-tree smoke tests
Typical use follows this sequence:
- Populate
veeprom_config_twith flash geometry and callback functions. - Allocate aligned instance memory sized with
veeprom_instance_size(). - Call
veeprom_init(). - Call
veeprom_mount()to scan existing flash contents. - If mount returns
VEEPROM_STATUS_UNFORMATTED, callveeprom_format(). - Use
veeprom_read()andveeprom_write()against the logical byte array.
Important behavioral notes:
veeprom_mount()scans existing media only. It never erases flash implicitly.veeprom_format()creates a new empty logical image and leaves the device mounted.veeprom_flush()is present as a stable API boundary, but writes are synchronous in v1.- Writes are committed one internal block record at a time. A write spanning multiple internal blocks is not transactional across the entire request.
#include <stdint.h>
#include "veeprom/veeprom.h"
static uint8_t device_memory[2048];
int initialize_store(const veeprom_flash_if_t *flash_if, veeprom_device_t **out_device)
{
veeprom_config_t config = {
.geometry = {
.flash_base_address = 0U,
.page_size_bytes = 512U,
.page_count = 4U,
.erase_size_bytes = 64U,
.program_unit_bytes = 8U,
},
.flash_if = flash_if,
.logical_size_bytes = 64U,
.erased_value = 0xFFU,
};
veeprom_status_t status;
status = veeprom_init(device_memory, sizeof(device_memory), &config, out_device);
if (status != VEEPROM_STATUS_OK)
{
return -1;
}
status = veeprom_mount(*out_device);
if (status == VEEPROM_STATUS_UNFORMATTED)
{
status = veeprom_format(*out_device);
}
return (status == VEEPROM_STATUS_OK) ? 0 : -1;
}See [examples/host_basic/main.c](/T:/Git Repos/Virtual EEPROM & Flash Memory Emulation/examples/host_basic/main.c:1) for a host-side example using the simulator backend.
cmake -S . -B build
cmake --build build
ctest --test-dir build --output-on-failureVEEPROM_BUILD_TESTS: build the automated test suiteVEEPROM_BUILD_SIMULATOR: build the host-side flash simulator and CLIVEEPROM_BUILD_EXAMPLES: build example applicationsVEEPROM_ENABLE_WARNINGS: enable strict warning profilesVEEPROM_ENABLE_SANITIZERS: enable host-side sanitizer instrumentation
include/veeprom/ Public API headers
src/ Core library implementation
tests/ Unit, integration, recovery, endurance, and packaging tests
tools/simulator/ Host-side simulator support and CLI
examples/host_basic/ Minimal example application
docs/ Architecture, layout, and design rationale
cmake/ Shared CMake helpers
- v1 assumes erased flash reads as
0xFF. - The configured logical image must fit into one fully populated active page.
- The core library is portable C11, but the simulator and CI are host-oriented.
- Multi-block user writes are not atomic as a single transaction.
The repository currently contains a complete v1 core implementation, host-side simulation support, automated tests, and CI scaffolding. The library is shaped as a production-oriented embedded component, with emphasis on clarity and reviewability over aggressive optimization.