Skip to content

Commit

Permalink
drv/bluetooth_stm32_cc2640: fix broadcast lockup
Browse files Browse the repository at this point in the history
This changes the command to update advertising data on the Bluetooth
chip in the broadcast task to use HCI_LE_setAdvertisingData() instead of
GAP_updateAdvertisingData().

It appears there is some sort of memory leak or some such on the
Bluetooth chip that causes it to lock up if we call the vendor-specific
GAP_updateAdvertisingData() too many times. It appears that we can work
around this by calling the standard Bluetooth command
HCI_LE_setAdvertisingData() instead.

GAP_updateAdvertisingData() would result in two events being sent back
from the Bluetooth chip, a status event and a command complete event.
With HCI_LE_setAdvertisingData() we only get a command complete event
back - with the TI vendor-specific opcode as if we had called
GAP_updateAdvertisingData().

Fixes: pybricks/support#1095
  • Loading branch information
dlech committed Nov 4, 2023
1 parent 4d386be commit b301d97
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 9 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@

### Fixed
- Fixed Move Hub accelerometer not working since v3.3.0b5 ([support#1269]).
- Fixed Bluetooth chip locking up on Technic and City hubs when broadcasting ([[support#1095]]).

[support#1095]: https://github.com/pybricks/support/issues/1095
[support#1269]: https://github.com/pybricks/support/issues/1269

## [3.3.0b9] - 2023-10-26
Expand Down
12 changes: 12 additions & 0 deletions lib/ble5stack/central/hci.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@

#include <string.h>

#include "hci_tl.h"

HCI_StatusCodes_t HCI_readBdaddr(void)
Expand All @@ -15,3 +17,13 @@ HCI_StatusCodes_t HCI_LE_readAdvertisingChannelTxPower(void)
{
return HCI_sendHCICommand(HCI_LE_READ_ADVERTISING_CHANNEL_TX_POWER, NULL, 0);
}

HCI_StatusCodes_t HCI_LE_setAdvertisingData(uint8_t len, uint8_t *data)
{
uint8_t pData[32];

pData[0] = len;
memcpy(&pData[1], data, len);

return HCI_sendHCICommand(HCI_LE_SET_ADVERTISING_DATA, pData, len + 1);
}
1 change: 1 addition & 0 deletions lib/ble5stack/central/hci.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
HCI_StatusCodes_t HCI_readBdaddr(void);
HCI_StatusCodes_t HCI_readLocalVersionInfo(void);
HCI_StatusCodes_t HCI_LE_readAdvertisingChannelTxPower(void);
HCI_StatusCodes_t HCI_LE_setAdvertisingData(uint8_t len, uint8_t *data);

#endif // HCI_H
1 change: 1 addition & 0 deletions lib/ble5stack/central/hci_tl.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@

// Low energy commands
#define HCI_LE_READ_ADVERTISING_CHANNEL_TX_POWER 0x2007 //!< opcode of @ref HCI_LE_readAdvertisingChannelTxPower
#define HCI_LE_SET_ADVERTISING_DATA 0x2008

/* HCI Status return types */
typedef enum
Expand Down
15 changes: 6 additions & 9 deletions lib/pbio/drv/bluetooth/bluetooth_stm32_cc2640.c
Original file line number Diff line number Diff line change
Expand Up @@ -827,16 +827,13 @@ static PT_THREAD(broadcast_task(struct pt *pt, pbio_task_t *task)) {
PT_EXIT(pt);
}

// HACK: calling GAP_updateAdvertisingData() repeatedly will cause the
// Bluetooth chips on Technic and City hubs to eventually lock up. So we
// call the standard Bluetooth command instead. We still get the vendor-
// specific command complete event as if we had called the TI command (but
// not the command status).
PT_WAIT_WHILE(pt, write_xfer_size);
GAP_updateAdvertisingData(GAP_AD_TYPE_ADVERTISEMENT_DATA, value->size, value->data);
PT_WAIT_UNTIL(pt, hci_command_status);

if (read_buf[8] != bleSUCCESS) {
task->status = ble_error_to_pbio_error(read_buf[8]);
PT_EXIT(pt);
}

// wait for GAP update advert data done event
HCI_LE_setAdvertisingData(value->size, value->data);
PT_WAIT_UNTIL(pt, hci_command_complete);

if (!is_broadcasting) {
Expand Down

0 comments on commit b301d97

Please sign in to comment.