ESP8266 512k flash: compiling using RTOS SDK 1.3
by kacang bawang
Since update from version 1.2 to 1.3 of Espressif’s RTOS SDK, if you try to compile anything targeting a 512kB flash device you get this message:
1 |
`.irom0.text' will not fit in region `irom0_0_seg' |
In this post I will show you how to organize and compile a project to using the RTOS SDK and how to solve the above problem. This post builds on this one, review as necessary.
First, let’s oranize our project. As an example I will use examples/smart_config
from the 1.3 RTOS SDK. Just like before (with the regular SDK) we organize our folder structure like this:
1 2 3 4 5 6 |
/home/my_esp8266_projects/smart_config_rtos src ............ renamed copy of "RTOS_SDK/examples/smart_config" directory Makefile ....... copy from "RTOS_SDK/", we will modify it slightly ld ............. link to "RTOS_SDKSDK/ld" lib ............ link to "RTOS_SDKSDK/lib" bin ............ create empty, output will be placed here |
Notice that we’ve skipped linking to RTOS_SDK/include
and RTOS_SDK/tools
as the makefile specifies these paths explicitly.
Now, let’s fix the makefile. Note that we’re talking about the “root” makefile – one which is in root directory of the project. There are additional makefiles inside the src/
directory. We will not change those.
Add the following to the top of the file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
####################### # My locations # TOOLS = /path/to/esp-open-sdk/xtensa-lx106-elf/bin PATH := $(PATH):$(TOOLS) export SDK_PATH = /path/to/ESP8266_RTOS_SDK export BIN_PATH = ../bin export COMPILE = gcc ######################## ###################### # My defaults. [] = genmisc script defaults # #old=boot_v1.1, new=boot_v1.2+, [none=none] BOOT := none #[0=eagle.flash.bin+eagle.irom0text.bin], 1=user1.bin, 2=user2.bin APP = 0 #20MHz, 26.7MHz, [40MHz], 80MHz SPI_SPEED = 40 #[QIO], QOUT, DIO, DOUT SPI_MODE = QIO #[0= 512KB( 256KB+ 256KB)] #2=1024KB( 512KB+ 512KB) #3=2048KB( 512KB+ 512KB) #4=4096KB( 512KB+ 512KB) #5=2048KB(1024KB+1024KB) #6=4096KB(1024KB+1024KB) SPI_SIZE_MAP = 0 ######################## |
This specifies compilation options related to flash size and specifies locations for the tool chain and the RTOS SDK.
At this point we can try compiling. You should see something like this:
1 2 3 4 5 6 7 8 9 10 |
$ make make[1]: Entering directory `/path/to/smart_config_rtos_1.3_src/src' make[2]: Entering directory `/path/to/smart_config_rtos_1.3_src/src/user' make[2]: Leaving directory `/path/to/smart_config_rtos_1.3_src/src/user' xtensa-lx106-elf-gcc -L../lib -Wl,--gc-sections -nostdlib -T../ld/eagle.app.v6.ld -Wl,--no-check-sections -u call_user_start -Wl,-static -Wl,--start-group -lminic -lgcc -lhal -lphy -lpp -lnet80211 -lwpa -lcrypto -lmain -lfreertos -llwip -lsmartconfig user/.output/eagle/debug/lib/libuser.a -Wl,--end-group -o .output/eagle/debug/image/eagle.app.v6.out /path/to/esp-open-sdk/xtensa-lx106-elf/lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/bin/ld: .output/eagle/debug/image/eagle.app.v6.out section `.irom0.text' will not fit in region `irom0_0_seg' collect2: error: ld returned 1 exit status make[1]: *** [.output/eagle/debug/image/eagle.app.v6.out] Error 1 make[1]: Leaving directory `/path/to/smart_config_rtos_1.3_src/src' make: *** [.subdirs] Error 2 |
Somehow, starting with version 1.3 of the RTOS SDK the libs from Espressif went up in size, so much so that they don’t fit into the 244kB alloted for irom0. What can we do? We can try compiling with -O2
and -Os
flags, but the resulting size is still too big. There still one thing to try.
Take a look at RTOS_SDK/ld/eagle.app.v6.ld
. It says that we can change the location and size of the irom0 area, as long as we take care not to run into to other areas. The flash.bin
(our own code) is typically a lot smaller than all the irom0 stuff. In this example, the sizes end up being:
1 2 |
27K eagle.flash.bin 257K eagle.irom0text.bin |
Thus, we will steal a little bit of space from the end of the flash.bin
area. Let’s take a look at what that makes our flash layout look like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Before: # ------------- 512K single slot -------------------- # 0x00000 - 0x3DFFF (248kB) flash.bin ............ user code # 0x3E000 - 0x3FFFF (8kB) master_device_key.bin (used for OTA updates, which are useless for us) # 0x40000 - 0x7BFFF (244kB) irom0text.bin ............ espressif's blobs # 0x7C000 - 0x7CFFF (4kb) RF params # 0x7E000 - 0x7FFFF (8kB) wifi config After: # ------------- 512K single slot -------------------- # 0x00000 - 0x2FFFF (197kB) flash.bin ............ user code # 0x30000 - 0x7BFFF (311kB) irom0text.bin ............ espressif's blobs # 0x7C000 - 0x7CFFF (4kb) RF params # 0x7E000 - 0x7FFFF (8kB) wifi config |
To achieve this change in flash layout we need to modify RTOS_SDK/ld/eagle.app.v6.ld
. We need to change *both* the starting offset and the length of the irom0 area. Edit the file like this:
1 2 3 4 5 6 7 8 |
MEMORY { dport0_0_seg : org = 0x3FF00000, len = 0x10 dram0_0_seg : org = 0x3FFE8000, len = 0x18000 iram1_0_seg : org = 0x40100000, len = 0x8000 /*irom0_0_seg : org = 0x40240000, len = 0x3C000*/ irom0_0_seg : org = 0x40230000, len = 0x4C000 } |
Flash is mapped to 0x40200000 in memory address space. irom0
originally appears at 0x40240000, corresponding to 0x40000 in flash space. But we want it to now begin at 0x30000, so we change the org
value to 0x40230000. Don’t forget to also increase length from 0x3C000 to 0x4C000.
Note that this means that we need to flash irom0 to 0x30000 (as opposed to 0x40000 before). Additionally this change will affect all projects, not just this one since we changed the original linker script in the RTOS_SDK directory.
Let’s try compiling. Booya, no errors. Note that the success printout from the makefile includes a hardcoded message of where to flash, so our change will not be reflected.
1 2 3 4 5 6 7 8 9 |
!!! SDK_PATH: /path/to/ESP8266_RTOS_SDK BIN_PATH: ../bin No boot needed. Generate eagle.flash.bin and eagle.irom0text.bin successully in BIN_PATH eagle.flash.bin---------;0x00000 eagle.irom0text.bin-----0x40000 #----- THIS IS WRONG !!! |
Lastly, take a look inside the /bin directory and observe that eagle.irom0text.bin is 257kB, which is indeed too large to fit in the original amount of flash that was reserved for it. Good thing the linker caught that.
Hat tip: kolban
Thank you.
Very useful. I just managed a build with 1.5.2. Noticed following:
– needed to link tools/ to the sdk/tools directory, otherwise it can’t find gen_appbin.py
(you have tools linked as “lib” – typo?)
Also, there was not enough space, but I moved irom0 to 0x40220000 (len = 0x50000).
Have no access to h/w at present but build seemed to go fine.
Thank you for your feedback Dan.
You are absolutely correct about the typo (fixed now). Linking to tools/ is certainly fine. I think you are using the nonOS SDK, which has makefiles that are just ever-so-slightly different. Your new irom0 address is also looks fine, the extent to which it has to be modified will depend on your code size (don’t forget to optimize).
Thanks for your instructions.
I’ve built an image, and like Dan I had to decrease the user space even further to fit the blob.
/*irom0_0_seg : org = 0x40240000, len = 0x3C000*/
irom0_0_seg : org = 0x40220000, len = 0x5C000
My image sizes are
-rw-rw-r– 1 chris chris 43728 Mar 25 21:54 eagle.flash.bin
-rwxrwxr-x 1 chris chris 357885 Mar 25 21:54 eagle.irom0text.bin
so flash.bin should fit in the 0x20000 user space.
When I flash my image I get a crash loop as below.
I’m not sure if this is due to my flash reorg, or another fault in my build, or a fault in my device. The device was working with 0.9.0 and 0.9.2 builds.
Has anyone got a post-1.0 512k image that I can put on my device to confirm
the device is OK? I have not found anything later than 0.9.2 pre-built on the net.
ets Jan 8 2013,rst cause:1, boot mode:(3,7)
load 0x40100000, len 31204, room 16
tail 4
chksum 0xe4
load 0x3ffe8000, len 2116, room 4
tail 0
chksum 0xf0
load 0x3ffe8850, len 10368, room 8
tail 8
chksum 0x34
csum 0x34
Not really sure what is causing your crash. I don’t see anything unusual from the boot log.
rst cause:1 means normal boot
boot mode:(3,7) means it is booting from flash
Can you post a successful boot log?
I found I had to check the toolchain+SDK out on an earlier tag (corresponding to 1.3) and then the process worked fine. The version I did from latest (1.5.2) which needed more address changes failed to work in hardware. So:
git clone –recursive https://github.com/pfalcon/esp-open-sdk
git fetch
git checkout b44afa47b5fdbcfe45d815e03bc521f0664ffc43
make STANDALONE=y
This (following the excellent instructions from KB) then built these binaries which seem to work fine on my 512k ESP-01s:
http://temple.dk/esp8266/build13/bin/eagle.irom0text.bin (load at 0x40000)
http://temple.dk/esp8266/build13/bin/eagle.flash.bin (load at 0x00000)
These work better for me than other early version binaries I’ve seen posted around, which seem to give various error messages under boot on my ESP-01s at least. All I wanted was an AT firmware load which a) works on 512k and b) supports the UART_CUR command, the above is the only way I’ve found.
Hey, glad to hear you were able to get it to work. One more thing to check crossed my mind just now, as I was reading your comment. There was at one time a bug in esptool.py where the higher addresses had to be flashed before the lower ones. I am not sure if it was ever fixed, but I still flash from high to low just in case.
Thank you very much!
I have one ESP8266-01 (512kb flash) and I was trying to make it work for about 2 days…
You really had an amazing ideia, it’s working very well.
I’m using RTOS with Wifi and Paho MQTT.
You’re welcome Gustavo 🙂
Glad to hear from somebody else working with the RTOS SDK
I updated the RTOS_SDK to version 1.5
It seems that the default “irom0_0_seg” value has changed: 0x40220000, len = 0x5C000
I’m having a lot of booting issues, a lot of fatal exceptions, some code (222) and others code(29). There is something wrong with the address.
Any thoughts?
Inside RTOS_SDK/ld/eagle.app.v6.ld version 1.5 we have:
/* eagle.flash.bin @ 0x00000 */
/* eagle.irom0text.bin @ 0x20000 */
/* Flash Map, support 512KB/1MB/2MB/4MB SPI Flash */
/* |……|…………………………|……………………..|…..|….| */
/* ^ ^ ^ ^ ^ */
/* |_flash.bin start(0x0000) |_irom0text.bin start(0x20000) | */
/* |_flash.bin end |_irom0text.bin end */
/* |_system param area(0x7b000) */
/* NOTICE: */
/* 1. You can change irom0 org, but MUST make sure irom0text.bin start not overlap flash.bin end. */
/* 2. You can change irom0 len, but MUST make sure irom0text.bin end not overlap system param area. */
/* 3. Space between flash.bin end and irom0text.bin start can be used as user param area. */
/* 4. Space between irom0text.bin end and system param area can be used as user param area. */
/* 5. Make sure irom0text.bin end . 512KB—>0x07b000 */
/* 2>. 1MB—–>0x0fb000 */
/* 3>. 2MB—–>0x1fb000 */
/* 4>. 4MB—–>0x3fb000 */
/* 7. Don’t change any other seg. */
MEMORY
{
dport0_0_seg : org = 0x3FF00000, len = 0x10
dram0_0_seg : org = 0x3FFE8000, len = 0x18000
iram1_0_seg : org = 0x40100000, len = 0x8000
irom0_0_seg : org = 0x40220000, len = 0x5C000
}
I updated the RTOS SDK to version 1.5
They updated irom address:
/* eagle.flash.bin @ 0x00000 */
/* eagle.irom0text.bin @ 0x20000 */
/* Flash Map, support 512KB/1MB/2MB/4MB SPI Flash */
/* |……|…………………………|……………………..|…..|….| */
/* ^ ^ ^ ^ ^ */
/* |_flash.bin start(0x0000) |_irom0text.bin start(0x20000) | */
/* |_flash.bin end |_irom0text.bin end */
/* |_system param area(0x7b000) */
MEMORY
{
dport0_0_seg : org = 0x3FF00000, len = 0x10
dram0_0_seg : org = 0x3FFE8000, len = 0x18000
iram1_0_seg : org = 0x40100000, len = 0x8000
irom0_0_seg : org = 0x40220000, len = 0x5C000
}
Those are the new eagle.app.v6.ld settings for RTOS SDK version 1.5
Should I use the original values and write irom to 0x20000?
Or should I keep using your address and writing irom to 0x30000?
Thanks 🙂
Sorry for the slow reply. I think using 0x20000 is ok. There is quite a bit of room to spare between the end iram1_0 and irom0_0. You could probably lower it even further.