-
-
Notifications
You must be signed in to change notification settings - Fork 186
Description
ESP32-S3 dual-role (client + server) fails with rc=519
on all NimBLE-Arduino versions 2.3.x
Description
When using an ESP32-S3 as both BLE central (client) and BLE peripheral (server), advertising (or connection) fails with:
E NimBLEAdvertising: Error enabling advertising; rc=519, Memory Capacity Exceeded
-
This occurs only on NimBLE-Arduino versions 2.3.x.
-
The exact same sketch runs correctly on NimBLE-Arduino version 2.2.3 without changes.
This looks like a regression in how NimBLE configures controller resources (advertising sets, connection pools, or GATT service init) on the ESP32-S3.
Minimal Reproduction Code
#include <NimBLEDevice.h>
static bool clientConnected = false;
const NimBLEAdvertisedDevice* foundDevice = nullptr;
// ========== Central (client) callbacks ==========
class clientCallbacks : public NimBLEClientCallbacks {
void onConnect(NimBLEClient* pClient) {
Serial.println(">> Client connected");
clientConnected = true;
}
void onDisconnect(NimBLEClient* pClient) {
Serial.println(">> Client disconnected");
clientConnected = false;
}
};
class clientScanCallbacks : public NimBLEScanCallbacks {
void onResult(const NimBLEAdvertisedDevice* advertisedDevice) {
Serial.printf(">> Device found: %s\n", advertisedDevice->toString().c_str());
foundDevice = advertisedDevice;
NimBLEDevice::getScan()->stop();
}
};
// ========== Peripheral (server) setup ==========
void setupServer() {
// Generic Access (0x1800) is implicit, we add DIS and CPS
NimBLEServer* pServer = NimBLEDevice::createServer();
// Device Information Service
NimBLEService* dis = pServer->createService(NimBLEUUID((uint16_t)0x180A));
NimBLECharacteristic* dis_ManufacturerName = dis->createCharacteristic(NimBLEUUID((uint16_t)0x2A29), \
NIMBLE_PROPERTY::READ);
dis_ManufacturerName->setValue("Vendor");
dis->start();
// Cycling Power Service (basic)
NimBLEService* cps = pServer->createService(NimBLEUUID((uint16_t)0x1818));
NimBLECharacteristic* cps_Measurement = cps->createCharacteristic(NimBLEUUID((uint16_t)0x2A63), \
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY);
cps_Measurement->setValue("W");
cps->start();
Serial.println(">> Server is setup and started!");
pServer->start();
// Advertising Data setup
NimBLEAdvertising* pAdvertising = NimBLEDevice::getAdvertising();
if(pAdvertising->addServiceUUID((uint16_t)0x1818) )
Serial.println(">> Setting Service [cps] in Advertised data");
if(pAdvertising->setName("Repro"))
Serial.println(">> Setting DeviceName in Advertised data");
}
// ========== Main flow ==========
void setup() {
Serial.begin(115200);
delay(200);
Serial.printf("Free heap: %d\n", ESP.getFreeHeap());
Serial.printf("Free PSRAM: %d\n", ESP.getFreePsram());
NimBLEDevice::init("Repro");
setupServer();
// Client scan setup and start scanning
NimBLEScan* pScan = NimBLEDevice::getScan();
pScan->setScanCallbacks(new clientScanCallbacks());
pScan->setActiveScan(true);
pScan->start(0, false, false); // NO Restart
Serial.println(">> Scanning started");
}
void loop() {
if (foundDevice && !clientConnected) {
Serial.println(">> Attempting connection...");
NimBLEClient* client = NimBLEDevice::createClient();
client->setClientCallbacks(new clientCallbacks(), false);
if (!client->connect(foundDevice)) {
Serial.println(">> Connection failed");
} else {
Serial.println(">> Connection success");
}
foundDevice = nullptr;
if(NimBLEDevice::startAdvertising()) Serial.println(">> Advertising started!");
else Serial.println(">> Advertising start FAILED!");
}
delay(1000);
}
Steps to Reproduce
-
Flash above sketch on an ESP32-S3 board (tested with LilyGo T-Display S3 and Seeed XIAO S3).
-
Have any connectable BLE device nearby (phone or another ESP32 peripheral).
-
With NimBLE-Arduino version 2.2.3:
- Device scans, connects, then starts advertising successfully.
-
With NimBLE-Arduino version later than 2.2.3 (from 2.3.0 to present 2.3.4 tested!):
-
Device scans, connects OK.
-
When advertising starts (or on subsequent connection attempt), fails with:
-
E NimBLEAdvertising: Error enabling advertising; rc=519, Memory Capacity Exceeded
Expected Behavior
ESP32-S3 should be able to:
-
scan & connect as central, then
-
advertise as peripheral,
with at least a small set of services (GA, DIS, CPS).
This worked fine on NimBLE-Arduino 2.2.3.
Actual Behavior
On NimBLE-Arduino versions 2.3.x:
-
Scan + connect still works.
-
Advertising (or connection in reversed order) fails with rc=519.
Environment
-
Board(s): ESP32-S3 (e.g. LilyGo T-Display S3, Seeed XIAO ESP32S3)
-
Arduino-esp32: tested version 3.2.0 until present 3.3.0 (no difference)
-
NimBLE-Arduino:
-
✅ 2.2.3 → works
-
❌ versions 2.3.x → fail with rc=519
-
-
PSRAM: enabled (8 MB available)
-
Heap: ~260 KB free before advertising
Regression Notes
-
The issue only appears starting with NimBLE-Arduino versions 2.3.x
-
Likely related to how versions later than 2.2.3 configure controller resources (advertising sets, connection pools, or GATT service init) for ESP32-S3.
-
Advertising payload size does not affect outcome (tested trimmed down).
-
Scanning and advertising are not active simultaneously.