I don’t know what can interrupt user code on the ESP8266 or what might do the interrupting, the documentation is lacking in that area, but something seems to be causing me a timing condition. With a really low time out on an NTP call I seemed to end up in the receive and the timeout code at the same time. The timeout kills the connection and the receive disarms the timeout, so in theory only one should ever be run, but what happens if the timeout occurs between the receive code being called and it actually disarming the timeout? Will the timeout interrupt the receive, kill the connection and then allow the receive code to continue? That is what it looked like, so I did the obvious thing and searched the API for some kind of mutex. No joy, but the whole API isn’t documented so I grepped the SDK libraries for any function name that might be relevant, still no joy. I’ve come to the conclusion the SDK does not provide any such functionality, so I had to get my hands dirty with some assembler…
Armed with a copy of the ‘Tensilica Xtensa Instruction Set Architecture‘ reference manual I tested out the S32C1I operation. The GCC compiler doesn’t know this instruction or the special register it uses (SCOMPARE1), so I wrote something similar and patched the right opcodes into the assembled object file. Unfortunately trying to write to this register reset the device, so it looks like the ESP8266 does not support the ‘Conditional Store Option’, darn.
So, I’m not sure how I ended up at it but I found some Linux kernel code with what appears to offer the solution and forms the basis of my esp8266 mutex code. The code is easy enough to use – declare a mutex_t, call CreateMutux against it, then GetMutex and ReleaseMutex as required.
Code now on GitHub: https://github.com/raburton/esp8266
2 thoughts on “Mutex for ESP8266”
Hi Richard, love your work. I am doing a bunch of stuff with the micropython project on the ESP and used your mutex for synchronising the interrupt handler and user time reading or the DHT22.
Now, some time later I come back to have a look at your DS3231 i2c code (because mine is not working).
(I have also had to deal with the word boundary issue of the flash. How I solved it is I make a word array with a python app of strings and use a little decoder in C. Apparently we are getting pre-compiled bytecode streams in micropython soon so I’ll be sure storing that in the SPI connected flash).
Funny thing is I have 100 lines of python but have written 1000 of C to support it on the ESP. I’m not sure if that qualifies me as a real man or not.
Richard, does your observation on receive and timeouts looks anything like my struggle ( see below ) ? Using actually already your mutex code, thanks for that. Because from the ESP8266 doc it’s not clear what code can be interrupted by other : software & hardware timers, tasks and all sorts of callbacks. The way the SDK works feels like “callback hell”.
When developing the embedded software on ESP8266, I regularly come into situations where the system stalls and the watchdog kicks in to reset the system.
I get error message : “mac 674” and the system freezes.
Is there a list of all possible error messages coming from this layer ? The “mac nnn” list.
The code is in a : “while(1) ;” loop. at lmacProcessTxSuccess +0x39
See disassembly :
40101904: a2a242 movi a4, 0x2a2
40101907: fa1e01 l32r a0, 40100180
4010190a: 0000c0 callx0 a0
4010190d: ffff06 j 4010190d —> loop on this instruction.
The stack shows :
3FFFFD70:4010190D CODE lmacProcessTxSuccess +0x39
3FFFFD80:4010190D CODE lmacProcessTxSuccess +0x39
3FFFFDD0:40221E90 CODE ip_output +0x30
3FFFFDF0:40002514 CODE ets_printf +0x48
3FFFFE70:4010431C CODE wDev_ProcessFiq +0x2F0
3FFFFE90:4000050C CODE _xtos_set_exception_handler +0xB8
3FFFFEB0:40000F68 CODE ets_post +0x144
3FFFFEC0:40000F58 CODE ets_post +0x134
3FFFFF80:40102986 CODE ppProcessTxQ +0x66
3FFFFF90:402116B6 CODE ppPeocessRxPktHdr +0x14A
3FFFFFB0:40000E19 CODE ets_run +0x15
3FFFFFC0:40001100 CODE ets_isr_unmask +0x158
3FFFFFD0:40100276 CODE call_user_start_local +0xE
3FFFFFE0:4010000D CODE call_user_start +0x9
3FFFFFF0:4000044C CODE UartDev +0x263C