arduino-libraries / ArduinoBLE

ArduinoBLE library for Arduino
GNU Lesser General Public License v2.1
315 stars 205 forks source link

Fix for BLE restart after a BLE end on portenta based devices #374

Open fabik111 opened 3 weeks ago

fabik111 commented 3 weeks ago

On portenta based board, if the user sketch starts and stops BLE several time, after the first time, the BLE stack advertises the wrong BLE mac address ( "AA:AA:AA:AA:AA:AA" ). This is caused because the BLE.end() function of ArduinoBLE doesn't turn off correctly the BLE mbed-os library.

Here a sketch for reproducing the bug.

#include <ArduinoBLE.h>
REDIRECT_STDOUT_TO(Serial);
BLEService ledService("19B10000-E8F2-537E-4F6C-D104768A1214"); // Bluetooth® Low Energy LED Service

// Bluetooth® Low Energy LED Switch Characteristic - custom 128-bit UUID, read and writable by central
BLEByteCharacteristic switchCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);
bool turnedOn = false;
const int ledPin = LED_BUILTIN; // pin to use for the LED
uint32_t lastChange = 0;
void turnBLEon(){
 // begin initialization
  if (!BLE.begin()) {
    Serial.println("starting Bluetooth® Low Energy module failed!");

    while (1);
  }

  // set advertised local name and service UUID:
  BLE.setLocalName("LED");
  BLE.setAdvertisedService(ledService);

  // add the characteristic to the service
  ledService.addCharacteristic(switchCharacteristic);

  // add service
  BLE.addService(ledService);

  // set the initial value for the characeristic:
  switchCharacteristic.writeValue(0);

  // start advertising
  BLE.advertise();

  Serial.println("BLE LED Peripheral");
  turnedOn = true;
}

void turnBLEoff(){
  BLEDevice central = BLE.central();
  if(central && central.connected()){
    BLE.disconnect();
  }
  BLE.end();
  turnedOn=false;
}

void setup() {
  Serial.begin(9600);
  while (!Serial);
  //BLE.debug(Serial);
  // set LED pin to output mode
  pinMode(ledPin, OUTPUT);

  turnBLEon();
  lastChange = millis();
}

void loop() {

  if(lastChange + 20000 < millis()){
    if(turnedOn){
      Serial.println("change turn off");
      turnBLEoff();

    }else{
      Serial.println("change turn on");
      turnBLEon();
    }
    lastChange = millis();
  }

  if(turnedOn){
    // listen for Bluetooth® Low Energy peripherals to connect:
    BLEDevice central = BLE.central();

    // if a central is connected to peripheral:
    if (central) {
      Serial.print("Connected to central: ");
      // print the central's MAC address:
      Serial.println(central.address());

      // while the central is still connected to peripheral:
      while (central.connected()) {
        // if the remote device wrote to the characteristic,
        // use the value to control the LED:
        if (switchCharacteristic.written()) {
          if (switchCharacteristic.value()) {   // any value other than 0
            Serial.println("LED on");
            digitalWrite(ledPin, HIGH);         // will turn the LED on
          } else {                              // a 0 value
            Serial.println(F("LED off"));
            digitalWrite(ledPin, LOW);          // will turn the LED off
          }
        }
      }

      // when the central disconnects, print it out:
      Serial.print(F("Disconnected from central: "));
      Serial.println(central.address());
    }
  }
}

The fix improves the HCICordioTransportClass::end() calling the ble.shutdown() of mbed-os BLE library and restores the default HCI data received handler to make a valid initialization of the BLE chip at the coming restart.

This PR depends on this PR on the mbed-os repository; do not merge separately.

github-actions[bot] commented 3 weeks ago

Memory usage change @ eab56317032f9c878503f61090ad3b043ff17001

Board flash % RAM for global variables %
arduino:mbed_nano:nano33ble :small_red_triangle: 0 - +64 0.0 - +0.01 0 - 0 0.0 - 0.0
arduino:mbed_nano:nanorp2040connect 0 - 0 0.0 - 0.0 0 - 0 0.0 - 0.0
arduino:megaavr:uno2018:mode=on 0 - 0 0.0 - 0.0 0 - 0 0.0 - 0.0
arduino:renesas_uno:unor4wifi 0 - 0 0.0 - 0.0 0 - 0 0.0 - 0.0
arduino:samd:mkrwifi1010 0 - 0 0.0 - 0.0 0 - 0 0.0 - 0.0
arduino:samd:nano_33_iot 0 - 0 0.0 - 0.0 0 - 0 0.0 - 0.0
Click for full report table Board|`examples/Central/LedControl`
flash|%|`examples/Central/LedControl`
RAM for global variables|%|`examples/Central/PeripheralExplorer`
flash|%|`examples/Central/PeripheralExplorer`
RAM for global variables|%|`examples/Central/Scan`
flash|%|`examples/Central/Scan`
RAM for global variables|%|`examples/Central/ScanCallback`
flash|%|`examples/Central/ScanCallback`
RAM for global variables|%|`examples/Central/SensorTagButton`
flash|%|`examples/Central/SensorTagButton`
RAM for global variables|%|`examples/Peripheral/Advertising/EnhancedAdvertising`
flash|%|`examples/Peripheral/Advertising/EnhancedAdvertising`
RAM for global variables|%|`examples/Peripheral/Advertising/RawDataAdvertising`
flash|%|`examples/Peripheral/Advertising/RawDataAdvertising`
RAM for global variables|%|`examples/Peripheral/BatteryMonitor`
flash|%|`examples/Peripheral/BatteryMonitor`
RAM for global variables|%|`examples/Peripheral/ButtonLED`
flash|%|`examples/Peripheral/ButtonLED`
RAM for global variables|%|`examples/Peripheral/CallbackLED`
flash|%|`examples/Peripheral/CallbackLED`
RAM for global variables|%|`examples/Peripheral/EncryptedBatteryMonitor`
flash|%|`examples/Peripheral/EncryptedBatteryMonitor`
RAM for global variables|%|`examples/Peripheral/LED`
flash|%|`examples/Peripheral/LED`
RAM for global variables|% -|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|- `arduino:mbed_nano:nano33ble`|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|64|0.01|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|64|0.01|0|0.0|0|0.0|0|0.0 `arduino:mbed_nano:nanorp2040connect`|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0 `arduino:megaavr:uno2018:mode=on`|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0 `arduino:renesas_uno:unor4wifi`|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0 `arduino:samd:mkrwifi1010`|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0 `arduino:samd:nano_33_iot`|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0|0|0.0
Click for full report CSV ``` Board,examples/Central/LedControl
flash,%,examples/Central/LedControl
RAM for global variables,%,examples/Central/PeripheralExplorer
flash,%,examples/Central/PeripheralExplorer
RAM for global variables,%,examples/Central/Scan
flash,%,examples/Central/Scan
RAM for global variables,%,examples/Central/ScanCallback
flash,%,examples/Central/ScanCallback
RAM for global variables,%,examples/Central/SensorTagButton
flash,%,examples/Central/SensorTagButton
RAM for global variables,%,examples/Peripheral/Advertising/EnhancedAdvertising
flash,%,examples/Peripheral/Advertising/EnhancedAdvertising
RAM for global variables,%,examples/Peripheral/Advertising/RawDataAdvertising
flash,%,examples/Peripheral/Advertising/RawDataAdvertising
RAM for global variables,%,examples/Peripheral/BatteryMonitor
flash,%,examples/Peripheral/BatteryMonitor
RAM for global variables,%,examples/Peripheral/ButtonLED
flash,%,examples/Peripheral/ButtonLED
RAM for global variables,%,examples/Peripheral/CallbackLED
flash,%,examples/Peripheral/CallbackLED
RAM for global variables,%,examples/Peripheral/EncryptedBatteryMonitor
flash,%,examples/Peripheral/EncryptedBatteryMonitor
RAM for global variables,%,examples/Peripheral/LED
flash,%,examples/Peripheral/LED
RAM for global variables,% arduino:mbed_nano:nano33ble,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,64,0.01,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,64,0.01,0,0.0,0,0.0,0,0.0 arduino:mbed_nano:nanorp2040connect,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0 arduino:megaavr:uno2018:mode=on,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0 arduino:renesas_uno:unor4wifi,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0 arduino:samd:mkrwifi1010,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0 arduino:samd:nano_33_iot,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0 ```