-
Notifications
You must be signed in to change notification settings - Fork 13.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
section .text will not fit in region iram1_0_seg #4551
Comments
Well, you can't post the code so how do you think one can help you? Do you use F(), PSTR, ICACHE_FLASH_ATTR...? |
Pablo, I appreciate the issue with posting defects without code; unfortunately, this issue is with the final link step. There are many libraries and tools where addressing problems does not require public sharing of a complete source code base. Were this required to debug popular toolchains, they couldn't be used for anything closed-source. I posted the issue for two reasons: 1) it seems like a serious problem with the 2.4.1 release and 2) sometimes the issue is obvious to an experienced developer who may be able to point me in the right direction quickly (I've already spent hours on this). I am very experienced with bare-metal ARM/Cortex development using the gnu toolchain, but am relatively new to the xtensa tools and so far have been blissfully isolated from them thanks to the delightful Arduino/ESP8266 Core IDE/tools you have so graciously made possible. I'm going through the linker scripts and build products now to figure out what's going on and will post more on this as I dig deeper. |
@dalbert2 you have to test the issue with git version first (IMO this has been suggested many times by developers). IMO no one can tell you what is wrong with near to zero informations about your project. To be more specific - did you check that you use ICACHE_FLASH_ATTR decorators where possible as i suggest? That's all i can say... |
I think we have recently moved some stuff (vtables?) into IRAM to free up some heap space. If your application used almost all available IRAM in the previous version it may fail to link with the new one. You can check this by running |
Thank you both for your help! Pablo, yes I make extensive use if ICACHE_FLASH_ATTR for all code except functions that will be called from an interrupt context. I also make extensive use of PROGMEM for literals. Ivan, thank you for jumping in! My .text section (built with 2.4.0) is 0x7f43 bytes, so yes, it's on the edge and apparently the change to 2.4.1 pushed it over the limit. The majority of my code (0x60a2d bytes) is in .irom0.text located in SPI flash, but it looks like I will need to find a way to reclaim some instruction RAM. A request: the build output reports "Memory Usage" which I had assumed to be RAM, but I now understand is only data RAM (.data+.rodata+.bss). It also reports "Program Size" which is SPI Flash usage (.irom0.text+.text+.rodata+?). However, it doesn't let you know how close you are to the 0x8000 (32K) limit of instruction RAM which is actually the tightest memory constraint on the platform. It would be very nice if the build output included % IRAM used. This would help many Arduino users who won't be familiar with code segmentation at all and it will also help experienced embedded developers who are not familiar with the split regions for instruction and data RAM (since your very nice Arduino environment insulates us from all of that). For example, I knew some of my code would be located in RAM, but I didn't realize that instruction RAM was separate from data RAM, so when I saw I had plenty of free RAM, I thought I was OK. Thank you both again for the quick responses and for helping me understand the issue! For my reference and for anyone who comes across this later: |
I have experienced similar issue recently - if I enable debug serial I would get the error message. Like @igrr suspected, my issue was related to the vtable placement. I had to remove some virtual destructors in the base classes to reduce vtable size. |
@Adam5Wu I haven't had a chance to check yet, but if the base SDK + Arduino pushes IRAM to 0x7300 bytes, that is a very serious problem; it means there's less a smidge more than 3K instruction RAM left for the user. |
Hi @dalbert2 , I still don't have plans to travel to Maryland, so that beer is still pending :) One PR that could be relevant for you is #4384 , although I somehow doubt it will be enough. Are you using your own ISRs? If you are, and they contain significant amount of code, I have an idea that may help you out. Let me know if that's the case, and we can discuss details. Also, if it's viable, I could take a private look at your code, and provide some feedback as to what you could do, as I have done a couple of times for others. |
Hi @devyte, the beer will be waiting when you have time to visit! Thank you for the pointer to #4384 If the cont_* functions haven't been moved to SPI Flash in 2.4.1, I'll try making a build using git head (the instructions for that don't seem to work but I'll figure it out) or I will make the changes to 2.4.1 locally; thanks for the suggestion and for finding more IRAM space to reclaim! My code has several ISRs; the application is a wireless gateway (proprietary telemetry network to WiFi) so there are ISRs to respond to radio events and a couple of front-panel push-buttons. My understanding is that any code that runs in the interrupt context must be located in IRAM. Now that I understand the problem (extremely limited space for ISR code), I can likely fix by reducing ISR functionality and shifting more of the work to the event loop. If I run into trouble, I'll happily take you up on your kind offer and if you have other approaches for freeing up IRAM, I'd love to hear them. I still haven't checked base free IRAM, but if it really is ~3K as Adam reported, I think it's a significant issue that merits further examination. Because the ESP8266/Arduino is an embedded platform, anyone using it for non-trivial applications will likely have some ISR code. At the very least, I think the need for ICACHE_FLASH_ATTR and ICACHE_RAM_ATTR decorators should be front and center in the documentation, covered at least as well as the PROGMEM documentation since this is not an obvious thing for developers new to this platform and likely bites everyone as soon as they start writing non-trivial programs. I am not part of this project, but will happily contribute the documentation if permitted. BTW, with respect to your comment in #797, IMO any developer who is writing interrupt handlers should be able to do so without the need for garbage collection and we'd benefit far more from better interrupt handling behavior and more available instruction RAM. Thanks again! |
I hit against this error right after 2.4.1 was committed (I normally sync to HEAD every few days), so I just rolled back to 2.4.0, expecting this just to be some minor commit typo that would be fixed soon. I use no extra ISR's (but I was planning to soon), and I try hard to not to use iram for variables, so this change in iram usage may be a bigger issue for me than I first thought. Does anyone have a list of advanced best practices to reduce iram usage other than the typical PROGMEM/PSTR()/F() wrapping? My .text usage under 2.4.0 is 0x7480, not quite as tight as dalbert2's project, but clearly pushing the limits. Backing out the vtables change from #4179 itself doesn't help , and all was fine leading up to 2.4.1 anyway, so I'm guessing something else is using more iram in 2.4.1 as well, It is commit: 170911a that triggers the blowout of iram for me. I'll look into why that is. On the previous commit 0643d6e .text usage is at 0x74f8. So, 2.4.1 works for me, I got confused until I tested further. |
So far, my first guess is that now that gdb_hooks.h is included explicitly in core_esp8266_main.cpp, it is pulling in extra code bits that use iram, even though it is supposed to be just a stub when not using gdb. Update: |
@dalbert2 Contributions are always welcome. If you propose a change, I'll take a look.
The idea is that you move out all your ISR code out of IRAM, and move that single scheduling function into IRAM. There's a PR that sort of goes along these lines, but for the Ticker instead of hw ISRs: #4209 . It can serve to explain the idea. |
@hreintke That sounds interesting, and I've been thinking of a rewrite of the scheduled function code in C++. |
I hit the IRAM wall again when I am trying to make a moderate complexity project, with ArduinoJson, AsyncWebServer, AsyncMQTT, vFATFS. The vtable size is 1750h and there no way it could fit into IRAM in the near term, even with all the improvement efforts mentioned in above discussions... Is there an easy way to make vtable location configurable? I am not very familiar with the linker part of workflow, is it possible to have |
Maybe it's worth considering removing the move to IRAM for vtables completely. When I proposed it I was thinking of putting vtables completely into flash (which would avoid all these issues and not take any add'l flash space over the way before where they were in BSS). But that would make accessing a virtual class function impossible during interrupt processing. So it ended up in IRAM, which for my own use cases was pretty empty, but is obviously not so as the SDK updates and on larger, class-based projects. However, that's one heck of a vtable size...at 6KB it'll eat up over 15% of total available RAM! The alternative, if deferred functions are working, would be to put VTABLES in flash (change the linker entry position) and require folks to use deferred funcs for processing... |
@d-a-v thanks a lot, that certainly makes life easier switching between modes! @earlephilhower I admit I am a bit of OO maniac... some of my classes use dual inheritance so the vtable tends to grow :D I think vtable in IRAM still have lots of value, with so little memory, every bit of saving counts! |
@d-a-v, @earlephilhower If the "move vtables" had a 3rd option "flash", then folks like me who mostly code in c instead of c++ could see an increase in both free iram and free heap? |
@Eszartek yes, it would increase iram and heap as the constant vtable would only ever be present in one spot (flash). You're under the usual restriction of not using classes w/vtable in IRQs or while doing SPI work (i.e. anywhere your code needs to be in IRAM to work). If this was extended, it's trivial to add an option to move I didn't try adding that to the earlier PRs because if you use that macro in your own code it'll crash w/o pgm_read_byte() mediated accesses. |
@Eszartek I will leave the Makefile flash option to the professionals. I was only the Makefile initiator here, because I sometimes do the operation by hand too and it costs the same price. |
@d-a-v I find it interesting to read all this discussion, that each vtable storage scenario (heap, iram, flash) has value depending on the project design. Up until now, I have only been concerned with minimizing heap usage and stuffing as much into flash as possible. I never imagined there were more gotchas lurking around the corner. Cool info! |
@earlephilhower I appreciate the insights and ideas. I'd like to respectfully suggest that until a flexible option for placement of vtables is available, the development team consider rolling back the move of vtables into IRAM or move them to flash. Moving vtables to IRAM has broken many medium-sized applications and may break the entire system depending on how the core develops. I believe it would be healthier for the project to maintain backward compatibility. The restriction of not using virtual functions for interrupt service routines is far less damaging than not being able to write non-trivial interrupt service routines at all (these are embedded systems after all). Thanks again to all the devs for all of their hard work on this, and I look forward to your decision! |
6K in vtables... Wow. @Adam5Wu have you considered a template based design instead of a polymorphic one? |
@dalbert2, all: @d-a-v has just pushed a makefile-based way to select iram or heap (the traditional way) for the tables. I'm going to add a mode to make it all in flash, as well, and in fact I think that's the best spot for them. IRQs and vtables are a bad mix IMO, and relatively uncommon, so flash as default a) saved heap and iram, and b) will work for the majority of folks. With people doing serious work where they need large vtables and access in IRQs, they can use either heap or iram via the makefile. I think that'd cover things. Backwards compatible for the vast majority of folks, even with medium to large projects (and giving them extra RAM to work with), but customizable for advanced users. OOM errors are probably the biggest issue on ESP8266, so I'd like to help solve them by default... |
You guys are awesome...thank you so much! |
@d-a-v @earlephilhower The new Makefile to choose heap/iram works perfect for me. I can now compile my project from the tip of master. Since now I'm all curious about iram usage, I wanted to see how much usage has changed since 2.4.1: Compiled with master with vtables in heap
Compiled with 2.4.1
So that is (7e48-74f0) = 958h or 2392 bytes more iram usage now vs 2.4.1. If this is the correct way to look at the usage, does the handful of commits since 2.4.1 really need to use this much more iram? Or, is this not a concern for me and I should stop dwelling on it? Update: Here is the results of vtables in flash:
.text section is the same as vtables in heap, but flash usage (.irom0.text) bumped up appropriately. Thank you @d-a-v & @earlephilhower for your work on this! |
Am I reading this correctly, even with the Makefile changes, there is virtually no IRAM available (only 440 bytes)? Having no ability to write ISRs seems like a critical problem for an embedded platform; what are the changes that consumed so much IRAM and are they really worthwhile? |
Check the .MAP output on git HEAD and look at the .text section. On the Blink example, I see about 0x6000 bytes taken by the SDK libs. LWIP2 looks like ~0x0500 bytes. On Arduino code, the sizes looks like below:
I think the libc replacements should probably able to be moved out (if you're calling _fopen_r in an interrupt, you are so far from correct it's not funny....) Some routines in core_wiring_digital might be able to be moved, (do you need to be able to attach or detach an interrupt, during an interrupt?) but a lot of the code needs to be there since you use IRQs for doing digitalWrites() to do PWM or stepper control or whatever. Same for cont_util (after the single init call, the cont_init fcn should never be used again....and even so, does it need to be in ram?) If there was a way to guarantee the cache is in a usable state, about 2/3 of the postmortem could be punted to flash, I think. |
good suggesting with libc - I took them all out and got an extra 192 bytes... The problem with running around doing these things is that unless you know everywhere in the library that they are used, you might be causing problems that will bite you in the backside weeks later... But any other suggestions? And it's interesting to note that the users on the Espressif are complaining because the SDk is itself become bloatware... As I said on the other post, having over 93% of a critical resource used before the user starts to write a program is just silly.. This IRAM issue looks to be the achilles heal of the 8266, as soon as you try and write a non trivial program on the 8266 you hit that 32K limit... Every bit that come out of the arudnio library needs to come out, even if that slightly limits some things (like not being able to call _fopen from an interupt!). |
should I start a new post with all the things I find to delete? I just trying them and seeing what happens :-) (almost random monkey approach)... ie Why would I need - Tone.c? Gone... hexdump? (not interested) gone. in postmortem - also something I'm not interested in - how is that ending up in IRAM? In fact, I may as well pull all the gdb stuff - that's an example of what I mean by bloat as you don't want any of it in your final code, and most people wouldn't use it in developing either.. So it should all be #defined out unless someone wants to use it.. (Of course, it may be and I just haven't seen it yet! ie until today I've never bothered with what inside the library .. :-) ). I'm looking for anything with ICACHE before it that can be got rid of... :-) |
@steminabox Your approach is flawed. If you remove.something like tone.c, and your app still builds, then you have gained nothing, because the TU wasn't being included in your build anyways. You seem to be forgetting about some build optimizations. About postmortem, that's a safety net. If your app crashes, or runs oom, then you want to know why and where. If you remove that, then your app will crash and not give you any useful insight as to why. You have the following choices:
About gdb stuff, I'm not sure if there is any overhead if it is not actively inited, I.e.: I suspect the TU should get left out, same as in other cases, but I'm not sure. Instead of shooting in the dark, how about you implement an idea that just came up? Put all ISRs in their own files, to make sure they don't get built into apps that don't use them. If you're interested, look me up in our gitter channel, and I can guide you on how to proceed. |
yep, I got that on tone.c - I didn't know how much optimization there was down stream (till I compiled an saw that it didn't make a difference).. But removing it wasn't going to be a problem either way.. Back to your idea - I see what you mean with the ISR into separate files, as I assume (like tone) they will be optimized out of the final build by the linker if they haven't been referenced. Why doesn't the official build do this ie have a sub director 'isr' and put them all in there? |
Although all is well for me at the moment with vtables in heap or flash as per @earlephilhower 's pr, commit 170911a still has me worried, since it was the commit that triggered the iram exhaustion for my app and it really appears to be including gdb bits that were never included before. Prior to this commit you had to explicitly #include <GDBStub.h> file, now its included in postmortem. On the other hand, It could be that it tipped iram usage by a few bytes and I was right on the line, so if it wasn't that commit, it would have been some other that would have become the trigger. Update: 108 byte increase. Nothing crazy, but enough to exceed my allowance of iram. I admit though, in this repo, the new commits that excite me the most are the ones that say "saved xxx bytes heap/ram by doing xyz". I drop whatever I'm doing at that moment to get my handout of free bytes :) |
Could someone post a for-dummys on how to build using the version on Git head? The instructions here seem to be out of date. Thanks! |
It works for me. I made a shell script for my convenience:
|
@dalbert2 These instructions are up to date and working. |
Datapoints: an empty sketch built with So at first glance, it looks like core/sdk IRAM didn't change IRAM usage much between versions. However, even when I reworked my application to reduce IRAM usage, when I build with: So it appears that something causes at least 925 bytes more IRAM usage with 2.4.1 but not when using 2.4.0 |
@d-a-v I will open another ticket and will provide relevant details (including the partial fix which came from #4464). I posted it here because until a fix for this issue is folded into a release, anyone struggling with the out-of-IRAM problem may want to pull from git head. The partial fix for building from git is to install Python 3.x (not 2.7x as per the instructions or it will fail during the get.py step (at least on Windows and Mac platforms). The step that is needed for dummies (i.e. me) that's not included in the instructions is how to get the downloaded 2.5.0-dev package to show up in the boards manager. I'll update this post when I figure that out. |
vtable location selector is in menu in core-2.4.2. |
Confirmed, 2.4.2 fixes the issue. |
Basic Infos
Platform
Settings in IDE
Problem Description
Section full when building with 2.4.1 (works fine with 2.4.0)
Detailed problem description goes here.
Codebase that builds perfectly under 2.4.0 will not build with 2.4.1
Building 1.0.22 release using 2.4.0 core for WifInfo (ESP12 4M/1M):
Building 1.0.22 release using 2.4.1 core for WifInfo (ESP12 4M/1M):
Building 1.0.22 release using 2.4.1 core for Generic ESP8266 module using Arduino IDE
MCVE Sketch
It's a big proprietary codebase, I'm sorry, I can't post it.
Debug Messages
The text was updated successfully, but these errors were encountered: