ESP32:在 FreeRTOS 中处理 NVS 闪存擦除(lock_acquire_generic。)

问题描述 投票:0回答:1

我正在尝试擦除 GPIO ISR 上的 nvs。我写了下面的代码。 仅向 DI 发出高信号时,中断发生了很多次,因此我在中断中添加了 3 秒延迟。

static void IRAM_ATTR gpio_isr_handler(void *arg)
{
    uint32_t current_time = xTaskGetTickCountFromISR();
    // Debounce: Only process if enough time has passed since the last interrupt
    if ((current_time - last_interrupt_time) > (3000 / portTICK_PERIOD_MS))
    {
        // button_state = true;
        esp_err_t err = nvs_flash_erase();
    
        if (err == ESP_OK) {
            ESP_LOGI("NVS", "NVS flash erased successfully.");
        } else {
            ESP_LOGE("NVS", "Failed to erase NVS flash: %s", esp_err_to_name(err));
        }
        last_interrupt_time = current_time;
    }
}

上面的代码出现以下错误。我该如何解决这个错误。 我检查了堆损坏也没有发生堆损坏。


abort() was called at PC 0x40082edf on core 0
--- 0x40082edf: lock_acquire_generic at C:/Users/Admin/.espressif/frameworks/esp-idf-v5.3/components/newlib/locks.c:133



Backtrace: 0x40081e0a:0x3ffb1b20 0x4008aa05:0x3ffb1b40 0x40092f55:0x3ffb1b60 0x40082edf:0x3ffb1bd0 0x4008301d:0x3ffb1c00 0x400830aa:0x3ffb1c20 0x4017e74e:0x3ffb1c50 0x40171c09:0x3ffb1f70 0x4018e435:0x3ffb1fa0 0x400918b9:0x3ffb1fd0 0x400831a9:0x3ffb2020 0x40083799:0x3ffb2040 0x4008386b:0x3ffb2070 0x40083545:0x3ffb20a0 0x40089723:0x3ffbbe70 0x400d47c3:0x3ffbbe90 0x4008c5d5:0x3ffbbeb0 0x4008b511:0x3ffbbed0
--- 0x40081e0a: panic_abort at C:/Users/Admin/.espressif/frameworks/esp-idf-v5.3/components/esp_system/panic.c:463
0x4008aa05: esp_system_abort at C:/Users/Admin/.espressif/frameworks/esp-idf-v5.3/components/esp_system/port/esp_system_chip.c:92
0x40092f55: abort at C:/Users/Admin/.espressif/frameworks/esp-idf-v5.3/components/newlib/abort.c:38
0x40082edf: lock_acquire_generic at C:/Users/Admin/.espressif/frameworks/esp-idf-v5.3/components/newlib/locks.c:133
0x4008301d: _lock_acquire_recursive at C:/Users/Admin/.espressif/frameworks/esp-idf-v5.3/components/newlib/locks.c:162
0x400830aa: __retarget_lock_acquire_recursive at C:/Users/Admin/.espressif/frameworks/esp-idf-v5.3/components/newlib/locks.c:321
0x4017e74e: _vfprintf_r at /builds/idf/crosstool-NG/.build/HOST-x86_64-w64-mingw32/xtensa-esp-elf/src/newlib/newlib/libc/stdio/vfprintf.c:846 (discriminator 2)
0x40171c09: vprintf at /builds/idf/crosstool-NG/.build/HOST-x86_64-w64-mingw32/xtensa-esp-elf/src/newlib/newlib/libc/stdio/vprintf.c:34
0x4018e435: esp_log_writev at C:/Users/Admin/.espressif/frameworks/esp-idf-v5.3/components/log/log.c:210
0x400918b9: esp_log_write at C:/Users/Admin/.espressif/frameworks/esp-idf-v5.3/components/log/log.c:220
0x400831a9: gpio_isr_handler at C:/Users/Admin/Desktop/gateway/main/wifi.c:168 (discriminator 1)
0x40083799: gpio_isr_loop at C:/Users/Admin/.espressif/frameworks/esp-idf-v5.3/components/esp_driver_gpio/src/gpio.c:4660x4008386b: gpio_intr_service at C:/Users/Admin/.espressif/frameworks/esp-idf-v5.3/components/esp_driver_gpio/src/gpio.c:496
0x40083545: _xt_lowint1 at C:/Users/Admin/.espressif/frameworks/esp-idf-v5.3/components/xtensa/xtensa_vectors.S:1240
0x40089723: xt_utils_wait_for_intr at C:/Users/Admin/.espressif/frameworks/esp-idf-v5.3/components/xtensa/include/xt_utils.h:82
 (inlined by) esp_cpu_wait_for_intr at C:/Users/Admin/.espressif/frameworks/esp-idf-v5.3/components/esp_hw_support/cpu.c:55
0x400d47c3: esp_vApplicationIdleHook at C:/Users/Admin/.espressif/frameworks/esp-idf-v5.3/components/esp_system/freertos_hooks.c:58
0x4008c5d5: prvIdleTask at C:/Users/Admin/.espressif/frameworks/esp-idf-v5.3/components/freertos/FreeRTOS-Kernel/tasks.c:4344 (discriminator 1)
0x4008b511: vPortTaskWrapper at C:/Users/Admin/.espressif/frameworks/esp-idf-v5.3/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c:134





ELF file SHA256: 1a4a2a846

Rebooting...
I (13) boot: ESP-IDF v5.3-dirty 2nd stage bootloader
I (13) boot: compile time Dec  5 2024 15:23:00
I (13) boot: Multicore bootloader
interrupt esp32 esp-idf
1个回答
0
投票

中断处理程序在非常脆弱的上下文中运行,并且许多操作在那里是不允许的。

简短回答:

根据 Espressif 的文档 中断处理程序内部的日志记录不应使用标准日志记录宏。

使用

ESP_DRAM_LOGI
和家人来代替。

长答案:

令我感到非常惊讶的是,闪存擦除在 ISR 内部起作用,而日志记录功能却失败了。我个人不会做这样的实验:)

如果ISR只做尽可能少的事情并将所有实际工作留给任务,那么ISR的工作效果会最好。它们当然不适合可能阻塞未知时间且不实时关键的操作。

您可以编写代码,以便常规任务在任务信号工具(如事件组)后面等待阻塞。 ISR 仅发布一个事件,该事件释放任务以完成其工作。

© www.soinside.com 2019 - 2024. All rights reserved.