50.1. EEPROM Emulation Base Test
50.1.1. Overview
This example demonstrates how to use the EEPROM emulation component (eeprom_emulation) to implement basic power-loss protected data storage. The example uses NOR Flash to emulate EEPROM characteristics, supporting data write, read, update, delete, and defragmentation operations.
50.1.2. Component Features
Power-loss protection: Dual half-area design ensures safe recovery from any power-loss scenario
CRC32 verification: Automatic data integrity verification on read
Auto defragmentation: Triggers flush automatically when space is insufficient
Portability: Abstracts Flash drivers via function pointers, supporting different media
50.1.3. Test Contents
This example includes the following function tests:
Write Test
Write 4 test variables (var1 ~ var4) with fixed block IDs (HPMC, A, AB, ABC)
Write string data via e2p_write()
Check write return value
Read Test
Read previously written 4 variables
Read data via e2p_read()
Verify read data consistency with written data
Update Test
Modify values of var1 and var2
Read again and verify update result
Verify old data is overwritten by new data
Delete Test
Delete var4 variable
Mark entry as invalid via e2p_delete()
Verify delete operation returns success
Flush Test
Force trigger data defragmentation
Organize data via e2p_flush(E2P_FLUSH_FORCE)
Reclaim deleted/obsolete data space and switch active area
Call e2p_show_info() to display status after flush
Clear Test
Erase entire storage area (both half-areas)
Clear all data via e2p_clear()
Display status after clear
Status Display
Print current storage area status info (option 7)
Display start address, sector count, remaining space, valid/total entries, etc.
50.1.4. Flash Area Layout
EEPROM emulation uses a continuous region of NOR Flash, divided into two half-areas (A and B):
+--------------------------------------------------+
| Half Area A |
| +--------------------------------------------+ |
| | Data (growing ↑) | Info (growing ↓) | |
| | - User data | - Block descriptors | |
| | - Tail: Header | | |
| +--------------------------------------------+ |
+--------------------------------------------------+
| Half Area B |
| (Same layout as above) |
+.--------------------------------------------------+
The front segment of each half-area stores Data (grows from low to high address)
The back segment of each half-area stores Info descriptors (grows from high to low address)
Info descriptors contain: block_id, data_addr, length, valid_state, crc32
Active area and backup area are switched via state machine for power-loss protection
50.1.5. State Machine and Power-Loss Protection
The component uses a 4-bit state machine (implemented via NOR Flash 1→0 bit transitions, no erase needed):
State Value |
State Name |
Description |
|---|---|---|
0 |
valid |
Normal operating state |
8 |
finish |
Data copy complete, ready to erase old area |
12 |
write |
Writing data to new area |
14 |
start |
Defragmentation started |
15 |
invalid |
Uninitialized/erased state |
State transition flow:
invalid(15) → start(14) → write(12) → finish(8) → valid(0)
Power-loss recovery strategy:
Power-loss Timing |
Area A |
Area B |
Recovery Action |
|---|---|---|---|
First boot |
15 |
15 |
Select Area A, mark as valid |
After flush, old erased |
0 (valid) |
8 (finish) |
Erase Area A, switch to B, mark B as valid |
During flush write |
0 (valid) |
12 (write) |
Erase B, re-flush |
Before flush start |
0 (valid) |
14 (start) |
Erase B, re-flush |
50.1.6. Configuration Parameters
This example uses the following configuration parameters (in main.c):
Macro |
Description |
|---|---|
DEMO_ERASE_SIZE |
Flash erase unit size (default 4096) |
DEMO_SECTOR_CNT |
Sector count, must be even (default 32) |
DEMO_MANAGE_SIZE |
Total managed size (DEMO_ERASE_SIZE * DEMO_SECTOR_CNT) |
DEMO_MANAGE_OFFSET |
Offset from flash base (BOARD_FLASH_SIZE - DEMO_MANAGE_SIZE * 2) |
Single variable data size must not exceed E2P_FLUSH_BUF_SIZE (default 512 bytes), configurable in user_config.h.
50.1.7. Usage Steps
Initialize NOR Flash port
nor_flash_init(&g_nor_cfg);
Configure eeprom_emulation context
g_e2p_ctx.config.start_addr = g_nor_cfg.base_addr + DEMO_MANAGE_OFFSET; g_e2p_ctx.config.erase_size = DEMO_ERASE_SIZE; g_e2p_ctx.config.sector_cnt = DEMO_SECTOR_CNT; g_e2p_ctx.config.version = 0x4553; /* 'E' 'S' */ g_e2p_ctx.config.flash_read = demo_flash_read; g_e2p_ctx.config.flash_write = demo_flash_write; g_e2p_ctx.config.flash_erase = demo_flash_erase;
Initialize eeprom_emulation
e2p_config(&g_e2p_ctx);
Generate block_id (e.g. for var1 ~ var4)
uint32_t var1 = e2p_generate_id("HPMC");
Write data
e2p_write(var1, sizeof("test"), (uint8_t *)"test");
Read data
uint8_t buf[32]; e2p_read(var1, sizeof(buf), buf);
Delete data (optional)
e2p_delete(var1);
Defragment data (optional; also auto-triggered when space is low)
e2p_flush(E2P_FLUSH_FORCE);
50.1.8. Notes
Single write data length should not exceed E2P_FLUSH_BUF_SIZE
sector_cnt must be even (two half-areas are required)
Delete operation only marks entry as invalid; space reclamation completes on next flush
When version number in config changes, the component automatically erases and reinitializes
50.1.9. Running the Example
After the example starts, serial output shows a menu:
========================================
EEPROM Emulation Demo Menu
========================================
1 - Write test data
2 - Read test data
3 - Update test data
4 - Delete a variable
5 - Flush (defragment)
6 - Clear all data
7 - Show status info
i - Show this menu
========================================
Suggested operation order:
Press 1 to write 4 test variables
Press 2 to read and verify data
Press 3 to update var1 and var2
Press 4 to delete var4
Press 5 to force defragment (reclaim deleted space)
Press 7 to view current status info
Press 6 to clear all data (optional)
Operation Example:
Press 1 to write 4 test variables
Press 2 to read and verify data
Press 3 to update var1 and var2
Press 4 to delete var4
Press 5 to force defragment (reclaim deleted space)
Press 6 to clear all data
Press 7 to view current status info
Console Output Example:
1
Writing 4 variables...
Write completed successfully
2
Reading variables...
var1 = abcdef
var2 = 1234
var3 = hello,world
var4 = eeprom_demo
3
Updating var1 and var2...
var1 = qwe
var2 = 5678
Update completed successfully
4
Deleting var4...
Delete successful
5
Flushing (defragmenting)...
Flush completed successfully
[E2P INFO] ------------ e2p init ok -----------
[E2P INFO] start address : 0x80fd0000
[E2P INFO] sector count : 16
[E2P INFO] erase size : 4096
[E2P INFO] version : 0x4553
[E2P INFO] end address : 0x80fe0000
[E2P INFO] data_ptr=0x80fd0015 info_ptr=0x80fdffb4 remain=0xff9f
[E2P INFO] entries valid / total : 3 / 3
[E2P INFO] ------------------------------------
6
Clearing all data...
Clear completed
[E2P INFO] ------------ e2p init ok -----------
[E2P INFO] start address : 0x80fd0000
[E2P INFO] sector count : 16
[E2P INFO] erase size : 4096
[E2P INFO] version : 0x4553
[E2P INFO] end address : 0x80fe0000
[E2P INFO] data_ptr=0x80fd0015 info_ptr=0x80fdffb4 remain=0xff9f
[E2P INFO] entries valid / total : 0 / 3
[E2P INFO] ------------------------------------