ESP8266 FLASH SIZES and SDK issues


Below you will see the MAKE file used in Windows for compiling ESP8266 code for, for example TUANPMs MQTT software which I often use as a base with the Eclipse programming environment.  My code is routinely compiled and run on ESP-12 boards and some time ago when I upgraded from the 0.96 SDK to 1.0 I stumbled on the fact that it would sometimes not run.

Well thanks to a conversation with Baoshi Zhu I may be getting to the bottom of this. It turns out that just maybe the ESP-12 has more FLASH memory than the ESP-01 and ESP-07.  My code runs on ESP-12 but using 1.0 or 1.1 SDK it will NOT run (though it compiles perfectly) on the ESP-01 or ESP-07. I discovered THIS when the above sent me a couple of samples of his excellent backboards for the ESP-07 (more on that later) and my code compiled on them but refused to run. It was not until I got an email from him suggesting that memory might be the issue (and I didn’t believe it at first). Sure enough I can repeat the problem on the 01.  The code compiles perfectly but nothing happens when you try to run it.

So – the question is – does anyone know how to modify this MAKE file to FORCE the use of a 4Mbit (512KB) FLASH… obviously the code fits or it would not work with the 0.96 compiler??? Once resolved this might prove useful for a lot of people.

# Changelog
# Changed the variables to include the header file directory
# Added global var for the XTENSA tool root
# This make file still needs some work.
# Output directors to store intermediate compiled files
# relative to the project directory
BUILD_BASE    = build
FW_BASE        = firmware
FLAVOR = release
#FLAVOR = debug

# Base directory for the compiler
XTENSA_TOOLS_ROOT ?= c:/Espressif/xtensa-lx106-elf/bin

# base directory of the ESP8266 SDK package, absolute
SDK_BASE    ?= c:/Espressif/ESP8266_SDK_1.01 path and port
PYTHON        ?= C:\Python27\python.exe
ESPTOOL        ?= c:\Espressif\utils\
ESPPORT        ?= COM6

# name for the target project
TARGET        = app

# which modules (subdirectories) of the project to include in compiling
MODULES        = driver mqtt user
EXTRA_INCDIR    = include $(SDK_BASE)/../include

# libraries used in this project, mainly provided by the SDK
LIBS        = c gcc hal phy pp net80211 lwip wpa upgrade main ssl

# compiler flags using during compilation of source files
CFLAGS        = -Os -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals  -D__ets__ -DICACHE_FLASH

# linker flags used to generate the main object file
LDFLAGS        = -nostdlib -Wl,–no-check-sections -u call_user_start -Wl,-static

ifeq ($(FLAVOR),debug)
CFLAGS += -g -O0
LDFLAGS += -g -O0

ifeq ($(FLAVOR),release)
CFLAGS += -g -O2
LDFLAGS += -g -O2

# linker script used for the above linkier step

# various paths from the SDK used in this project
SDK_LIBDIR    = lib
SDK_LDDIR    = ld
SDK_INCDIR    = include include/json

# we create two different files for uploading into the flash
# these are the names and options to generate them
FW_FILE_1    = 0x00000
FW_FILE_1_ARGS    = -bo $@ -bs .text -bs .data -bs .rodata -bc -ec
FW_FILE_2    = 0x40000
FW_FILE_2_ARGS    = -es .irom0.text $@ -ec

# select which tools to use as compiler, librarian and linker
CC        := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc
AR        := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-ar
LD        := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc

#### no user configurable options below here
FW_TOOL        ?= $(XTENSA_TOOLS_ROOT)/esptool
SRC_DIR        := $(MODULES)
BUILD_DIR    := $(addprefix $(BUILD_BASE)/,$(MODULES))

SDK_LIBDIR    := $(addprefix $(SDK_BASE)/,$(SDK_LIBDIR))
SDK_INCDIR    := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR))

SRC        := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c))
OBJ        := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC))
LIBS        := $(addprefix -l,$(LIBS))
APP_AR        := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a)
TARGET_OUT    := $(addprefix $(BUILD_BASE)/,$(TARGET).out)

LD_SCRIPT    := $(addprefix -T$(SDK_BASE)/$(SDK_LDDIR)/,$(LD_SCRIPT))

INCDIR    := $(addprefix -I,$(SRC_DIR))
EXTRA_INCDIR    := $(addprefix -I,$(EXTRA_INCDIR))
MODULE_INCDIR    := $(addsuffix /include,$(INCDIR))

FW_FILE_1    := $(addprefix $(FW_BASE)/,$(FW_FILE_1).bin)
FW_FILE_2    := $(addprefix $(FW_BASE)/,$(FW_FILE_2).bin)
BLANKER    := $(addprefix $(SDK_BASE)/,bin/blank.bin)

ifeq (“$(V)”,”1″)
Q :=
vecho := @true
Q := @
vecho := @echo

vpath %.c $(SRC_DIR)

define compile-objects
$1/%.o: %.c
$(vecho) “CC $$<”

.PHONY: all checkdirs clean

all: checkdirs $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2)

$(vecho) “FW $@”

$(vecho) “FW $@”

$(vecho) “LD $@”
$(Q) $(LD) -L$(SDK_LIBDIR) $(LD_SCRIPT) $(LDFLAGS) -Wl,–start-group $(LIBS) $(APP_AR) -Wl,–end-group -o $@

$(APP_AR): $(OBJ)
$(vecho) “AR $@”
$(Q) $(AR) cru $@ $^

checkdirs: $(BUILD_DIR) $(FW_BASE)

$(Q) mkdir -p $@

$(Q) mkdir -p $@

flash: firmware/0x00000.bin firmware/0x40000.bin
$(PYTHON) $(ESPTOOL) -p $(ESPPORT) write_flash 0x00000 firmware/0x00000.bin 0x3C000 $(BLANKER) 0x40000 firmware/0x40000.bin

blank512k: firmware/0x00000.bin firmware/0x40000.bin
$(PYTHON) $(ESPTOOL) -p $(ESPPORT) write_flash 0x00000 blank/blank512k.bin

test: flash
screen $(ESPPORT) 115200

rebuild: clean all

$(Q) rm -f $(APP_AR)
$(Q) rm -f $(TARGET_OUT)
$(Q) rm -rf $(BUILD_DIR)
$(Q) rm -rf $(BUILD_BASE)
$(Q) rm -f $(FW_FILE_1)
$(Q) rm -f $(FW_FILE_2)
$(Q) rm -rf $(FW_BASE)

$(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir))))


27 thoughts on “ESP8266 FLASH SIZES and SDK issues

  1. hi pete,

    i have chosen ESP8266 chip for my Engineering Project. I want to use RTOS SDK so that i can make use of multithreading in the program. i’m Having a lot of problems compiling the Program using the latest RTOS SDK V1.4.x in windows. I have tried numerous tutorials from other site and failed. Can you please guide me in compiling RTOS SDK from scratch in either linux or windows(whichever you prefer). And also i wanted to know the maximum number of threads we could run in ESP8266_RTOS_SDK.

  2. Dear Pete,
    I know you from some other ESP8266 site. Happy to see you here. I have a problem with ESP8266 12E and 12F series about write commands. When I need to write data to the ROM in ESP8266 it only allows to around 6800 times with (w+) command. I am using both integer and float and lastest and previous firmwares but nothing changes. An example simple code is below. W,th ESPlorer I run the codes and when both test1 lua and test2 lua reaches to 3400 file system starts to reset the module. I only activate module by formatting it. If I use just one file it reaches around 6800 cycle of writing. With (a+) command and 2 files I only managed to write up to total 13600 number somehow. Then again a format is needed.
    Any help would be appriciated.

    tmr.alarm(6, 100, 1, function()


    1. hi there Ugur

      Sorry I gave up on Lua a long time ago – not enough RAM and it was crashing often – I went to programming the chips in C and have had no problems since. So afraid I can’t help you – someone else may have something to say..

  3. Hello Everyone,
    I try to compiling the code of mesh.But it show below error what will be the issue
    c:/Espressif/ESP8266_SDK/lib\libmain.a(app_main.o): In function `user_uart_wait_tx_fifo_empty’:
    (.irom0.text+0x5c4): undefined reference to `user_init’
    c:/Espressif/ESP8266_SDK/lib\libmain.a(app_main.o): In function `user_rf_pre_init’:
    (.irom0.text+0x85a): undefined reference to `user_init’
    collect2.exe: error: ld returned 1 exit status
    C:/Users/abc/worksorg/meshnetwork/Makefile:187: recipe for target ‘build/app.out’ failed
    mingw32-make.exe: *** [build/app.out] Error 1

  4. You have it the other way around, irom0text.bin stays on flash and flash.bin is loaded into memory. This is just an example (default) layout, you can change the split with the linker file. The reason it is split is just a poor design decision by espressif, when you use a boot loader (rBoot or the sdk one) you can combine them into a single file that is written in one chunk to the flash. The reason for two “user data” areas is just to fill in the gap that that poor decision leaves, if you use a loader then you just have a single larger user data area.

  5. So I have been using Lua Scripts for some time and now moving to SDK.
    I am using the Unofficial SDK and read the documentation that comes with it in the doc directory.

    I have some doubts:

    What is the difference between: flash.bin and irom0.text.bin??
    Why is there two different sections in the ESP Flash Mapping?
    In the FOTA section, they showed two user firmwares user1.bin and user2.bin, why two firmwares??

    I might be posting this off topic, but I am not getting reply from the esp community and would like to know more about SDK. Thank you.

    1. The file names are arbitrary, but a standard sdk app has two files, one contains the elf sections that go in memory and the other (the larger one) contains the sections that stay on flash and are accessed through memory mapped flash.
      When using a boot loader (sdk or rBoot) all sections are contained in a single file.
      The only really safe way to do OTA is have two copies of the rom on the device, one that is running and one that is to be updated and switched to. If these are both in the same 1mb chunk of flash they need to be linked differently. So user1 and user2 are the same rom, just linked differently depending on where they will sit within that 1mb chunk. If they are to be in different 1mb chunks of flash (but the same relative position within each) you only need to link a single file which can be used in either 1mb chunk.

      1. Thanks a lot Burton, that cleared most of my doubts.

        I am still unclear about the Flash partitions though.

        In the section “Flash Map” of IOT SDK Manual document, it demonstrates a 512KB flash map for none boot:

        Flash.bin| User Data| User Parameter |irom0text.bin| User Data| System Parameter

        What is the need to partition two 256KB segments?
        Why is there two User Data segments?
        Ans as per your explanation, flash.bin will contain data that remains on flash and iromtext.bin contains the elf data that goes into memory. Am I right? Or is it the other way around?

        *Ignore my poor drawing skills 🙂

  6. Hello i am a beginner to ESP8266 , i got acouple of ESP-01 from Aliexpress
    and i want to use it as wifi shield to send and receive data connected it to Arduino Uno , Nano etc. using Blynk app on android.

    my problem is to use it with Blynk it must be loaded with AT firmware (the official one) , and the SDK 1.0 AT command v 22
    mine has FW 0.95.

    any easy way to do that and where can i find the required uploader and FW files

    1. Blynk looks very near – a shame you have to use the AT firmware.. however… if that’s the direction you want to go (see the article I just did on websockets – though that means your own “cloud”) – the ESP-01 boards are not the easiest to program – as you’ll need an FTDI board (usb-serial convertor) and some interfacing unless your FTDI can output 3v3 volts. a simpler bet would be something like the nodemcu or other variation that has a micro-usb connector – then it is just a matter of getting the right software. You will need the facility to FLASH the chip – and the code can be had from the ESPRESSIF forum. On a PC, I personally found it easiest to get hold of the ALTERNATIVE ESP8266 environment which has just about everything you need (assuming you’re using Windows) – on Linux, you’ll need to seek advice from others. Just Google “ESP8266 flashing AT software” – someone will already have done this and that will save you some learning curve. In the end it is all very easy, just a bit of a learning curve. This advice seems pretty good at first glance.

      1. Hello,
        when ever i try to complie code the following errors occurs.Can you tell me what will be the issue

        ets Jan 8 2013,rst cause:1, boot mode:(3,7)

        load 0x40100000, len 27468, room 16
        tail 12
        chksum 0x75
        ho 0 tail 12 room 4
        load 0x3ffe8000, len 1376, room 12
        tail 4
        chksum 0xfb
        load 0x3ffe8560, len 5048, room 4
        tail 4
        chksum 0xf3
        csum 0xf3

        1. When you are COMPILING the code!!???!!! That’s a reboot are you sure it is when you are compiling – don’t you mean AFTER you’ve flashed the code?

          1. Sorry not in compiling.After upload the code in esp, the following error shown in output window i.e in putty terminal.

      2. i know that AT FW is sucks , but as Blynk use ITEADLIB_Arduino_WeeESP8266 library that communicate with ESP8266 loaded with AT FW ver 1.0 even not the latest.

        i tried to use OpenHAP but i found it very complicated especially designing the sitemap and
        also add the bindings, so Blynk is the shortcut for now.

        i am waiting the USB To Serial to arrive , to start playing with Blynk

        1. I too found OpenHab to be a little heiroglyphic – and that started me down the road of using MQTT and Node-Red – and I’ve never looked back 🙂

  7. The erase function is buggy, I don’t know if it’s or the esp8266 itself. On my ESP-12 I’ve found many times that writing the bootloader at 0x00000 has also erased the second sector, despite the bootloader only being about 2k and so it should fit comfortably within the first sector.

    And yes, the ESP-12 does have a larger eeprom, it’s 32Mbit. You can make sure you’re rom will fit at link time by setting the section sizes and addresses correctly in the linker script, if you then try to exceed them it will complain when you link the rom.

    You can change the 0x40000 position of the .irom0.text section, but be sure to update the linker script and where you flash too. Better than that if you use the bootloader it supports a newer rom type that puts the .irom0.text section first and your iram section follow straight after, meaning you don’t need to specify an arbitrary split up front.

    I recently wrote a bit about the boot process, the sdk bootloader and even wrote a new open source bootloader myself. See and the couple of articles that follow for more info.


  8. while playing this afternoon, I watched the eclipse console as I flashed an ESP-01 with a sming example. It looked like so:

    [first bin]
    Writing at 0x00000000… (3 %)
    Writing at 0x00000400… (7 %)
    Writing at 0x00006800… (96 %)
    Writing at 0x00006c00… (100 %)

    [second bin]
    Writing at 0x00009000… (0 %)
    Writing at 0x0003c000… (99 %)
    Writing at 0x0003c400… (100 %)

    As you can see it’s reporting the start and end addresses of each of the two flash operations. So if you examine the flash console output from when you flash the problem set, it should be obvious if the first binary is writing into the address range of the second.

    As we’ve discussed, the fix could be as simple as simply assigning a higher or different start address for the second bin. Though of course it would help to know what’s more bloated in v1.01 vs v0.96.

    1. There’s a good chance you are right – I’m now reversing the flashing order (400000 first) and having no issues at all. I’ve not been able to do the fixes suggested in that link in my Windows Makefile however.. but reversing the flashing order does seem to solve it.

  9. Interesting issue.

    Some (random) thoughts:
    – have you tried arbitrarily commenting out code sections to see if the resulting compile now fits?
    – have you tried thinning out debugging or similar code?
    – have you flagged enough of your functions with ICACHE_FLASH_ATTR to move it in memory? Maybe flagged too many?

    There’s some old notes about memory at

    In the main make file, there’s a set of profilers that produce something like this after a compile:
    Section info:

    out/build/app.out: file format elf32-xtensa-le

    Idx Name Size VMA LMA File off Algn
    0 .data 000005b8 3ffe8000 3ffe8000 000000e0 2**4
    1 .rodata 00001a10 3ffe85c0 3ffe85c0 000006a0 2**4
    2 .bss 00009390 3ffe9fd0 3ffe9fd0 000020b0 2**4
    3 .irom0.text 0002f4e8 40209000 40209000 00007020 2**4
    4 .text 00004f69 40100000 40100000 000020b0 2**2
    Memory Usage:
    Section| Description| Start (hex)| End (hex)|Used space
    data| Initialized Data (RAM)| 3FFE8000| 3FFE85B8| 1464
    rodata| ReadOnly Data (RAM)| 3FFE85C0| 3FFE9FD0| 6672
    bss| Uninitialized Data (RAM)| 3FFE9FD0| 3FFF3360| 37776
    text| Cached Code (IRAM)| 40100000| 40104F69| 20329
    irom0_text| Uncached Code (SPI)| 40209000| 402384E8| 193768
    Total Used RAM : 45912
    Free RAM : 36008
    Free IRam : 12457

    … perhaps these might give a clue about whether the files ‘fit’.

    I suspect there’s some setting in the makefile that determines where the two bin files get placed and linked. The 0x40000 might just be arbitrary and can be changed to reallocate memory a bit.

    1. I’m trying to avoid that – I intend to make the program bigger not smaller and it works on the .96 SDK…

  10. Which seems to suggest that the code being written at 0x00000 is too big and is being clobbered by the subsequent write at 0x40000, doesn’t it. Sounds like an off-by-one type bug.

  11. Here’s the funny thing… somewhere I found a directive for ESPTOOL called -bz 512K – but it doesn’t work. Elsewhere I found the suggestion to reverse the flashing order.. and that DOES. It is certainly not a solution, more a CLUGE but it does work and I can now blow the code to both ESP-01 and ESP-07 and it works. Need a better way though..

    flash: firmware/0x00000.bin firmware/0x40000.bin
    $(PYTHON) $(ESPTOOL) -p $(ESPPORT) write_flash 0x3C000 $(BLANKER) 0x40000 firmware/0x40000.bin 0x00000 firmware/0x00000.bin

    ## $(PYTHON) $(ESPTOOL) -p $(ESPPORT) write_flash 0x00000 firmware/0x00000.bin 0x3C000 $(BLANKER) 0x40000 firmware/0x40000.bin

Comments are closed.