This is an old revision of the document!
Table of Contents
ESP8266 Non-FOTA Flash Layout: WEMOS D1 Mini Pro (16MB)
Framework: esp-open-sdk (NON-OTA Configuration)
This only applies to NON-FOTA firmware versions.
The Espressif SDK family does not natively support a 16 MB flash mapping profile for application code execution. Instead, it handles a 16 MB chip (like the one on the WEMOS D1 Mini Pro) by addressing it as a 4 MB (32 Mbit) layout profile. The remaining 12 MB is invisible to the linker script and can only be accessed manually using raw sector reading/writing APIs (spi_flash_read).
Flash execution
In order to flash ESP8266 the GPIO0 should be connected to GND. This is D3 on Wemos D1 Mini Pro.
Non-OTA Binary Structure
In a non-OTA layout, your build outputs two primary binary files:
- eagle.flash.bin (Flashed at 0x00000): Contains code initialized straight into internal RAM—specifically IRAM (code required to execute with no flash latency, interrupt handlers) and DRAM (initialized global/static variables).
- eagle.irom0text.bin (Flashed at offset 0x10000 or 0x20000): Contains main application code and SDK functions tagged with ICACHE_FLASH_ATTR. It remains in flash memory and is read dynamically via the Xtensa instruction cache (irom0).
Non-OTA Flash Maps: Map 4 vs. Map 6
In a traditional Non-OTA setup the flash is mapped using Flash Map 4 (or 6 depending on the exact SDK version configuration). In Espressif SDK nomenclature, Flash Maps correspond to numerical IDs (selected via FLASH_SIZE or map configuration during compile time).
| Attribute | Flash Map 4 | Flash Map 6 |
|---|---|---|
| Target Hardware | ESP-01 modules or older legacy ESP8266 boards with 512 KB flash chips | ESP-12E/F, NodeMCU, WeMos D1 Mini, and most modern ESP8266 development boards containing 4 MB flash |
| Physical Flash Size | 512 KB (4 Mbit) | 4 MB (32 Mbit) |
Max Code Space (irom0) | ~364 KB – 428 KB | ~880 KB (Bounded by 1 MB MMU cache limit) |
| Storage Beyond 1 MB | None | ~3 MB available for SPIFFS/LittleFS |
1. Flash Map 4 (512 KB Flash / 4 Mbit)
Layout Structure:
0x00000–0x0B000(~44 KB):eagle.flash.bin(IRAM + Data).0x10000or0x20000–0x7B000(~364 KB to 428 KB):eagle.irom0text.bin(Flash-cached application code).0x7B000–0x80000(Last 20 KB): System Parameter Area (RF calibration, Wi-Fi configuration saved by the SDK:esp_init_data_default.binandblank.bin).
2. Flash Map 6 (4 MB Flash / 32 Mbit)
Layout Structure:
0x00000–0x0B000(~44 KB):eagle.flash.bin(IRAM + Data).0x20000–0xFC000(~880 KB):eagle.irom0text.bin(Flash-cached application code).0x100000–0x3FB000(~3 MB): Unmapped / Free user space (available for SPIFFS/LittleFS or user storage).0x3FC000–0x400000(Last 16 KB): System Parameter Area (esp_init_data_default.bin&blank.bin) positioned at the end of the 4 MB physical flash boundary.
Because it is targeted as a 4 MB envelope, the default critical system parameters are pushed to the very end of the first 4 MB segment, not the physical end of the 16 MB chip.
2. Crucial `esp-open-sdk` Compilation & Flashing Quirks
The Linker Script (`.ld`) Constraint
Your application compilation must use the correct linker script. Look inside your sdk directory (ld/) and ensure you target:
eagle.app.v6.ld
This forces the compiler to build the code assuming a single application image (Non-OTA) rather than splitting it into user1.bin and user2.bin layout profiles typical of an OTA environment.
The `esptool.py` Flash Size Trick
When flashing an esp-open-sdk firmware onto the WEMOS D1 Mini Pro, you must be careful with the -fs (flash size) parameter. If you set -fs 16MB, the Espressif system configuration files will be expected at the absolute end of the 16MB space (0xFFC000), which will cause a boot loop (rf_cal_size error) because the SDK logic is expecting them at the 4MB mark.
To successfully flash a Non-OTA open-sdk project on this board, force a 4MB size parameter during upload:
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash \ -fm dio -fs 4MB \ 0x00000 eagle.flash.bin \ 0x10000 eagle.irom0text.bin \ 0x3FC000 esp_init_data_default.bin \ 0x3FF000 blank.bin
Note: If you explicitly want to map out the hidden 12 MB for custom partition spaces or filesystems, you must flashesp_init_data_default.binat0xFFC000andblank.binat0xFFF000, but you must manually ensure your custom open-sdk Makefile overrides the defaultFLASH_SIZEconstants to prevent SDK crashes.
ESP-OPEN-SDK Firmwares
First initial flash
# Full erase first
esptool.py --port /dev/ttyUSB0 --baud 115200 erase_flash
# Flash esp-open-sdk/sdk/bin/esp_init_data_default.bin at 0x3fc000
esptool.py --port /dev/ttyUSB0 --baud 115200 write_flash
--flash_mode dio --flash_size 32m
0x00000 firmware/0x00000.bin
0x10000 firmware/0x10000.bin
0x3fc000 /home/oscar/esp8266/esp-open-sdk/sdk/bin/esp_init_data_default.bin
Subsequential flash
esptool.py --port /dev/ttyUSB0 --baud 115200 write_flash
--flash_mode qio --flash_size 32m
0x00000 firmware/0x00000.bin
0x10000 firmware/0x10000.bin
EASY ESP Firmware
sudo python esptool/esptool.py erase_flash sudo python esptool/esptool.py -p /dev/ttyUSB0 -b 460800 write_flash -fm qio 0x00000 0x00000.bin
NODEMCU Firmware
Finally got the Wemos D1 mini pro with 16 MByte flash.
esptool.py erase_flash esptool.py -b 460800 write_flash -fm qio 0x00000 bin/0x00000.bin 0x10000 bin/0x10000.bin
And finally it was resolved with dev version of NodeMcu prepared in https://nodemcu-build.com/
My best result is 17 modules in the BIN. Many was unsuccessful I reported result in GitHub (with modules) - https://github.com/nodemcu/nodemcu-firmware/pull/1529
Also their own fixed esptool used - https://github.com/nodemcu/nodemcu-firmware/tree/dev/tools
