-
Notifications
You must be signed in to change notification settings - Fork 13.3k
WifiClient.connect() crashes when connect fails and in the mean time an io interrupt occured. #2181
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
Comments
ISR handlers have to be marked with ICACHE_RAM_ATTR. |
In my case they are ! As far as i can see it crashes before either _s_connected or _s_error is called. (Interrupts re-enabled or leaving nmi ??) |
Same goes for any functions you may be calling from ISR, make sure those are in RAM as well. You can check where it crashes — do objdump of the output ELF file and look for |
I used the stack dump decoding tool..... |
Could you please upload the elf file from that sketch somewhere and share a link to it? |
Hmmmm.... You are right @iggr, I should have noticed that... |
@igrr All files can be found here. The problem is a bit different as it seemed. The address should be digitalRead, as it is a inline inline call to digitalRead, Check the code-snippets: It actually is an inline calling an inline and the first inline (cIoPin::input()) compiles really inline, but the second inline (cIoPin::getInput()) compiles as a function in flash... And if we take a good look at the stackdump we can see another problem:
|
You are reading too much into this "trace". Recursive interrupt calls are not possible in this case, what happens is that you happen to have return address of Now back to the real issue. Compiler is not obliged to inline a member function marked as |
Sorry iggr, but that 'junk' in memory is below the current stackpointer and does not show in the stackdump ! What you see in the stackdump is what is currently pending. (return addresses and local function data). So, since the return address of the handler->fn() call in wiring_digital interrupt_handler (40106f44) is twice on stack, and I even recognise my interruptHandlers local data, recursive interrupt calls are happening in this case. Also i don't agree on that a compiler may ignore inline, unless you tell it explicitly to ignore or optimize inlining and in the last case it should only change inline code to functions if 1: the inline code is substantial and 2: it is called multiple times. Both are not the case here.... Anyway I will try Thanks for your advice, |
But still I wonder why it should not be possible to call a flash function from an interrupt... For the same reason the use of noInterrupts(), interrupts() should be forbidden (and should, in my opinion, be removed from the library or changed to Sure worth to look into these matters...... |
Regarding gcc behaviour w.r.t. inlining, i think you might be better of discussing this with someone who actually knows a thing or two about gcc. I'm not a gcc developer so I can not comment on optimization decisions which gcc does. This project simply uses a toolchain which is available. You probably didn't understand my comment regarding junk on the stack frames. Let me try to explain again. Stack frames are not "dense", i.e. when the compiler allocates 8 words for a stack frame it doesn't mean that each and every word will have a value written into it. Some words may stay unused, and will have whatever values they had previously, essentially being "junk" values. This is even more obvious with interrupt handlers, which always have extra 0x100 bytes of unused stack space allocated in prologue. Consider a program which has three functions,
If you were to dump the stack in case 2, and then decode every instruction-address-like value into code line, you would see PC of ISR appearing twice on the "stack trace". Of course, such list of decoded instruction-address-like values is not a stack trace. To get a real stack trace, you need to use GDB. Next thing, on the flash caching. Execution of code from flash happens via a bit of hardware which can be enabled or disabled. There are no software routines involved (what you describe as "copy from flash to RAM"). Different parts of WiFi stack can disable flash caching for short periods of time, because of "Reasons" (TM). If the ISR happens at this time, there is no way to execute code from flash because the cache is disabled. If you really want your handler to be in flash, you can write a wrapper around your ISR handler to check if cache is enabled and bail out if it isn't, setting a flag somewhere to run the handler later. |
Thanks for the explanation. I know a lot, but I don't know that much about esp8266 and gcc internals. |
On GCC end, the usual set of online docs for gcc project. I'm closing the issue since the ISR problem is resolved for you. |
Basic Infos
Hardware
Hardware: ESP-12
Core Version: 2.2.0
Description
Problem description
1: An io interrupt handler is attached to an io pin, (in my case RcSwitch, but any io interrupt on any pin causes the same problem)
2: Trying to connect a WiFiClient to a non existing server (server is unreachable/off-line)
Problem:
If during the connect attemp any io interrupt(s) occur the esp crashes at the moment the connect attempt times-out.
epc1=0x40216b74 ==> Is digitalRead (called from io interrupt).
(I did not yet check if any other interrupts, like a timer, causes the same problem, but what i noticed is that it always crashes on a digitalRead called from the interrupt.)
And also when the connect is succesfull it doesn't crash (but in this case the time interval is much shorter and so the change of having an interrupt during the connect is also smaller..., but even with a remote pressed during successful connecting, interrupting almost ten thousand times a second, I couldn't get it to crash... )
When during the connect attempt IO interrupts are disabled it won't crash...
The text was updated successfully, but these errors were encountered: