In the process of creating the reproducer test code I figured out what is causing the panic (that's how it usually goes, right?). I'm not sure if it is really a bug as much as a change in behavior, but the crux of it is this:
If you enable a UART pattern detect interrupt on some UART port, AND also intend to later delete the UART driver on that UART port, then you MUST disable the pattern detect interrupt before deleting the UART driver, otherwise you'll get a panic when entering deep sleep.
The issue doesn't happen if you don't delete the UART driver.
Here's the reproducer code for the issue. If you run the code as-is then you won't see a crash, because the code calls
to disable the pattern detect interrupt before it calls
This is basically what my larger codebase was doing - using the UART driver and pattern detect interrupt to check it a sensor was connected and transmitting, before deleting the UART driver to turn things over to the ULP program. But I've not been disabling the pattern detect interrupt...
Code: Select all
#include <stdio.h>
#include "esp_log.h"
#include "esp_sleep.h"
#include "driver/uart.h"
#include "esp_check.h"
#define UART_RXBUF_SIZE (UART_HW_FIFO_LEN(UART_PORT_NUM) * 2)
#define UART_DET_QUEUE_SIZE 2
#define UART_RX_PIN 26
#define UART_TX_PIN 25
const static char *TAG = "example";
void app_main(void)
{
ESP_LOGI(TAG, "Example starting");
// configure and load UART1 driver
QueueHandle_t uartQueue;
uart_config_t uartConfig = {
.baud_rate = 9600,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_APB,
};
ESP_ERROR_CHECK(uart_param_config(UART_NUM_1, &uartConfig));
ESP_ERROR_CHECK(uart_set_pin(UART_NUM_1, UART_TX_PIN, UART_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
ESP_ERROR_CHECK(uart_driver_install(UART_NUM_1, UART_RXBUF_SIZE, 0, UART_DET_QUEUE_SIZE, &uartQueue, 0));
// enable UART1 pattern detect interrupt
ESP_ERROR_CHECK(uart_enable_pattern_det_baud_intr(UART_NUM_1, '\r', 1, 9, 0, 0));
ESP_ERROR_CHECK(uart_pattern_queue_reset(UART_NUM_1, UART_DET_QUEUE_SIZE));
ESP_LOGI(TAG, "Loaded UART1 driver");
// when done with UART1 it is necessary to disable this interrupt,
// otherwise you'll get a panic when attempting to enter deep sleep
ESP_ERROR_CHECK(uart_disable_pattern_det_intr(UART_NUM_1));
// delete the UART1 driver
ESP_ERROR_CHECK(uart_driver_delete(UART_NUM_1));
ESP_LOGI(TAG, "Deleted UART1 driver");
// configure and enter deep sleep
esp_sleep_enable_timer_wakeup(10 * 1000 * 1000);
ESP_LOGI(TAG, "Starting deep sleep for 10s");
esp_deep_sleep_start();
}
If you comment out the
Code: Select all
ESP_ERROR_CHECK(uart_disable_pattern_det_intr(UART_NUM_1))
line in the above code and run it then you'll see it crash with the same panic I described in my initial post:
Code: Select all
I (307) spi_flash: detected chip: generic
I (310) spi_flash: flash io: dio
I (314) main_task: Started on CPU0
I (324) main_task: Calling app_main()
I (324) example: Example starting
I (324) uart: queue free spaces: 2
I (324) example: Loaded UART1 driver
I (334) example: Deleted UART1 driver
I (334) example: Starting deep sleep for 10s
Guru Meditation Error: Core 0 panic'ed (Interrupt wdt timeout on CPU0).
Core 0 register dump:
PC : 0x40081e0a PS : 0x00060e34 A0 : 0x800848aa A1 : 0x3ffb4d90
0x40081e0a: esp_rom_uart_tx_wait_idle at /Users/chris/esp/esp-idf/components/esp_rom/patches/esp_rom_uart.c:22 (discriminator 1)
A2 : 0x00000001 A3 : 0x00000000 A4 : 0x000028f6 A5 : 0x00003380
A6 : 0x00000000 A7 : 0x50001fe8 A8 : 0x00000000 A9 : 0x3ffb4db0
A10 : 0x3ffb0050 A11 : 0x00000000 A12 : 0x00000000 A13 : 0x00000000
A14 : 0x3f40331b A15 : 0x000003e8 SAR : 0x00000009 EXCCAUSE: 0x00000005
EXCVADDR: 0x00000000 LBEG : 0x400014fd LEND : 0x4000150d LCOUNT : 0xfffffffd
0x400014fd: strlen in ROM
0x4000150d: strlen in ROM
Backtrace: 0x40081e07:0x3ffb4d90 0x400848a7:0x3ffb4dc0 0x40084957:0x3ffb4de0 0x40084c06:0x3ffb4e30 0x40084c45:0x3ffb4e50 0x400d5817:0x3ffb4e70 0x400e5ec4:0x3ffb4eb0 0x40087ff9:0x3ffb4ee0
0x40081e07: uart_ll_is_tx_idle at /Users/chris/esp/esp-idf/components/hal/esp32/include/hal/uart_ll.h:864 (discriminator 4)
(inlined by) esp_rom_uart_tx_wait_idle at /Users/chris/esp/esp-idf/components/esp_rom/patches/esp_rom_uart.c:22 (discriminator 4)
0x400848a7: flush_uarts at /Users/chris/esp/esp-idf/components/esp_hw_support/sleep_modes.c:440
0x40084957: esp_sleep_start at /Users/chris/esp/esp-idf/components/esp_hw_support/sleep_modes.c:652
0x40084c06: deep_sleep_start at /Users/chris/esp/esp-idf/components/esp_hw_support/sleep_modes.c:982
0x40084c45: esp_deep_sleep_start at /Users/chris/esp/esp-idf/components/esp_hw_support/sleep_modes.c:1005
0x400d5817: app_main at /Users/chris/esp/sleep-panic-example/main/main.c:48
0x400e5ec4: main_task at /Users/chris/esp/esp-idf/components/freertos/app_startup.c:208
0x40087ff9: vPortTaskWrapper at /Users/chris/esp/esp-idf/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c:134
Hopefully this helps someone in the future!