Skip to content

Commit 1dabf12

Browse files
committed
sys/bluetooth: fix UART service not working after reconnect
If Bluetooth disconnected while sending data via the Nordic UART service, then that service would no longer work after reconnecting. This happened because of a combination of: 1. The current message never had the is_queued flag cleared because it was no longer in the queue and the send_done callback as never called. 2. Some of the Bluetooth drivers did not reset internal state properly after "power off" of the chip (contiki process stopped abruptly). This is fixed by keeping the active message in the queue until either send_done() or reset_all() is called. This guarantees that the message will always be properly cleaned up. The affected drivers are also fixed. Issue: pybricks/support#325
1 parent e334cea commit 1dabf12

File tree

5 files changed

+16
-12
lines changed

5 files changed

+16
-12
lines changed

lib/pbio/drv/bluetooth/bluetooth_btstack.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ static void pybricks_can_send(void *context) {
6363
pbdrv_bluetooth_send_context_t *send = context;
6464

6565
pybricks_service_server_send(pybricks_con_handle, send->data, send->size);
66-
send->done(send);
66+
send->done();
6767
}
6868

6969
static void pybricks_data_received(hci_con_handle_t tx_con_handle, const uint8_t *data, uint16_t size) {
@@ -80,7 +80,7 @@ static void nordic_can_send(void *context) {
8080
pbdrv_bluetooth_send_context_t *send = context;
8181

8282
nordic_spp_service_server_send(uart_con_handle, send->data, send->size);
83-
send->done(send);
83+
send->done();
8484
}
8585

8686
static void nordic_spp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {

lib/pbio/drv/bluetooth/bluetooth_stm32_bluenrg.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ static PT_THREAD(send_value_notification(struct pt *pt, void *context))
308308
}
309309

310310
done:
311-
send->done(send);
311+
send->done();
312312

313313
PT_END(pt);
314314
}
@@ -761,8 +761,11 @@ PROCESS_THREAD(pbdrv_bluetooth_spi_process, ev, data) {
761761
static struct pt child_pt;
762762

763763
PROCESS_EXITHANDLER({
764+
spi_disable_cs();
764765
bluetooth_reset(true);
765-
bluetooth_ready = false;
766+
bluetooth_ready = pybricks_notify_en = uart_tx_notify_en = false;
767+
conn_handle = 0;
768+
PROCESS_EXIT();
766769
});
767770

768771
PROCESS_BEGIN();

lib/pbio/drv/bluetooth/bluetooth_stm32_cc2640.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ static PT_THREAD(send_value_notification(struct pt *pt, void *context))
363363
}
364364

365365
done:
366-
send->done(send);
366+
send->done();
367367

368368
PT_END(pt);
369369
}
@@ -1149,7 +1149,9 @@ PROCESS_THREAD(pbdrv_bluetooth_spi_process, ev, data) {
11491149
PROCESS_EXITHANDLER({
11501150
spi_set_mrdy(false);
11511151
bluetooth_reset(RESET_STATE_OUT_LOW);
1152-
bluetooth_ready = false;
1152+
bluetooth_ready = pybricks_notify_en = uart_tx_notify_en = false;
1153+
conn_handle = NO_CONNECTION;
1154+
PROCESS_EXIT();
11531155
});
11541156

11551157
PROCESS_BEGIN();

lib/pbio/include/pbdrv/bluetooth.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,8 @@ typedef void (*pbdrv_bluetooth_on_event_t)(void);
3737

3838
/**
3939
* Callback that is called when sending a notification is done.
40-
* @param context [in] The context that was given to pbdrv_bluetooth_send().
4140
*/
42-
typedef void (*pbdrv_bluetooth_send_done_t)(pbdrv_bluetooth_send_context_t *context);
41+
typedef void (*pbdrv_bluetooth_send_done_t)(void);
4342

4443
/**
4544
* Callback that is called when BLE characteristic is written to.

lib/pbio/sys/bluetooth.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,8 @@ static void handle_receive(pbdrv_bluetooth_connection_t connection, const uint8_
160160
}
161161
}
162162

163-
static void send_done(pbdrv_bluetooth_send_context_t *context) {
164-
send_msg_t *msg = PBIO_CONTAINER_OF(context, send_msg_t, context);
163+
static void send_done(void) {
164+
send_msg_t *msg = list_pop(send_queue);
165165

166166
if (msg->context.connection == PBDRV_BLUETOOTH_CONNECTION_UART && lwrb_get_full(&uart_tx_ring)) {
167167
// If there is more buffered data to send, put the message back in the queue
@@ -270,8 +270,8 @@ PROCESS_THREAD(pbsys_bluetooth_process, ev, data) {
270270
}
271271

272272
if (!send_busy) {
273-
send_msg_t *msg = list_pop(send_queue);
274-
// msg->is_queued is set to false in send_done callback rather than here
273+
// msg is removed from queue in send_done callback rather than here
274+
send_msg_t *msg = list_head(send_queue);
275275
if (msg) {
276276
msg->context.done = send_done;
277277
if (msg->context.connection == PBDRV_BLUETOOTH_CONNECTION_UART) {

0 commit comments

Comments
 (0)