SPI semaphore trips wdt when light sleep enabled
Posted: Sat Nov 04, 2023 9:44 pm
I have an application that interacts with a radio transceiver using the SPI bus. Typically, when the radio receives a message, it raises a status line which is configured as an interrupt source on the ESP32. The ESP32 ISR then reads data from the radio.
The code makes use of the functions:
These are the only functions that call SPI.beginTransaction() and SPI.endTransaction(). This works well until the main loop enables light sleep (which is configured to wake on interrupt):
When light sleep is enabled, I frequently get an exception:
The watchdog is in SPI.cpp:179 which is:
When light sleep is disabled, this never happens.
It's not clear to me how the deadlock could be taking place, but I'm obviously doing something wrong and any suggestions would be appreciated!
The code makes use of the functions:
Code: Select all
uint8_t IRAM_ATTR xcvr_read(uint8_t reg) {
uint8_t value;
SPI.beginTransaction(SPISettings(SPI_RATE, SPI_MSBFIRST, SPI_MODE0));
digitalWrite(NSS, 0);
SPI.transfer(reg);
value = SPI.transfer(0);
digitalWrite(NSS, 1);
SPI.endTransaction();
return value;
}
void IRAM_ATTR xcvr_write(uint8_t reg, uint8_t value) {
SPI.beginTransaction(SPISettings(SPI_RATE, SPI_MSBFIRST, SPI_MODE0));
digitalWrite(NSS, 0);
SPI.transfer(0x80 | reg); // set write bit
SPI.transfer(value);
digitalWrite(NSS, 1);
SPI.endTransaction();
}
Code: Select all
esp_sleep_enable_ext1_wakeup((1ULL<<GPIO_NUM_25) | // radio packet preamble
(1ULL<<GPIO_NUM_26) | // radio packet received
(1ULL<<GPIO_NUM_34), // power coprocessor
ESP_EXT1_WAKEUP_ANY_HIGH);
// Enter low power sleep mode
esp_light_sleep_start();
// restore normal operation of GPIOs used for external wakeup
rtc_gpio_deinit(GPIO_NUM_25);
rtc_gpio_deinit(GPIO_NUM_26);
rtc_gpio_deinit(GPIO_NUM_34);
Code: Select all
Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1).
Core 1 register dump:
PC : 0x40092577 PS : 0x00060835 A0 : 0x80091be7 A1 : 0x3ffbfc0c
A2 : 0x3ffbfde8 A3 : 0xb33fffff A4 : 0x0000cdcd A5 : 0x00060823
A6 : 0x00060823 A7 : 0x0000abab A8 : 0x0000cdcd A9 : 0xffffffff
A10 : 0x00000015 A11 : 0x3ffc50a8 A12 : 0x80008000 A13 : 0x3ffcd0e0
A14 : 0x007bfde8 A15 : 0x003fffff SAR : 0x0000001b EXCCAUSE: 0x00000006
EXCVADDR: 0x00000000 LBEG : 0x40085bbd LEND : 0x40085bc5 LCOUNT : 0x00000027
Core 1 was running in ISR context:
EPC1 : 0x400f35a7 EPC2 : 0x00000000 EPC3 : 0x00000000 EPC4 : 0x00000000
...
#0 0x400923df:0x3ffbb5e0 in vListInsert at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/freertos/list.c:183
#1 0x4009105b:0x3ffbb600 in vTaskPlaceOnEventList at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/freertos/tasks.c:3566
#2 0x400903e6:0x3ffbb620 in xQueueSemaphoreTake at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/freertos/queue.c:1679
#3 0x400de7e4:0x3ffbb660 in SPIClass::beginTransaction(SPISettings) at C:/Users/david/.platformio/packages/framework-arduinoespressif32/libraries/SPI/src/SPI.cpp:179
Code: Select all
SPI_PARAM_LOCK();
which is:
#define SPI_PARAM_LOCK() do {} while (xSemaphoreTake(paramLock, portMAX_DELAY) != pdPASS)
It's not clear to me how the deadlock could be taking place, but I'm obviously doing something wrong and any suggestions would be appreciated!