Skip to content

Flash Layout

Espilon uses a custom 4 MB partition table that supports dual-slot OTA and isolates the provisioned master key in a dedicated, OTA-safe factory partition. No module is ever written to flash.

Partition table

Partition Offset Size Purpose
bootloader 0x1000 (Xtensa) / 0x0 (RISC-V) variable First-stage bootloader
partition table 0x8000 variable Partition definitions
nvs 0x9000 32 KB WiFi driver cache + encrypted config
otadata 0x11000 8 KB OTA slot selection metadata
phy_init 0x13000 4 KB RF calibration
fctry 0x14000 24 KB Master key + device id (never erased by OTA)
nvs_key 0x1a000 4 KB NVS encryption key
ota_0 0x20000 ~1.9 MB Firmware slot A
ota_1 0x200000 ~1.9 MB Firmware slot B

The fctry partition is sacred

fctry (offset 0x14000) holds the device-unique 32-byte master key and device id. It sits outside both OTA regions and is written once at provisioning. A firmware update never touches it, so OTA cannot brick a device's identity or keys.

flowchart LR
    subgraph FLASH["4 MB flash"]
        BL["bootloader"] --> PT["partition table"] --> NVS["nvs (32 KB)"]
        NVS --> OD["otadata"] --> PHY["phy_init"]
        PHY --> FC["fctry 0x14000<br/>master_key (OTA-safe)"]
        FC --> NK["nvs_key"]
        NK --> O0["ota_0 0x20000"]
        O0 --> O1["ota_1 0x200000"]
    end

Dual-slot OTA

Firmware updates use the A/B slots ota_0 and ota_1. An update is downloaded over HTTPS and written to the inactive slot; on success the bootloader switches to it, leaving the previous slot intact for rollback. The otadata partition records which slot is active.

The firmware exposes OTA as built-in ota_update <url> and ota_status commands. OTA validates the image header before flashing and aborts on a 30-second stall.

Encrypted NVS config

WiFi credentials and the Management Protocol server address are stored encrypted in the NVS config namespace, protected with the device's config_key. At boot nvs_config_load() decrypts them. The nvs_key partition holds the NVS encryption key. The master key itself lives in the crypto namespace of the fctry partition under the key name master_key.

No modules in flash

ESPM modules exist only in RAM during execution. They are never written to flash unless explicitly persisted to the encrypted NVS config (up to 8 modules), so by default a power cycle leaves the device a clean hollow shell.

See also