Other Parts Discussed in Thread: BLE-STACK
Tool/software: TI-RTOS
Since July 2018 we are already having the below problems, and still no fix has been made by Ti although we have reported the bug multiple times.
Stack crash when connecting with multiple devices
Setup
- SDK 2.40 (January 2019)
- Simple_Peripheral example from this release
- Changed DEFAULT_ADDRESS_MODE to ADDRMODE_PUBLIC
- Added the below code snipped (borrowed from the forum) at the end of the SimplePeripheral_removeConn function for some memory information (and the .h file on the top of the SimplePeripheral project).
#include <xdc/cfg/global.h> // This is included to access cfg file variables
// Get the HeapSize
ICall_heapStats_t stats;
ICall_getHeapStats(&stats);
if((HEAPMGR_CONFIG & 0x03) == 0x00)
{
Display_printf(dispHandle, 14,0, "Using Heap: OSAL");
}
else if ((HEAPMGR_CONFIG & 0x03) == 0x01)
{
Display_printf(dispHandle, 14,0, "Using Heap: HeapMem");
}
else if((HEAPMGR_CONFIG & 0x03) == 0x02)
{
Display_printf(dispHandle, 14,0, "Using Heap: HeapMem + HeapTrack");
}
Display_printf(dispHandle, 15,0, "Heap Size total: %d", stats.totalSize);
Display_printf(dispHandle, 15,0, "Heap Size free: %d", stats.totalFreeSize);
- 8 ESP32 modules flashed with the below Arduino code (note: it's very dirty code)
/**
A BLE client example that is rich in capabilities.
There is a lot new capabilities implemented.
author unknown
updated by chegewara
*/
#include "BLEDevice.h"
//#include "BLEScan.h"
// The remote service we wish to connect to.
static BLEUUID serviceUUID("0000fff0-0000-1000-8000-00805f9b34fb");
// The characteristic of the remote service we are interested in.
static BLEUUID charUUID("beb5483e-36e1-4688-b7f5-ea07361b26a8");
const int ledPin = 21;
long myTime;
static boolean doConnect = false;
static boolean connected = false;
static boolean doScan = false;
static BLERemoteCharacteristic* pRemoteCharacteristic;
static BLEAdvertisedDevice* myDevice;
static void notifyCallback(
BLERemoteCharacteristic* pBLERemoteCharacteristic,
uint8_t* pData,
size_t length,
bool isNotify) {
Serial.print("Notify callback for characteristic ");
Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str());
Serial.print(" of data length ");
Serial.println(length);
Serial.print("data: ");
Serial.println((char*)pData);
}
class MyClientCallback : public BLEClientCallbacks {
void onConnect(BLEClient* pclient) {
}
void onDisconnect(BLEClient* pclient) {
connected = false;
Serial.println("onDisconnect");
ESP.restart();
}
};
bool connectToServer() {
Serial.print("Forming a connection to ");
Serial.println(myDevice->getAddress().toString().c_str());
BLEClient* pClient = BLEDevice::createClient();
Serial.println(" - Created client");
pClient->setClientCallbacks(new MyClientCallback());
// Connect to the remote BLE Server.
pClient->connect(myDevice); // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)
Serial.println(" - Connected to server");
// Obtain a reference to the service we are after in the remote BLE server.
BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
if (pRemoteService == nullptr) {
Serial.print("Failed to find our service UUID: ");
Serial.println(serviceUUID.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println(" - Found our service");
// // Obtain a reference to the characteristic in the service of the remote BLE server.
// pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
// if (pRemoteCharacteristic == nullptr) {
// Serial.print("Failed to find our characteristic UUID: ");
// Serial.println(charUUID.toString().c_str());
// pClient->disconnect();
// return false;
// }
// Serial.println(" - Found our characteristic");
//
// // Read the value of the characteristic.
// if(pRemoteCharacteristic->canRead()) {
// std::string value = pRemoteCharacteristic->readValue();
// Serial.print("The characteristic value was: ");
// Serial.println(value.c_str());
// }
//
// if(pRemoteCharacteristic->canNotify())
// pRemoteCharacteristic->registerForNotify(notifyCallback);
connected = true;
digitalWrite (ledPin, HIGH); // turn on the LED
////////////// disconnect ////////////////
Serial.println("Resetting in 9...");
delay(1000);
Serial.println("Resetting in 8...");
delay(1000);
Serial.println("Resetting in 7...");
delay(1000);
Serial.println("Resetting in 6...");
delay(1000);
Serial.println("Resetting in 5...");
delay(1000);
Serial.println("Resetting in 4...");
delay(1000);
Serial.println("Resetting in 3...");
delay(1000);
Serial.println("Resetting in 2...");
delay(1000);
Serial.println("Resetting in 1...");
delay(1000);
delay(1000);
ESP.restart();
//////////////////////////////////////////
}
/**
Scan for BLE servers and find the first one that advertises the service we are looking for.
*/
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
/**
Called for each advertising BLE server.
*/
void onResult(BLEAdvertisedDevice advertisedDevice) {
Serial.print("BLE Advertised Device found: ");
Serial.println(advertisedDevice.toString().c_str());
// We have found a device, let us now see if it contains the service we are looking for.
if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) { // Found our server
BLEDevice::getScan()->stop();
myDevice = new BLEAdvertisedDevice(advertisedDevice);
doConnect = true;
doScan = true;
}
} // onResult
}; // MyAdvertisedDeviceCallbacks
void setup() {
Serial.begin(115200);
Serial.println("Starting Arduino BLE Client application...");
BLEDevice::init("");
// Retrieve a Scanner and set the callback we want to use to be informed when we
// have detected a new device. Specify that we want active scanning and start the
// scan to run for 5 seconds.
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setInterval(100);
pBLEScan->setWindow(99);
pBLEScan->setActiveScan(true);
pBLEScan->start(5, false);
pinMode (ledPin, OUTPUT);
digitalWrite (ledPin, LOW); // turn off the LED
myTime = millis();
} // End of setup.
// This is the Arduino main loop function.
void loop() {
// If the flag "doConnect" is true then we have scanned for and found the desired
// BLE Server with which we wish to connect. Now we connect to it. Once we are
// connected we set the connected flag to be true.
if (doConnect == true) {
if (connectToServer()) {
Serial.println("We are now connected to the BLE Server.");
} else {
Serial.println("We have failed to connect to the server; let's reset and try again.");
ESP.restart();
}
doConnect = false;
}
// If we are connected to a peer BLE Server, update the characteristic each time we are reached
// with the current time since boot.
if (doScan) BLEDevice::getScan()->start(0); // this is just eample to start scan after disconnect, most likely there is better way to do it in arduino
if (millis() > myTime + 5000 && connected == false) {
Serial.println("No device found, resetting...");
ESP.restart();
}
delay(1000); // Delay a second between loops.
} // End of loop
Procedure
- Connect all ESP32 modules to a 8-port switch
- Turn on the switch. Randomly turn it off and on. Also, the Arduino's will randomly start and stop by themselves.
Result
- Within a few minutes, the stack will crash. See the below screenshot.
- If you let about 5 modules connect, and then disconnect them all, you can see the memory footprint growing and growing.
Stack stuck, no crash (or maybe just not yet)
We tried something else.
Setup
- We changed DEFAULT_DESIRED_MIN_CONN_INTERVAL to 12, DEFAULT_DESIRED_MAX_CONN_INTERVAL to 12, and BTM_BLE_CONN_TIMEOUT_DEF to 600.
- We show the parameters where devices initially connect with by adding the following line in SimplePeripheral
// Display the address of the connection update Display_printf(dispHandle, SP_ROW_STATUS_2, 0, "Link Param Updated: %s __ Interval: %d Latency: %d Timeout: %d", Util_convertBdAddr2Str(linkInfo.addr), pPkt->connInterval, pPkt->connLatency, pPkt->connTimeout);
- And also at the end of the AddConn function:
Display_printf(dispHandle, SP_ROW_STATUS_2, 0, "Interval: %d Latency: %d Timeout: %d", linkInfo.connInterval, linkInfo.connLatency, linkInfo.connTimeout);
- We added The following code in our Arduino project, just before pClient->Connect:
esp_bd_addr_t addr; memcpy(addr,myDevice->getAddress().toString().c_str(),6); esp_ble_gap_set_prefer_conn_params(addr, 12,12, 0, 600);
This will cause the Arduino ESP32 example to connect without any parameter updates happening. We were hoping this might fix the issue (we've had issues with parameter updates in the past).
Procedure
- Let the ESP32 connect for a few times (it resets a few times automatically). You'll notice that sometimes you can see 3 connections on the serial output, while actually there is only 1 devices connecting. Before we reached 2 maximum, but now 3. Probably this happens due to the increase timeout value of 600 instead of 300.
Result
The result of this was that the stack got stuck. It didn't get into an Abort, but it stopped advertising and we were not able to connect anymore.
We think something in handling multiple connection to the same devices it not going well in the stack. Please help us: in 2 weeks we're starting a demo with our customers, and this issue happens often.
