Skip to content

Flash Memory Layout

Reference for the flash memory layout used to store calibration data and device configuration.

NanoVNA-H stores persistent data in on-chip flash memory:

  • Calibration data (properties_t): Sweep settings and calibration coefficients
  • Configuration data (config_t): Device settings and color palette

Data is stored at the end of flash, leaving room for firmware at the beginning.


STM32F072xB Flash Layout

Address RangeSizeContent
0x08000000 - 0x0801BFFF112 KBFirmware code
0x0801C000 - 0x0801D7FF6 KBProperty slot 0
0x0801D800 - 0x0801EFFF6 KBProperty slot 1
0x0801F000 - 0x080207FF6 KBProperty slot 2
0x08020800 - 0x08021FFF6 KBProperty slot 3
0x08022000 - 0x080237FF6 KBProperty slot 4
0x08023800 - 0x08023FFF2 KBConfiguration

Constants:

#define FLASH_START_ADDRESS 0x08000000
#define FLASH_TOTAL_SIZE (128*1024) // 131072 bytes
#define FLASH_PAGESIZE 0x800 // 2048 bytes
#define SAVEAREA_MAX 5 // 5 calibration slots
#define SAVE_CONFIG_SIZE 0x00000800 // 2 KB config
#define SAVE_PROP_CONFIG_SIZE 0x00001800 // 6 KB per property

The save area starts at the end of flash:

// Total save area size
#define SAVE_FULL_AREA_SIZE (SAVE_CONFIG_SIZE + SAVEAREA_MAX * SAVE_PROP_CONFIG_SIZE)
// Configuration address (at very end)
#define SAVE_CONFIG_ADDR (FLASH_START_ADDRESS + FLASH_TOTAL_SIZE - SAVE_CONFIG_SIZE)
// Properties start address (before config)
#define SAVE_PROP_CONFIG_ADDR (FLASH_START_ADDRESS + FLASH_TOTAL_SIZE - SAVE_FULL_AREA_SIZE)
SAVE_FULL_AREA_SIZE = 0x800 + 5 * 0x1800 = 0x7800 (30 KB)
SAVE_CONFIG_ADDR = 0x08000000 + 0x20000 - 0x800 = 0x0801F800
SAVE_PROP_CONFIG_ADDR = 0x08000000 + 0x20000 - 0x7800 = 0x08018800
SAVE_FULL_AREA_SIZE = 0x800 + 7 * 0x4000 = 0x1C800 (114 KB)
SAVE_CONFIG_ADDR = 0x08000000 + 0x40000 - 0x800 = 0x0803F800
SAVE_PROP_CONFIG_ADDR = 0x08000000 + 0x40000 - 0x1C800 = 0x08023800

Each calibration slot stores a complete properties_t structure.

TargetSWEEP_POINTS_MAX_cal_data sizeTotal size
F0721014,040 bytes~5 KB
F30340116,040 bytes~17 KB
float _cal_data[CAL_TYPE_COUNT][SWEEP_POINTS_MAX][2];
Cal TypeIndexDescription
CAL_LOAD050 ohm load measurement
CAL_OPEN1Open circuit measurement
CAL_SHORT2Short circuit measurement
CAL_THRU3Through connection measurement
CAL_ISOLN4Isolation measurement

Each entry stores complex data: [0] = real, [1] = imaginary.


Configuration is stored in a single 2 KB area.

FieldSizeDescription
magic4CONFIG_MAGIC (0x434f4e56)
_harmonic_freq_threshold4Harmonic mode threshold
_IF_freq4IF frequency offset
_touch_cal[4]8Touch calibration corners
_vna_mode2Mode flags
_dac_value2DAC output value
_vbat_offset2Battery voltage offset
_bandwidth2Default bandwidth setting
_lever_mode1Lever control mode
_brightness1LCD brightness (F303)
_lcd_palette[32]64Color palette
_serial_speed4USART baud rate
_xtal_freq4TCXO frequency
_measure_r4Reference impedance
_band_mode1Band selection
_reserved[3]3Reserved
checksum4Data integrity check

#define CONFIG_MAGIC 0x434f4e56 // "CONV" - Config
#define PROPERTIES_MAGIC 0x434f4e54 // "CONT" - Properties

When loading data:

  1. Check magic value matches expected
  2. Verify checksum
  3. If either fails, use defaults

Flash memory requires erasing before writing. The erase granularity is one page (2 KB).

// Erase pages at address
void flash_erase_pages(uint32_t page_address, uint32_t size);
// Write data (must be erased first)
void flash_program_half_word_buffer(uint16_t* dst, uint16_t *data, uint16_t size);
  1. Calculate checksum of data
  2. Erase required flash pages
  3. Write data in 16-bit half-words
  4. Verify write completed
  1. Read magic value
  2. If magic matches, verify checksum
  3. Copy data to RAM structure
  4. If verification fails, return error

CommandAction
save <n>Save to slot n (0-4 or 0-6)
recall <n>Load from slot n
saveconfigSave configuration
clearconfigReset configuration

Save: CAL > SAVE > slot number Recall: CAL > RECALL > slot number


The linker script reserves flash for storage.

MEMORY
{
flash0 : org = 0x08000000, len = 112K /* Firmware */
flash7 : org = 0x0801C000, len = 16K /* Reserved for storage */
...
}
MEMORY
{
flash0 : org = 0x08000000, len = 128K /* Firmware */
flash7 : org = 0x08020000, len = 128K /* Reserved for storage */
...
}

If configuration becomes corrupted:

  1. From menu: CONFIG > EXPERT SETTINGS > CLEAR CONFIG
  2. From shell: clearconfig command
  3. Hardware reset: Hold BOOT0 during power-on, reflash firmware

STM32 flash has limited write cycles (~10,000 per page).

Best practices:

  • Avoid excessive saves during development
  • Use saveconfig sparingly
  • Calibration rarely changes, so wear is minimal
  • If flash fails, the page may become read-only