ESP32 偶尔与多个 I2C 设备崩溃,堆问题?

Posted

技术标签:

【中文标题】ESP32 偶尔与多个 I2C 设备崩溃,堆问题?【英文标题】:ESP32 sporadically crashing with multiple I2C devices, heap issue? 【发布时间】:2021-09-06 09:56:34 【问题描述】:

我有一个 ESP32(M5Stack Core Grey),它通过 I2C 连接到 PMIC(带有 I2C 寄存器的自定义 IP5306)和加速度计 (MPU9250)。两个库大部分时间同时独立工作。有时,我会遇到 2 个错误之一,我怀疑这是我的代码尝试调用这两个设备时的某种冲突:

assertion "head != NULL" failed: file "/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/multi_heap_poisoning.c", line 245, function: multi_heap_realloc
Decoding stack results
0x4008d774: invoke_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c line 155
0x4008d9a5: abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c line 170
0x400ec7ef: __assert_func at ../../../.././newlib/libc/stdlib/assert.c line 63
0x4008d401: multi_heap_free at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/multi_heap_poisoning.c line 214
0x40085456: heap_caps_free at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/heap_caps.c line 268
0x40085c2d: _free_r at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/newlib/syscalls.c line 42
0x400e24fb: i2cFlush at C:\users\quan\.platformio\packages\framework-arduinoespressif32\cores\esp32\esp32-hal-i2c.c line 1604
0x400e2e0c: i2cRead at C:\users\quan\.platformio\packages\framework-arduinoespressif32\cores\esp32\esp32-hal-i2c.c line 1649
0x400dc025: TwoWire::readTransmission(unsigned short, unsigned char*, unsigned short, bool, unsigned int*) at C:\users\quan\.platformio\packages\framework-arduinoespressif32\libraries\Wire\src\Wire.cpp line 139
0x400dc0d9: TwoWire::requestFrom(unsigned short, unsigned char, bool) at C:\users\quan\.platformio\packages\framework-arduinoespressif32\libraries\Wire\src\Wire.cpp line 193
0x400dc155: TwoWire::requestFrom(int, int) at C:\users\quan\.platformio\packages\framework-arduinoespressif32\libraries\Wire\src\Wire.cpp line 296
0x400dafcc: getBatteryGauge() at src\myPower.cpp line 16
0x400daff8: powerLoop(void*) at src\myPower.cpp line 37
0x40089eb1: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c line 143

然后有时我会得到以下信息:

assertion "head != NULL" failed: file "/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/multi_heap_poisoning.c", line 245, function: multi_heap_realloc
Decoding stack results
0x4008d774: invoke_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c line 155
0x4008d9a5: abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c line 170
0x400ec7eb: __assert_func at ../../../.././newlib/libc/stdlib/assert.c line 59
0x4008d459: multi_heap_realloc at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/multi_heap_poisoning.c line 245
0x400854c6: heap_caps_realloc at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/heap_caps.c line 297
0x4008552a: heap_caps_realloc_default at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/heap/heap_caps.c line 163
0x40085c3d: _realloc_r at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/newlib/syscalls.c line 47
0x400e22ca: i2cAddQueue at C:\users\quan\.platformio\packages\framework-arduinoespressif32\cores\esp32\esp32-hal-i2c.c line 1057
0x400e234f: i2cAddQueueWrite at C:\users\quan\.platformio\packages\framework-arduinoespressif32\cores\esp32\esp32-hal-i2c.c line 1081
0x400e2d4c: i2cWrite at C:\users\quan\.platformio\packages\framework-arduinoespressif32\cores\esp32\esp32-hal-i2c.c line 1617
0x400dc001: TwoWire::writeTransmission(unsigned short, unsigned char*, unsigned short, bool) at C:\users\quan\.platformio\packages\framework-arduinoespressif32\libraries\Wire\src\Wire.cpp line 133
0x400dc055: TwoWire::endTransmission(bool) at C:\users\quan\.platformio\packages\framework-arduinoespressif32\libraries\Wire\src\Wire.cpp line 158
0x400dc558: CommUtil::readByte(unsigned char, unsigned char, unsigned char*) at C:\users\quan\.platformio\lib\M5Stack_ID1851\src\utility\CommUtil.cpp line 98
0x400dfcf6: MPU9250::readByte(unsigned char, unsigned char) at C:\users\quan\.platformio\lib\M5Stack_ID1851\src\utility\MPU9250.cpp line 438
0x400d1bce: readIMU(void*) at src\accelerometer.cpp line 75
0x40089eb1: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c line 143

这两个错误看起来很相似,但它们是从不同的地方调用的。我已将 PMIC 和 IMU 读取放在单独的 FreeRTOS 任务中。我是否需要确保在每次 I2C 读取之前获取信号量并在完成后将其返回?我已经把它放在我明确读取值的代码中,但可能遗漏了一些地方。大多数 M5Stack 代码一次只演示一个模块,因此当您组合多个传感器时,我不确定最佳实践。非常感谢任何指导。

【问题讨论】:

这是代码中某处缓冲区溢出的症状。如果您使用的是 RTOS,最好使用信号量。该错误似乎来自传感器读取缓冲区溢出。 【参考方案1】:

您需要使用互斥锁从不同的任务访问硬件。

  //GLOBAL
  SemaphoreHandle_t xI2CSemaphore;            //Shared I2C Resource Mutex
  
  //PROGRAM SETUP
  if ( xI2CSemaphore == NULL )
  
    xI2CSemaphore = xSemaphoreCreateMutex();
    if ( ( xI2CSemaphore ) != NULL )
      xSemaphoreGive( ( xI2CSemaphore ) );
  



 //WHEN USING IN A TASK...
 if ( xSemaphoreTake( xI2CSemaphore, ( TickType_t ) 250 ) == pdTRUE )
 

 xSemaphoreGive( xI2CSemaphore ); // Now free or "Give" the Serial Port for others.
 

【讨论】:

以上是关于ESP32 偶尔与多个 I2C 设备崩溃,堆问题?的主要内容,如果未能解决你的问题,请参考以下文章

ESP32学习笔记(17)——I2C接口使用

ESP32学习笔记(17)——I2C接口使用

ESP32-IDF开发实例-JSON数据构造与解析

ESP32开发板控制OLED显示屏

ESP32开发板控制OLED显示屏

ESP32学习笔记之I2C总线