Partition Table Reference
The exact contents of partitions.csv for the 16 MB ESP32-S3-N16R8. The reasoning behind every entry: flash partitions.
| Name | Type | SubType | Offset | Size | Holds |
|---|---|---|---|---|---|
nvs | data | nvs | 0x9000 | 64 KB | Settings, favorites, cards, schedules, resume record, API token |
phy_init | data | phy | 0x19000 | 4 KB | Radio calibration data |
otadata | data | ota | 0x1A000 | 8 KB | Boot slot selection, two redundant copies |
ota_0 | app | ota_0 | 0x20000 | 4.5 MB | OTA slot A (USB flashes land here) |
ota_1 | app | ota_1 | 0x4A0000 | 4.5 MB | OTA slot B |
storage | data | littlefs (0x82) | 0x920000 | 2 MB | Dashboard files, TLS certificate and key |
coredump | data | coredump | 0xB20000 | 64 KB | Crash post-mortems |
nvs_key | data | nvs_keys | 0xB30000 | 4 KB | NVS encryption key material (production) |
Production builds use partitions_production.csv instead of this table: it
sits at offset 0x10000 (Secure Boot V2 bootloader headroom) and moves
nvs_key to 0xB50000. The 0xB30000 row above, including its
(production) annotation, is the development and legacy layout.
There is deliberately no factory partition: A/B OTA never rewrites it, so
it only wasted 3 MB. With otadata blank the bootloader logs
"No factory image, trying OTA 0" and boots ota_0; a failed OTA falls back
to the other slot. All data partitions keep the offsets of the previous
table, so encrypted NVS and the dashboard image survive the upgrade; the
one-time move from the three-slot layout requires a full USB flash.
Flash offsets used when writing a full image over USB (always include
ota_data_initial.bin so a stale slot selection cannot point at an empty
partition):
python -m esptool --chip esp32s3 write_flash \
0x0 bootloader.bin \
0x8000 partition-table.bin \
0x1a000 ota_data_initial.bin \
0x20000 Safi.bin \
0x920000 storage.bin
Rules for edits (alignment, immovable entries, the full-flash requirement after changes) are in the partitions chapter.