ArduinoBLE
ArduinoBLE copied to clipboard
ESP32: BLEDevice::discoverService(SERVICE_UUID) made ESP crash because runs out of memory
Hi,
Since ArduinoBLE is compatible with ESP32 with the latest merge, I'm trying to use it with an ESP32.
But when I run the example "PeripheralExplorer.ino", I got this exception: (I update the code to detect a peripheral with localName = "D1533286" instead of "Led")
Found 00:a0:50:61:87:06 'D1533286' 00035b03-58e6-07dd-021a-08123a000300
Connecting ...
Connected
Discovering attributes ...
Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x400904c5 PS : 0x00060030 A0 : 0x800d5c70 A1 : 0x3ffc6980
A2 : 0x00000000 A3 : 0xfffffffc A4 : 0x000000ff A5 : 0x0000ff00
A6 : 0x00ff0000 A7 : 0xff000000 A8 : 0x00000000 A9 : 0x3ffc6aa0
A10 : 0x3ffbcadc A11 : 0x00001800 A12 : 0x00000010 A13 : 0x3ffc29f4
A14 : 0x3ffc6940 A15 : 0x3ffc6950 SAR : 0x0000000f EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000000 LBEG : 0x400904c5 LEND : 0x400904d5 LCOUNT : 0xffffffff
Backtrace:0x400904c2:0x3ffc69800x400d5c6d:0x3ffc6990 0x400d4ddf:0x3ffc69c0 0x400d3c81:0x3ffc6b20 0x400d22cb:0x3ffc6b50 0x400d16cd:0x3ffc6b70 0x400d1962:0x3ffc6bc0 0x400d99a1:0x3ffc6c80
ELF file SHA256: 0000000000000000
I don't understand why this exception occurred.
Here is my code:
/*
Peripheral Explorer
This example scans for Bluetooth® Low Energy peripherals until one with a particular name ("LED")
is found. Then connects, and discovers + prints all the peripheral's attributes.
The circuit:
- Arduino MKR WiFi 1010, Arduino Uno WiFi Rev2 board, Arduino Nano 33 IoT,
Arduino Nano 33 BLE, or Arduino Nano 33 BLE Sense board.
You can use it with another board that is compatible with this library and the
Peripherals -> LED example.
This example code is in the public domain.
*/
#include <ArduinoBLE.h>
void setup()
{
Serial.begin(9600);
while (!Serial)
;
// begin initialization
if (!BLE.begin())
{
Serial.println("starting Bluetooth® Low Energy module failed!");
while (1)
;
}
Serial.println("Bluetooth® Low Energy Central - Peripheral Explorer");
// start scanning for peripherals
BLE.scan();
}
void loop()
{
// check if a peripheral has been discovered
BLEDevice peripheral = BLE.available();
if (peripheral)
{
// discovered a peripheral, print out address, local name, and advertised service
Serial.print("Found ");
Serial.print(peripheral.address());
Serial.print(" '");
Serial.print(peripheral.localName());
Serial.print("' ");
Serial.print(peripheral.advertisedServiceUuid());
Serial.println();
// see if peripheral is a LED
if (peripheral.localName() == "D1533286")
{
// stop scanning
BLE.stopScan();
explorerPeripheral(peripheral);
// peripheral disconnected, we are done
while (1)
{
// do nothing
}
}
}
}
void explorerPeripheral(BLEDevice peripheral)
{
// connect to the peripheral
Serial.println("Connecting ...");
if (peripheral.connect())
{
Serial.println("Connected");
}
else
{
Serial.println("Failed to connect!");
return;
}
// discover peripheral attributes
Serial.println("Discovering attributes ...");
if (peripheral.discoverAttributes())
{
Serial.println("Attributes discovered");
}
else
{
Serial.println("Attribute discovery failed!");
peripheral.disconnect();
return;
}
// read and print device name of peripheral
Serial.println();
Serial.print("Device name: ");
Serial.println(peripheral.deviceName());
Serial.print("Appearance: 0x");
Serial.println(peripheral.appearance(), HEX);
Serial.println();
// loop the services of the peripheral and explore each
for (int i = 0; i < peripheral.serviceCount(); i++)
{
BLEService service = peripheral.service(i);
exploreService(service);
}
Serial.println();
// we are done exploring, disconnect
Serial.println("Disconnecting ...");
peripheral.disconnect();
Serial.println("Disconnected");
}
void exploreService(BLEService service)
{
// print the UUID of the service
Serial.print("Service ");
Serial.println(service.uuid());
// loop the characteristics of the service and explore each
for (int i = 0; i < service.characteristicCount(); i++)
{
BLECharacteristic characteristic = service.characteristic(i);
exploreCharacteristic(characteristic);
}
}
void exploreCharacteristic(BLECharacteristic characteristic)
{
// print the UUID and properties of the characteristic
Serial.print("\tCharacteristic ");
Serial.print(characteristic.uuid());
Serial.print(", properties 0x");
Serial.print(characteristic.properties(), HEX);
// check if the characteristic is readable
if (characteristic.canRead())
{
// read the characteristic value
characteristic.read();
if (characteristic.valueLength() > 0)
{
// print out the value of the characteristic
Serial.print(", value 0x");
printData(characteristic.value(), characteristic.valueLength());
}
}
Serial.println();
// loop the descriptors of the characteristic and explore each
for (int i = 0; i < characteristic.descriptorCount(); i++)
{
BLEDescriptor descriptor = characteristic.descriptor(i);
exploreDescriptor(descriptor);
}
}
void exploreDescriptor(BLEDescriptor descriptor)
{
// print the UUID of the descriptor
Serial.print("\t\tDescriptor ");
Serial.print(descriptor.uuid());
// read the descriptor value
descriptor.read();
// print out the value of the descriptor
Serial.print(", value 0x");
printData(descriptor.value(), descriptor.valueLength());
Serial.println();
}
void printData(const unsigned char data[], int length)
{
for (int i = 0; i < length; i++)
{
unsigned char b = data[i];
if (b < 16)
{
Serial.print("0");
}
Serial.print(b, HEX);
}
}
Thanks
UPDATE 2022-08-31
BLEDevice::discoverService
crashes when ATTClass::discoverAttributes
discovers descriptors with ATTClass::discoverDescriptors
.
The while loop inside ATTClass::discoverDescriptors
is never stopped and reads the descriptors in a loop until the ESP has no more memory.
I found that for my device there are only 16 descriptors, so I managed to make my program work by stopping the loop after 16 iterations, but I don't understand why the condition if (responseBuffer[0] == ATT_OP_FIND_INFO_RESP) {
is always true.
I'm getting the same error with .discoverAttributes(), however if I call .discoverService("uuid here") and pass in my service uuid instead it does not crash and lets me connect.
//if (peripheral.discoverAttributes()) { //causes an error on ESP32
if (peripheral.discoverService(SERVICE_ATT)) { //works fine on ESP32
I'm not sure what effect this will have down the line, but happy to see ESP32 support is being actively worked on
Thanks for your comment! So, with your method, you can access to the characteristics of the device?
I will test that tomorrow!
Yes so far everything else in the BLE sample is working on the ESP32. (I'm using the LED control sample as a starting point).
When I use peripheral.discoverService("my-service-uuid")
, the ESP crashes too.
Here is the backtrace:
Decoding stack results
0x400836a5: panic_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/panic.c line 402
0x40092149: esp_system_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/esp_system.c line 128
0x400975c5: abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/newlib/abort.c line 46
0x40102f93: __cxxabiv1::__terminate(void (*)()) at /builds/idf/crosstool-NG/.build/HOST-i686-w64-mingw32/xtensa-esp32-elf/src/gcc/libstdc++-v3/libsupc++/eh_terminate.cc line 47
0x40102fda: std::terminate() at /builds/idf/crosstool-NG/.build/HOST-i686-w64-mingw32/xtensa-esp32-elf/src/gcc/libstdc++-v3/libsupc++/eh_terminate.cc line 57
0x40102a79: __cxxabiv1::__cxa_allocate_exception(std::size_t) at /builds/idf/crosstool-NG/.build/HOST-i686-w64-mingw32/xtensa-esp32-elf/src/gcc/libstdc++-v3/libsupc++/eh_alloc.cc line 300
0x401028b0: operator new(unsigned int) at /builds/idf/crosstool-NG/.build/HOST-i686-w64-mingw32/xtensa-esp32-elf/src/gcc/libstdc++-v3/libsupc++/new_op.cc line 54
0x400d5121: ATTClass::discoverDescriptors(unsigned short, BLERemoteDevice*) at C:\Users\victo\Documents\Arduino\libraries\ArduinoBLE\src\utility\ATT.cpp line 1738
0x400d3cab: ATTClass::discoverAttributes(unsigned char, unsigned char*, char const*) at C:\Users\victo\Documents\Arduino\libraries\ArduinoBLE\src\utility\ATT.cpp line 217
0x400d22d3: BLEDevice::discoverService(char const*) at C:\Users\victo\Documents\Arduino\libraries\ArduinoBLE\src\BLEDevice.cpp line 274
0x400d16d5: explorerPeripheral(BLEDevice) at C:\Users\victo\Documents\Arduino\generated_examples\PeripheralExplorer_3/PeripheralExplorer_3.ino line 90
0x400d196a: loop() at C:\Users\victo\Documents\Arduino\libraries\ArduinoBLE\src/BLEDevice.h line 39
0x400d93a1: loopTask(void*) at C:\Users\victo\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.4\cores\esp32\main.cpp line 50
The problem occurs when the function ATTClass::discoverDecriptors
creates a new BLERemoteDescriptor
. But I don't know why.
After some researches, I found out that the problem occurs because of an infinite loop in the function bool ATTClass::discoverDescriptors(uint16_t connectionHandle, BLERemoteDevice* device)
in src/utility/ATT.cpp
The program finds descriptors but loop to them until the ESP runs out of memory. I manage to fix this temporary with a counter that stop the loop after 16 iterations, but I suppose there is a bug hidden somewhere that prevents the condition if (responseBuffer[0] == ATT_OP_FIND_INFO_RESP) {
from being false.
Maybe linked to https://github.com/arduino-libraries/ArduinoBLE/pull/259 ?
Maybe #259 fixed peripheral.discoverAttributes()
but there is a problem after. I will rename the issue to be more accurate.