Description
Hardware:
Board: M5StickC ESP32-PICO Mini IoT Development Kit
Core Installation version: v3.2.3-14-gd3e562907
IDE name: Platform.io (Espressif32 v1.12.4, Arduino)
Flash Frequency: 40 Mhz
PSRAM enabled: No
Upload Speed: 1500000 Baud
Computer OS: Windows 10
Description:
During the development of a custom BLE gamepad, I experienced crashes including a backtrace after calling BLEAdvertising::start().
A deeper analysis using the 'nRF Connect for Mobile' app revealed that BLEAdvertising::start()
configures the advertisment data and the scan response data in such a way that the Bluetooth stack includes specific information, e.g. the appearance attribute, into both, the advertisment message and the scan response message.
A crash occurs when the total payload size of the scan response message exceeds 31 bytes. The problem can be avoided by improving the configuration of the scan response data in BLEAdvertising::start()
.
I have included a more detailed description and solution outline below the debug messages.
Sketch:
#include <Arduino.h>
#include <BLEDevice.h>
#include <BLEHIDDevice.h>
void setup() {
BLEDevice::init("ESP32 Wireless Joystick");
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->setAppearance(HID_GAMEPAD);
pAdvertising->start();
}
void loop() {
}
Debug Messages:
[I][BLEDevice.cpp:554] getAdvertising(): create advertising
[D][BLEDevice.cpp:556] getAdvertising(): get advertising
[V][BLEAdvertising.cpp:177] start(): >> start: customAdvData: 0, customScanResponseData: 0
[D][BLEAdvertising.cpp:196] start(): - no services advertised
[V][BLEAdvertising.cpp:237] sta
Sta: << start
smashing protect failure!
abort() was called at PC 0x400da634 on core 0
Backtrace: 0x40090f78:0x3ffd13f0 0x400911a9:0x3ffd1410 0x400da634:0x3ffd1430 0x4010c52d:0x3ffd1450 0x40132171:0x3ffd14b0 0x401327b1:0x3ffd14d0 0x4013d4ee:0x3ffd14f0 0x40112c4e:0x3ffd1510 0x4008dbb9:0x3ffd1540
#0 0x40090f78:0x3ffd13f0 in invoke_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c:707
#1 0x400911a9:0x3ffd1410 in abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c:707
#2 0x400da634:0x3ffd1430 in __stack_chk_fail at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/stack_check.c:36
#3 0x4010c52d:0x3ffd1450 in BTM_BleWriteScanRsp at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/bt/bluedroid/stack/btm/btm_ble_gap.c:1869
#4 0x40132171:0x3ffd14b0 in bta_dm_ble_set_scan_rsp at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/bt/bluedroid/bta/dm/bta_dm_act.c:4965
#5 0x401327b1:0x3ffd14d0 in bta_dm_sm_execute at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/bt/bluedroid/bta/dm/bta_dm_main.c:394
#6 0x4013d4ee:0x3ffd14f0 in bta_sys_event at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/bt/bluedroid/bta/sys/bta_sys_main.c:496
#7 0x40112c4e:0x3ffd1510 in btu_task_thread_handler at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/bt/bluedroid/stack/btu/btu_task.c:233
#8 0x4008dbb9:0x3ffd1540 in vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c:355 (discriminator 1)
Rebooting...
Analysis of the Problem:
The scan response is configured by the following lines of code in BLEAdvertising.cpp:
m_advData.set_scan_rsp = true;
m_advData.include_name = m_scanResp;
m_advData.include_txpower = m_scanResp;
Therein, m_advData
is the same struct that is used for the configuration of the advertisement data.
Therefore, the attributes 'Flags (type: 0x01)' and 'Apperance (type: 0x19)' are contained in both messages. This can be seen in the following screenshot from the 'nRF Connect for Mobile' app:
Note: For taking the screenshot, I used a device name with 22 characters, so the payload of the scan response message is 31 bytes.
Solution Outline:
I suggest to configure the scan response message using a separate struct (not a copy of 'm_advData'), so that all fields are zero-initialized, and only the fields 'set_scan_rsp', 'include_name', and 'include_txpower' are set to 'true'. Thus the redundant attributes in the scan response message are eliminated, and a device name with up to 29 characters is possible without causing a crash. This can be seen in the following screenshot:
(Note: The Bluetooth LE stack includes the Tx power attribute in the scan response only if the device name has at most 26 characters.)With the proposed solution, there is no loss of information because the other attributes such as 'Appearance' are still transmitted in the advertisement message.
Please let me know if you would like me to provide my solution proposal in a source code branch.