Sming - Open Source framework for high efficiency native ESP8266 development

User avatar
By gschmott
#26310 Hi Richard -

Thanks for the ideas. I've done some more (preliminary) investigation and discovered one new item. Again, my layout is a 4MB Flash (ESP-12) that's been split in half with the first slot starting at 0x02000 (ROM0) and the second at 0x202000 (ROM1). I have BOOT_BIG_FLASH enabled and can flash one ROM in the upper region and another in the lower region and (manually) switch between them by sending my app an MQTT command instructing it to switch slots.

So, early tests show that I can fairly reliably (minus an occasional time-out) flash ROM1 from ROM0 via the OTA mechanism. However, trying to flash ROM0 from ROM1 *always* results in the lock-up in spi_flash_erase_sector() at sector 2. Does this make sense. Could there be some issue with the 1MB mapping?

I tried to put a ets_print() in my replacement Cache_Read_Enable_New() function but I can never seem to catch it at start-up. However, if I flash two different images into each slot I can *see* that two different images are running when I switch between slots. Can you think of any reason it would be tough for me to catch the ets_printf() in my Cache_Read_Enable_New() override? When should I expect to see it? What's the baudrate when it's shown? Any suggestions there would help. I have looked in my libmain2.a file (that I'm linking against) and it is marked as "(w)eak".

Finally, still no time to investigate SPIFFs in any detail. There is something not quite right there as well.

Thanks for your continual feedback . . . it's been helpful.
User avatar
By rab
#26366 The boot messages from a cold boot come out at 76,800 for some odd reason. After rebooting they generally come out at whatever baud the terminal has been initialised at by the sdk on the previous boot. So to catch them on the first boot you'll need a terminal set at 76,800. I recommend uncommenting the delay in rboot to give a moment for everything to be powered up and in sync before data starts to flow. Without being able to see what rBoot thinks is going on it'll be very difficult to debug the problem, so it's worth getting this first output working.

The lockup when erasing sector 2 while booted to the second rom does sound fishily like you might not really be booted to rom 2, again seeing what rBoot says on startup will help to be sure. I note though you do say that you have different roms and they appear to both run, but I wonder how are you indicating that? If it's a message in code this could end up being from irom or iram, one of which will be dependant on the rBoot loading the right iram sections at boot time and the other having the right rom mapped at run time. Or is it coming from resources in the spiffs, in which case we haven't ascertained yet if that's working right anyway (I suspect it should be though, at least once everything else is).

If it's something easily sharable, and buildable without too much difficulty on my simple setup (I can compile sming samples with my modified makefiles ok), I'd be willing to have a go here and see if I can help get to the bottom of the issue. Especially if once we get it all going you'd be willing to write a little tutorial on how to use rBoot with sming because I've had a number of people enquire. Aside from the simple examples I've tested I don't have any real sming experience.

Richard.
User avatar
By gschmott
#26422 Hi Richard -

Below is the output from booting the two roms:

Code: Select all ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x40100000, len 2208, room 16
tail 0
chksum 0x64
load 0x3ffe8000, len 760, room 8
tail 0
chksum 0x1f
csum 0x1f

rBoot v1.2.1 - richardaburton@gmail.com
Flash Size:   32 Mbit
Flash Mode:   QIO
Flash Speed:  40 MHz
rBoot Option: Big flash
rBoot Option: Config chksum
rBoot Option: irom chksum

Booting rom 0.


And . . . .

Code: Select all ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x40100000, len 2208, room 16
tail 0
chksum 0x64
load 0x3ffe8000, len 760, room 8
tail 0
chksum 0x1f
csum 0x1f

rBoot v1.2.1 - richardaburton@gmail.com
Flash Size:   32 Mbit
Flash Mode:   QIO
Flash Speed:  40 MHz
rBoot Option: Big flash
rBoot Option: Config chksum
rBoot Option: irom chksum

Booting rom 1.


Both images boot up fine. I have a function that prints out which image was flashed (static text . . . in a C++ method) when probed over MQTT. I believe in Sming all C++ functions/methods (unless explicitly marked otherwise) are placed in irom.txt. I'd have to look at the Sming linker file in more details but I think I recall someone asking a similar question a while back.

I think one problem I have is that Cache_Read_Enable_New() is *not* overriding the one in libmain2.a. Here's a dump of that symbol from app.out:
Code: Select allxtensa-lx106-elf-objdump -t app.out | grep Cache_Read_Enable_New
40100098  w    F .text   00000032 Cache_Read_Enable_New


Here's what it looks like in the "app" static library that Sming produces:

Code: Select allxtensa-lx106-elf-objdump -t app_app.a | grep Cache_Read_Enable_New
00000020 g     F .iram.text   00000067 Cache_Read_Enable_New


So you can see it's using the "weak" libmain2.a version in the final output file instead of the one defined in the "app" archive. For the life of me I can't force it to use the stronger "global" one defined in my application.

I found this after searching the Internet:

Gcc (actually the linker) treats libraries differently.
By default, it tries use the first found symbol and does not detect duplicated symbols.


The suggestion is to use the "-Wl,--whole-archive" and "-Wl,--no-whole-archive" options to force the linker to rescan *all* the libraries between the markers when resolving symbols so that it picks the stronger symbol over the weaker., e.g.

Code: Select all(TC)gcc main.c -L. -Wl,--whole-archive -lbar -Wl,--no-whole-archive -o test.exe


That might work but I encountered symbols in both the SDK (and Sming) that are defined multiple times which causes the linker to error out. Likely these should be fixed by ExpressIf and the Sming developers but that doesn't help me at the moment.

I'd share my project but it's a little complex. I created a Docker ESP8266 buildbox where I house the SDK and build tools. Then I pull in Sming and rboot as submodules in a larger Git repo. It works nicely for me but it may be tough for you to recreate. I can certainly share the pertinent files (e.g. linker files, makefiles, etc...) if that would prove helpful. Likewise, I'd love to share the steps necessary to get this to work if I could manage to pull it off. I think I'm close but overriding weak symbols with static libraries is not the usual (nor apparently recommended) use case with the GCC (or xtensa) linker. That probably explains your earlier difficulty. I even tried making Cache_Read_Enable_New() local to the libmain2.a library but that just resulted in an image the reboots due to an exception early on. I also tried re-arranged the order the libraries specified on the linker command-line - no luck.

Do you have any other tricks/suggestions up your sleeves? This probably explains (I think) why I'm not seeing the mmap printf's on the screen during boot. I think it's using the version in my manufactured libmain2.a rather than the one in my application.

Thanks again for the continued suggestions . . .
User avatar
By rab
#26450 Ok, so what happens when big flash is enabled and Cache_Read_Enable_New isn't overridden is that rBoot will load the data and iram sections correctly from the chosen rom, but the memory mapped flash will always be the first 1mb. The result is that everything works fine for rom0, but when booting rom1 you'll get a mismatched iram and irom. In your current tests with just a message different between them you'll probably get away with (except when you try to flash from rom1 and are erasing the rom0 irom code you are using). As soon as there is much more difference between the two roms you'd expect to see exceptions because addresses of functions in irom will not be the same. Also, the wrong spiffs will be used, or if the start offset is different it won't be able to find it at all.

Now, how to get this override working... There are two methods in the readme which I assume you've tried, but I mention it again just in case you haven't tried them both. One involves undefining a symbol and getting the ld options in the right order (I can send you my ld line when I get home). The other involves #including the rboot-bigflash.c code into your main c file, instead of compiling it as a separate object file (I don't know why that works easier, but it did for me).

Another is option is to override at a different point. I haven't actually done this because I didn't need to and it will cost slightly more space in iram. The Cache_Read_Enable_New function is an SDK wrapper for the Cache_Read_Enable rom function. The wrapper must be in iram because it's called when the flash isn't yet mapped. Ideally we replace this with our own copy that looks at the rBoot config to determine which mb to map. By replacing it we only have one wrapper in the final code, but that replacement is the tricky part. So instead we can wrap the rom Cache_Read_Enable function, that's easy because the linker only knows about it because it's named in the ld file, it's not actually part of the libraries we are linking. If we change the name in ld file it won't know about the rom function and will look for it amongst the input we supply to the linker. So we add our own function called Cache_Read_Enable, and rename the rom one in the ld file to Cache_Read_Enable_Old. The SDK wrapper will now call our wrapper, which can then call the real Cache_Read_Enable in rom (by it's new name Cache_Read_Enable_Old). This way there are two wrappers (hence more memory usage) and they both get called, but the end result is the same - we control the parameters that are ultimately passed to the real rom Cache_Read_Enable function that does the mapping. Hope that makes sense.

Third option is to completely replace the rom Cache_Read_Enable to do the rBoot part and avoid having two levels of wrapper, but that would use even more iram.