Esp32:即使相同的命令在其他地方工作,双核任务也会崩溃

Posted

技术标签:

【中文标题】Esp32:即使相同的命令在其他地方工作,双核任务也会崩溃【英文标题】:Esp32: Dual Core task crashing even though same command works elsewhere 【发布时间】:2021-09-07 08:50:25 【问题描述】:

我在这方面已经超出了我的能力范围。

这个项目是为了给一些学生做一个物联网演示。使用 Telegram,他们可以控制一些照明以及接收一些事件通知。

以下已确认有效:

所有照明和照明电报消息

温度传感器和电报消息

门铃,但不是电报消息

如果将bot.sendMessage(chat_id, "Someone is at the door.", ""); 添加到soundDoorbell() 函数中,则会发生以下崩溃

CORRUPT HEAP: Bad head at 0x3fff479c. Expected 0xabba1234 got
0x3ffffff8 abort() was called at PC 0x40086cd1 on core 0

ELF file SHA256: 0000000000000000

Backtrace: 0x40088904:0x3ffdc5d0 0x40088b81:0x3ffdc5f0
0x40086cd1:0x3ffdc610 0x40086dfd:0x3ffdc640 0x400f6bcf:0x3ffdc660
0x400f2ebd:0x3ffdc920 0x400f2e4c:0x3ffdc970 0x4008d25d:0x3ffdc9a0
0x40081f1e:0x3ffdc9c0 0x4008208d:0x3ffdc9e0 0x40123ca6:0x3ffdca00
0x4011706a:0x3ffdca20 0x400d3a28:0x3ffdca40 0x400d3629:0x3ffdca60
0x400d37fb:0x3ffdca80 0x400d38f1:0x3ffdcab0 0x400d464d:0x3ffdcad0
0x400d707d:0x3ffdcb00 0x400d15cd:0x3ffdcba0 0x400d16a3:0x3ffdcbc0
0x40089b92:0x3ffdcc00

Rebooting... ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT) configsip: 0,
SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1 load:0x3fff0018,len:4 load:0x3fff001c,len:1044
load:0x40078000,len:10124 load:0x40080400,len:5856 entry 0x400806a8

解码堆栈显示:

0x40088904: invoke_abort at
/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c
line 156 0x40088b81: abort at
/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c
line 171 0x40086cd1: lock_acquire_generic at
/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/newlib/locks.c
line 143 0x40086dfd: _lock_acquire_recursive at
/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/newlib/locks.c
line 171 0x400f6bcf: _vfiprintf_r at
../../../.././newlib/libc/stdio/vfprintf.c line 860 0x400f2ebd:
fiprintf at ../../../.././newlib/libc/stdio/fiprintf.c line 50
0x400f2e4c: __assert_func at ../../../.././newlib/libc/stdlib/assert.c
line 59 0x4008d25d: multi_heap_free at
/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/multi_heap_poisoning.c
line 218 0x40081f1e: heap_caps_free at
/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/heap_caps.c line 268 0x4008208d: esp_mbedtls_mem_free at
/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/mbedtls/port/esp_mem.c
line 35 0x40123ca6: mbedtls_free at
/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/mbedtls/mbedtls/library/platform.c
line 98 0x4011706a: mbedtls_ssl_free at
/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/mbedtls/mbedtls/library/ssl_tls.c
line 8992 0x400d3a28: stop_ssl_socket(sslclient_context*, char const*,
char const*, char const*) at
C:\Users\abas034\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\libraries\WiFiClientSecure\src\ssl_client.cpp
line 272 0x400d3629: WiFiClientSecure::stop() at
C:\Users\abas034\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\libraries\WiFiClientSecure\src\WiFiClientSecure.cpp
line 93 0x400d37fb: WiFiClientSecure::connect(char const*, unsigned
short, char const*, char const*, char const*) at
C:\Users\abas034\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\libraries\WiFiClientSecure\src\WiFiClientSecure.cpp
line 154 0x400d38f1: WiFiClientSecure::connect(char const*, unsigned
short) at
C:\Users\abas034\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\libraries\WiFiClientSecure\src\WiFiClientSecure.cpp
line 112 0x400d464d: UniversalTelegramBot::sendGetToTelegram(String
const&) at C:\Users\abas034\UOA\OneDrive - The University of
Auckland\Documents\Arduino\libraries\UniversalTelegramBot\src\UniversalTelegramBot.cpp
line 73 0x400d707d: UniversalTelegramBot::getUpdates(long) at
C:\Users\ab\UOA\OneDrive - The University of
Auckland\Documents\Arduino\libraries\UniversalTelegramBot\src\UniversalTelegramBot.cpp
line 369 0x400d15cd: checkTelegramBot() at
C:\Users\ab\OneDrive\Documents\Projects\WorkingOn\IoT-Demo\HomeAutomationV3/HomeAutomationV3.ino
line 315 0x400d16a3: nonloopingCode(void*) at
C:\Users\ab\OneDrive\Documents\Projects\WorkingOn\IoT-Demo\HomeAutomationV3/HomeAutomationV3.ino
line 343 0x40089b92: vPortTaskWrapper at
/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c
line 143

鉴于“bot.sendMessage”函数在其他任何地方都有效,我无法弄清楚为什么它会在这种情况下失败。

代码

#包括 #包括 #包括 #ifdef ESP32 #包括 #别的 #包括 #万一 #包括 #包括 #包括 #include "DHTesp.h" //Wifi 和 Telgram 凭据 #include "config.h" // 传感器和控制 #define pin_DHT11 4 // #define pin_alarmsensor 2 //RCWL-0516 #define pin_siren 19 #define pin_led_veranda 26 #define pin_led_bedroom 25 #define pin_doorbell 27 DHTESP dht; #define DATA_PIN 18 #define LED_TYPE WS2812 #define COLOR_ORDER GRB #define NUM_LEDS 12 CRGB LED[NUM_LEDS]; #定义亮度 50 #define FRAMES_PER_SECOND 120 布尔警报武装=假; 布尔警报触发=假; 布尔党派森=假; bool livingroomledson = false; int 按钮状态; int lastButtonState = 低; 无符号 long lastDebounceTime = 0; unsigned long debounceDelay = 50; WiFiClient安全客户端; UniversalTelegramBot bot(BOTtoken,客户端); int botRequestDelay = 50; 无符号 long lastTimeBotRan; 字符文本选项; 字符串 chat_id; TaskHandle_t 循环任务; TaskHandle_t 非循环任务; void GetTemperature() //已实现 字符串消息=“温度:”; TempAndHumidity newValues = dht.getTempAndHumidity(); message.concat(String(newValues.temperature)); message.concat("."); bot.sendMessage(chat_id, message, ""); 无效切换警报() 警报武装 = !警报武装; 如果(报警) bot.sendMessage(chat_id, "报警。", ""); else bot.sendMessage(chat_id, "警报解除。", ""); 无效切换派对灯() 派对莱森 = !派对莱森; 如果(派对) livingroomledson = 假; bot.sendMessage(chat_id, "派对灯打开了。", ""); else bot.sendMessage(chat_id, "派对灯已关闭。", ""); 无效 ToggleVerandaLights() bool LightStatus = digitalRead(pin_led_veranda); LightStatus = !LightStatus; digitalWrite(pin_led_veranda,LightStatus); LightStatus = digitalRead(pin_led_veranda); 如果(光状态) bot.sendMessage(chat_id, "阳台灯已打开。", ""); else bot.sendMessage(chat_id, "阳台灯已关闭。", ""); 无效 ToggleLivingRoomLights() 派对莱森 = 假; bool LightStatus = livingroomledson; livingroomledson = !livingroomledson; 如果(客厅莱森) for (int i = 0; i (leds, NUM_LEDS).setCorrection(TypicalLEDStrip); FastLED.setBrightness(亮度); FastLED.clear(); FastLED.show(); Serial.println("开始"); pinMode(pin_siren,输出); pinMode(pin_led_veranda,输出); pinMode(pin_led_bedroom,输出); pinMode(pin_alarmsensor,输入); pinMode(pin_doorbell,INPUT_PULLUP); // 连接到 Wi-Fi WiFi.mode(WIFI_STA); WiFi.begin(ssid, 密码); client.setCACert(TELEGRAM_CERTIFICATE_ROOT); 而(WiFi.status()!= WL_CONNECTED) 延迟(1000); Serial.println("正在连接 WiFi.."); // 打印 ESP32 本地 IP 地址 Serial.println(WiFi.localIP()); Serial.println("机器人启动了?"); bot.sendMessage(CHAT_ID, "系统重启", ""); //创建一个将在Task1code()函数中执行的任务,优先级为1,在核心0上执行 xTaskCreatePinnedToCore( nonloopingCode, /* 任务函数。 */ "nonloopingTasks", /* 任务名称。 */ 16384, /* 任务栈大小 */ NULL, /* 任务参数 */ 1, /* 任务的优先级 */ &nonloopingTasks, /* 跟踪创建任务的任务句柄 */ 0); /* 将任务固定到核心 0 */ 延迟(500); xTaskCreatePinnedToCore( juggle, /* 任务函数。 */ "loopingTasks", /* 任务名称。 */ 16384, /* 任务栈大小 */ NULL, /* 任务参数 */ 1, /* 任务的优先级 */ &loopingTasks, /* 跟踪创建任务的任务句柄 */ 1); /* 将任务固定到核心 1 */ 延迟(500); 无效 checkTelegramBot() if (millis() > lastTimeBotRan + botRequestDelay) int numNewMessages = bot.getUpdates(bot.last_message_received + 1); 而(numNewMessages) Serial.println("得到响应"); 处理新消息(numNewMessages); numNewMessages = bot.getUpdates(bot.last_message_received + 1); lastTimeBotRan = 毫秒(); 无效非循环代码(无效* pvParamters) Serial.print("nonloopingCode running on core"); Serial.println(xPortGetCoreID()); 为了 (;;) 如果 ((!partyledson) && (!livingroomledson)) FastLED.clear(); FastLED.show(); 如果(报警) 如果(数字读取(pin_alarmsensor)) bot.sendMessage(chat_id, "警报触发", ""); 派对莱森 = 假; 警报触发 = 真; checkTelegramBot(); 无效杂耍(无效* pvParamters) Serial.print("Juggle 在核心上运行"); Serial.println(xPortGetCoreID()); 为了 (;;) 检查门铃(); if (alarmTriggered)soundAlarm(); 如果(派对) fadeToBlackBy(leds, NUM_LEDS, 20); 字节 dothue = 0; 诠释 i = 0; 而((我去抖延迟) 如果(阅读!= buttonState) 按钮状态 = 阅读; 如果(按钮状态 == 低) 声音门铃(); lastButtonState = 阅读; 无效循环()

【问题讨论】:

【参考方案1】:

我不认为 Telegram 例程是线程安全的。

使用 FreeRTOS 互斥锁 (https://microcontrollerslab.com/arduino-freertos-mutex-tutorial-priority-inversion-priority-inheritance/),我设法让它工作,虽然有很多滞后,但这是一个更容易解决的问题 :)

【讨论】:

以上是关于Esp32:即使相同的命令在其他地方工作,双核任务也会崩溃的主要内容,如果未能解决你的问题,请参考以下文章

esp32确定是不是是中断任务

ESP32 Arduino双核编程示例

即使相同的命令在其他地方工作,也尝试分配给只读属性?

ESP-总体理解(arduino-esp32)

esp32启动了但不运行程序

esp32低功耗远程唤醒