h2zero / NimBLE-Arduino

A fork of the NimBLE library structured for compilation with Arduino, for use with ESP32, nRF5x.
https://h2zero.github.io/NimBLE-Arduino/
Apache License 2.0
667 stars 138 forks source link

Crash with 'Arduino Nano ESP32' on core ESP32 3.0.1 with NimbleV1.4.2 #688

Open ednieuw opened 2 weeks ago

ednieuw commented 2 weeks ago

I installed the latest NimBLE 1.4.2 library and compiled it for the Arduino Nano ESP32 board with ESP32 core 2.0.13, which worked fine.

Then, I switched to the ESP32 3.0.1 board, restarted my PC, and compiled my program using NimBLE for ESP32-C3 and ESP32-S3 boards, which also worked fine.

However, the Arduino Nano ESP32 crashes when compiling and uploading with the ESP32 core 3.0.1.

I attempted the example programs 'NimBLE_Scan_Continuous' and 'BLE_uart', and both caused the Nano to crash.

After compilation, the upload COM port, COM13 in my case, disappears, and a new COM port, COM12, appears after the upload.

There are no errors during compilation, but the Arduino Nano must be put into boot mode for a new upload.

I tried the ArduinoBLE example 'Scan', which worked, but the 'UART' example failed to compile, showing errors. This is unfortunate because I need the UART connectivity.

Below the BLE code in my program

 //--------------------------------------------                                                //
// BLE 
// SendMessage by BLE Slow in packets of 20 chars
// or fast in one long string.
// Fast can be used in IOS app BLESerial Pro
//------------------------------
void SendMessageBLE(std::string Message)
{
 if(deviceConnected) 
   {
    if (Mem.UseBLELongString)                                                                 // If Fast transmission is possible
     {
      pTxCharacteristic->setValue(Message); 
      pTxCharacteristic->notify();
      delay(10);                                                                              // Bluetooth stack will go into congestion, if too many packets are sent
     } 
   else                                                                                       // Packets of max 20 bytes
     {   
      int parts = (Message.length()/20) + 1;
      for(int n=0;n<parts;n++)
        {   
         pTxCharacteristic->setValue(Message.substr(n*20, 20)); 
         pTxCharacteristic->notify();
         delay(40);                                                                           // Bluetooth stack will go into congestion, if too many packets are sent
        }
     }
   } 
}
//-----------------------------
// BLE Start BLE Classes
//------------------------------
class MyServerCallbacks: public BLEServerCallbacks 
{
 void onConnect(BLEServer* pServer) {deviceConnected = true; };
 void onDisconnect(BLEServer* pServer) {deviceConnected = false;}
};

class MyCallbacks: public BLECharacteristicCallbacks 
{
 void onWrite(BLECharacteristic *pCharacteristic) 
  {
   std::string rxValue = pCharacteristic->getValue();
   ReceivedMessageBLE = rxValue + "\n";
//   if (rxValue.length() > 0) {for (int i = 0; i < rxValue.length(); i++) printf("%c",rxValue[i]); }
//   printf("\n");
  }  
};
//--------------------------------------------                                                //
// BLE Start BLE Service
//------------------------------
void StartBLEService(void)
{
 BLEDevice::init(Mem.BLEbroadcastName);                                                       // Create the BLE Device
 pServer = BLEDevice::createServer();                                                         // Create the BLE Server
 pServer->setCallbacks(new MyServerCallbacks());
 BLEService *pService = pServer->createService(SERVICE_UUID);                                 // Create the BLE Service
 pTxCharacteristic                     =                                                      // Create a BLE Characteristic 
     pService->createCharacteristic(CHARACTERISTIC_UUID_TX, NIMBLE_PROPERTY::NOTIFY);                 
 BLECharacteristic * pRxCharacteristic = 
     pService->createCharacteristic(CHARACTERISTIC_UUID_RX, NIMBLE_PROPERTY::WRITE);
 pRxCharacteristic->setCallbacks(new MyCallbacks());
 pService->start(); 
 BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
 pAdvertising->addServiceUUID(SERVICE_UUID); 
 pServer->start();                                                                            // Start the server  Nodig??
 pServer->getAdvertising()->start();                                                          // Start advertising
 TekstSprint("BLE Waiting a client connection to notify ...\n"); 
}
//                                                                                            //
//-----------------------------
// BLE  CheckBLE
//------------------------------
void CheckBLE(void)
{
 if(!deviceConnected && oldDeviceConnected)                                                   // Disconnecting
   {
    delay(300);                                                                               // Give the bluetooth stack the chance to get things ready
    pServer->startAdvertising();                                                              // Restart advertising
    TekstSprint("Start advertising\n");
    oldDeviceConnected = deviceConnected;
   }
 if(deviceConnected && !oldDeviceConnected)                                                   // Connecting
   { 
    oldDeviceConnected = deviceConnected;
    SWversion();
   }
 if(ReceivedMessageBLE.length()>0)
   {
    SendMessageBLE(ReceivedMessageBLE);
    String BLEtext = ReceivedMessageBLE.c_str();
    ReceivedMessageBLE = "";
    ReworkInputString(BLEtext); 
   }
}
h2zero commented 2 weeks ago

@ednieuw could you please try this:

#include "NimBLEDevice.h"
void setup() { NimBLEDevice::init(""); }
void loop() { delay(1); }

If that works, start adding more of your code until it crashes and report back.

ednieuw commented 2 weeks ago

I think I found the culprit. pServer->setCallbacks(new MyServerCallbacks()); When this line is in the code the upload succeeds but COM13 disappears in COM12 comes up. When you disconnect and reset the Nano by double pressing the button it goes in boot mode. and you see the green LED flashing.

A new upload with the line " pServer->setCallbacks(new MyServerCallbacks()); " disabled seems to work but it is not. You have to disconnect the Nano again and upload. Probably the Nano copies back the bad source when it is in a stress situation.

That is why is added some LED flashing and Serial printing commands. I have also tested the GPIO legacy setting, which is necessary to operate NeoPixel. Initially, I suspected an issue with core version 3.0.1, NimBLE, and the GPIO legacy setting. However, that does not appear to be the case.

For now I learned to be sure the Nano does not fall back and keeps the old program in it. After a crash first upload a small blinking program in it and if that works the actual corrected program again.


#include "NimBLEDevice.h"

BLEServer *pServer      = NULL;
BLECharacteristic * pTxCharacteristic;
bool deviceConnected    = false;
bool oldDeviceConnected = false;
std::string ReceivedMessageBLE;

#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"                         // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

static uint32_t msTick;
enum DigitalPinAssignments {   
 PCB_LED_D09  = D9,               // D9
 PCB_LED_D10  = D10,              // D10
 secondsPin   = LED_BUILTIN,      // D13  GPIO48 (#ifdef LED_BUILTIN  #undef LED_BUILTIN #define LED_BUILTIN 48)
};
//-----------------------------
// BLE Start BLE Classes
//------------------------------
class MyServerCallbacks: public BLEServerCallbacks 
{
 void onConnect(BLEServer* pServer) {deviceConnected = true; };
 void onDisconnect(BLEServer* pServer) {deviceConnected = false;}
};

class MyCallbacks: public BLECharacteristicCallbacks 
{
 void onWrite(BLECharacteristic *pCharacteristic) 
  {
   std::string rxValue = pCharacteristic->getValue();
   ReceivedMessageBLE = rxValue + "\n";
//   if (rxValue.length() > 0) {for (int i = 0; i < rxValue.length(); i++) printf("%c",rxValue[i]); }
//   printf("\n");
  }  
};

void setup() 
{ 
 Serial.begin(115200);        
 pinMode(secondsPin, OUTPUT);                                                                 // turn On seconds LED-pin
 pinMode(PCB_LED_D09, OUTPUT);                                                                // LED on PCB board  09
 pinMode(PCB_LED_D10, OUTPUT);                                                                // LED on PCB board  10
  int32_t Tick = millis();  
  while (!Serial)  
 {if ((millis() - Tick) >5000) break;}  Serial.println("Serial started");                       // Wait max 5 seconds until serial port is started   
  NimBLEDevice::init("TestEd"); 
  pServer = BLEDevice::createServer();                                                         // Create the BLE Server
 //pServer->setCallbacks(new MyServerCallbacks());   //  << --- THIS fails
Serial.println("Started");

}

//--------------------------------------------                                                //
// BLE 
// SendMessage by BLE Slow in packets of 20 chars
// or fast in one long string.
// Fast can be used in IOS app BLESerial Pro
//------------------------------
void SendMessageBLE(std::string Message)
{
 if(deviceConnected) 
   {
    if (false)               //Mem.UseBLELongString                                                  // If Fast transmission is possible
     {
      pTxCharacteristic->setValue(Message); 
      pTxCharacteristic->notify();
      delay(10);                                                                              // Bluetooth stack will go into congestion, if too many packets are sent
     } 
   else                                                                                       // Packets of max 20 bytes
     {   
      int parts = (Message.length()/20) + 1;
      for(int n=0;n<parts;n++)
        {   
         pTxCharacteristic->setValue(Message.substr(n*20, 20)); 
         pTxCharacteristic->notify();
         delay(40);                                                                           // Bluetooth stack will go into congestion, if too many packets are sent
        }
     }
   } 
}

void loop() {  EverySecondCheck(); }

void EverySecondCheck(void)
{
 static bool Toggle = 1;
 uint32_t msLeap = millis() - msTick;                                                         // 
 if (msLeap >999)                                                                             // Every second enter the loop
 {
  msTick = millis();                                                                          // get the time for the seconds 
  Toggle = !Toggle;                                                                           // Used to turn On or Off Leds
  UpdateStatusLEDs(Toggle);
 }  
}

void UpdateStatusLEDs(bool Toggle)
{
  digitalWrite(LED_BUILTIN, Toggle);                                                      // Turn the LED on/ or off
  digitalWrite(PCB_LED_D09, Toggle);                                                      //
  digitalWrite(PCB_LED_D10, 1-Toggle);                                                    //
}