Here’s a quick guide to how the ESP32’s flash memory is organized in the Annex project, including why each partition exists and how their sizes are determined.
You should be able to better understand why is so difficult to deal with modules with only 4MB of flash.
When working with the ESP32 using the Arduino or IDF SDK, flash memory is divided into partitions—distinct regions, each with a specific purpose. The partition table, a small file embedded in flash, defines the size, location, and role of each partition. This organization is crucial for managing firmware, persistent data, and user files, and it directly impacts features like OTA updates and filesystem storage.
Partition Roles and Dimensioning
- Standard System Partitions:
- Partition Table: The map that defines all partitions.
- Bootloader: Initializes hardware and loads the application at startup.
- NVS: Non-volatile storage for settings, WiFi credentials, etc.
- OTADATA: Tracks which application partition should be booted, essential for OTA updates.
- Annex Custom Application Partitions:
- Main Application (Annex RDS): The primary firmware partition.
- OTA Partition: In Annex, this is a secondary application used specifically for updates. When an update is triggered, the device boots into this OTA partition, which then overwrites the main application partition with the new firmware. After completion, the device reboots and runs the updated main application. This custom method allows the main partition to be larger and the OTA partition to be much smaller than in the standard ESP32 dual-slot OTA setup.
- LittleFS Partition:
- This partition is dedicated to the LittleFS filesystem, used for storing user files and scripts.
- Its size is determined by subtracting the sizes of the main and OTA partitions (as well as system partitions) from the total flash size.
- Typical 4MB Flash Layout:
- Main Application: ~2MB (0x230000 = 2,294,784 bytes)
- OTA Partition: ~700KB (0xc0000 = 786,432 bytes)
- LittleFS: Remainder, about 1MB
- With LVGL (Larger Firmware):
- Main Application: Increased to 3MB (0x300000 = 3,145,728 bytes) to accommodate the larger firmware.
- OTA Partition: Remains ~700KB.
- LittleFS: Shrinks to only a few hundred KB, which may be insufficient for many use cases.
- Remove the OTA Partition:
- Frees up ~700KB for LittleFS, but you lose the ability to update firmware over-the-air.
- Use an External SD Card:
- Offloads file storage, preserving flash for firmware, but requires additional hardware.
- Trim the Main Application Partition:
- Set the main partition to around 2.6MB, giving more space to LittleFS. However, this limits future expansion of the firmware and features.
Partition Table Configuration
- Standard Partition Sizes:
- Main: 0x230000 (2,294,784 bytes)
- OTA: 0xc0000 (786,432 bytes)
- LittleFS: 0x100000 (1,048,576 bytes)
- With LVGL:
- Main: 0x300000 (3,145,728 bytes)
- OTA: 0xc0000 (786,432 bytes)
- LittleFS: 0x30000 (196,608 bytes)
Summary
ESP32 partitioning is flexible and powerful, but requires careful planning—especially with limited flash. The custom Annex approach, using a small OTA updater partition, maximizes space for your main application and filesystem. However, when firmware grows (e.g., with LVGL), you must balance between OTA capability, internal storage, and potential need for external sdcard. In all cases, modifying partitions involves editing the partition table, a process that complicates firmware updates and device maintenance.