Memory use ESP8266

Can someone explain this to me..

I’m using the ECLIPSE environment in a PC and only starting to get to grips with the MAKE files – I really still don’t understand most of what’s in there.

I’m looking at the MQTT installation which is one of the easier ones (I don’t understand why the likes of the LUA compilation throws out 18 million lines of un-decipherable gook while the MQTT files churns out very little – only showing you what you need to know about – i.e. errors).

So I understand how non-volatile storage is being done – at the segment 3C000  (I’ll probably get the number of zeros wrong  but that’s not important here).. So we blow some code at 0000, we wipe a little bit at 3C000 – which seems utterly pointless as the startup routines check a checksum at that area to see if it needs wiping/updating…  and then more code at 40000… now that last block seems to fill up rather quickly..

It not possible and indeed more sensible to start at 00000 and work all the way up in one block, leaving, say some blocks at the top free for non-volatile variables. I’d give this a shot myself but I need to understand why everyone splits up the code like this leaving a huge chunk of (unused?) memory down near the bottom.


7 thoughts on “Memory use ESP8266

  1. Just a guess but I think those code boundaries are baked into the hardware and/or the mostly inscrutable xtensa OS I want to learn alot more about XTOS; I spent about an hour last night trying to turn up some more docs on the Tensilica xtensa xtos c library, but not a sausage, as you might say.

    I suspect that vectors (pointers) and the most critical controlling instructions load at 00000, and the rest load above 40000. This is probably configurable somewhere, but at that point you're now editing the OS, which could be a huge commitment to months of debugging.

  2. Not really correct. TL;DR is that fimrware is split in two parts - one will be copied directly to IRAM (which is separate from normal RAM used for HEAP BTW), other one will be kept on flash.

    Those addresses are not burned into hardware, they are configured inside of linker script (, for example). As you may know, for ESP8266 the code can be in normal .text section or in .irom0.text section when you specify magic ICACHE_FLASH_ATTR, which is defined like this if you grep your SDK:

    #define ICACHE_FLASH_ATTR __attribute__((section(".irom0.text")))

    Now all the code in .text section will be copied by bootloader to IRAM from where it will be executed. There is 32kb of IRAM so it's imposible to fix all the code there. Rest of the code will be executed from flash by ICACHE (istruction cache mechanizm).This is possible because whole flash is memory mapped (at 0x40200000).

    Knowing that, open up your and check fist section:
    dport0_0_seg : org = 0x3FF00000, len = 0x10
    dram0_0_seg : org = 0x3FFE8000, len = 0x14000
    iram1_0_seg : org = 0x40100000, len = 0x8000
    irom0_0_seg : org = 0x40240000, len = 0x32000

    See the org argument? Since 0x40240000 is where code from irom0 segment will go and 0x40200000 is base address for flash mapping, the code will actually be on 0x40000 in the flash.

    Now the code for normal .text section could be placed in any place, the addresses specified by the script are out of falsh memory mapping (0x40100000). That's not a problem becasue the code will be copied anyways (as described earlier).

    Now that 0x0 address for IRAM segment may be hardcoded as this is where the bootloader will be looking for it. But the irom0 section address is read from the ELF section when image is created and then when when it's transfered to the SoC when flashing so you can change this. Compare it with the link script from LUA firmware, for example:

    dport0_0_seg : org = 0x3FF00000, len = 0x10
    dram0_0_seg : org = 0x3FFE8000, len = 0x14000
    iram1_0_seg : org = 0x40100000, len = 0x8000
    irom0_0_seg : org = 0x40210000, len = 0x50000

    As you can see, they put their irom section on 0x10000 instead of 0x40000.

  3. If that's not enough, here are some more details:
    - when flash utility talks to bootloader to flash the code, it will send it in segments. Each segment consist of memory offset, size and data itself. This way the bootloader knows where it should look for IROM section. I'm not sure if IRAM (.text) section can be moved to place other than 0x0, possibly yes but haven't tried that as I don't see too much sense in that.

    - when the bootloader starts it will print some information which is usually seen as garbage becasue of odd baud rate. But if you set your baud rate right, you would see something like:

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

    load 0x40100000, len 24236, room 16
    tail 12
    chksum 0xb7
    ho 0 tail 12 room 4
    load 0x3ffe8000, len 3008, room 12
    tail 4
    chksum 0x2c
    load 0x3ffe8bc0, len 4816, room 4
    tail 12
    chksum 0x46
    csum 0x46

    So you can see that it loads three segments - .text to 0x40100000 (this is the start address of IRAM), then some section (probably .bss) to 0x3ffe8000 (this the start address of normal RAM aka DRAM) and then one other section (probably .rodata) to 0x3ffe8bc0. It says nothing about ICACHE section as it's not copied anywayre, of course.

    Hope this makes at least some things clearer 🙂

  4. And here I am back again looking for ways to get stuff out of the .text section. I use ICACHE_FLASH_ATTR almost everywhere but the Makefile is reporting I'm using 7c20 of my ,TEXT 32k. I tried adding something the other day and got the message out of .text space... surely there has to be another way to minimise the use of this area??

  5. Hello Pete,

    I am stuck with this irom0_0_seg issue,

    I get this error: "xtensa-lx106-elf/bin/ld.exe: build/app.out section `.irom0.text' will not fit in region `irom0_0_seg'"
    collect2.exe: error: ld returned 1 exit status

    I believe you too have faced this issue and have figured out a way to work around this. I too am using Eclipse + Windows build environment from Mikhail Grigorev.

    Please shed some light on the way to get out of this...

    1. All functions must have

      Just before the function name or you are soon going to run out of irom0 RAM.... you will simply have to systemicially go through all functions until you get enough RAM back.

Comments are closed.