Skip to content

Commit ed14435

Browse files
jimmodpgeorge
authored andcommitted
extmod/modbluetooth: Refactor stack/hci/driver/port bindings.
Previously the interaction between the different layers of the Bluetooth stack was different on each port and each stack. This commit defines common interfaces between them and implements them for cyw43, btstack, nimble, stm32, unix.
1 parent e46aac2 commit ed14435

32 files changed

+849
-341
lines changed

drivers/cyw43/cywbt.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,19 @@
3131
#include "py/mphal.h"
3232
#include "pin_static_af.h"
3333
#include "uart.h"
34-
#include "extmod/modbluetooth_hci.h"
34+
#include "extmod/mpbthci.h"
3535

3636
#if MICROPY_PY_NETWORK_CYW43
3737

3838
extern const char fw_4343WA1_7_45_98_50_start;
3939
#define CYWBT_FW_ADDR (&fw_4343WA1_7_45_98_50_start + 749 * 512 + 29 * 256)
4040

41+
// Provided by the port.
42+
extern pyb_uart_obj_t mp_bluetooth_hci_uart_obj;
43+
44+
// Provided by the port, and also possibly shared with the stack.
45+
extern uint8_t mp_bluetooth_hci_cmd_buf[4 + 256];
46+
4147
/******************************************************************************/
4248
// CYW BT HCI low-level driver
4349

@@ -168,10 +174,6 @@ int mp_bluetooth_hci_controller_init(void) {
168174
mp_hal_pin_config(pyb_pin_WL_GPIO_4, MP_HAL_PIN_MODE_OUTPUT, MP_HAL_PIN_PULL_NONE, 0); // RF-switch power
169175
mp_hal_pin_high(pyb_pin_WL_GPIO_4); // Turn the RF-switch on
170176

171-
return 0;
172-
}
173-
174-
int mp_bluetooth_hci_controller_activate(void) {
175177
uint8_t buf[256];
176178

177179
mp_hal_pin_low(pyb_pin_BT_REG_ON);
@@ -219,7 +221,7 @@ int mp_bluetooth_hci_controller_activate(void) {
219221
return 0;
220222
}
221223

222-
int mp_bluetooth_hci_controller_deactivate(void) {
224+
int mp_bluetooth_hci_controller_deinit(void) {
223225
mp_hal_pin_low(pyb_pin_BT_REG_ON);
224226

225227
return 0;

extmod/btstack/btstack.mk

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,17 @@ CFLAGS += $(shell pkg-config libusb-1.0 --cflags)
3838
LDFLAGS += $(shell pkg-config libusb-1.0 --libs)
3939
endif
4040

41+
ifeq ($(MICROPY_BLUETOOTH_BTSTACK_H4),1)
42+
SRC_BTSTACK += \
43+
lib/btstack/src/hci_transport_h4.c \
44+
lib/btstack/chipset/zephyr/btstack_chipset_zephyr.c
45+
46+
EXTMOD_SRC_C += \
47+
extmod/btstack/btstack_hci_uart.c \
48+
49+
CFLAGS_MOD += -DMICROPY_BLUETOOTH_BTSTACK_H4=1
50+
endif
51+
4152
ifeq ($(MICROPY_BLUETOOTH_BTSTACK_ENABLE_CLASSIC),1)
4253
include $(BTSTACK_DIR)/src/classic/Makefile.inc
4354
SRC_BTSTACK += \

extmod/btstack/btstack_config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// #define ENABLE_CLASSIC
99
#define ENABLE_LE_DATA_CHANNELS
1010
// #define ENABLE_LOG_INFO
11+
// #define ENABLE_LOG_DEBUG
1112
#define ENABLE_LOG_ERROR
1213

1314
// BTstack configuration. buffers, sizes, ...

ports/stm32/btstack.c renamed to extmod/btstack/btstack_hci_uart.c

Lines changed: 22 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* The MIT License (MIT)
55
*
66
* Copyright (c) 2020 Damien P. George
7+
* Copyright (c) 2020 Jim Mussared
78
*
89
* Permission is hereby granted, free of charge, to any person obtaining a copy
910
* of this software and associated documentation files (the "Software"), to deal
@@ -31,12 +32,14 @@
3132
#if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_BTSTACK
3233

3334
#include "lib/btstack/src/btstack.h"
34-
#include "lib/btstack/platform/embedded/btstack_run_loop_embedded.h"
35-
#include "lib/btstack/platform/embedded/hal_cpu.h"
36-
#include "lib/btstack/platform/embedded/hal_time_ms.h"
3735

38-
#include "extmod/modbluetooth_hci.h"
39-
#include "extmod/btstack/modbluetooth_btstack.h"
36+
#include "extmod/mpbthci.h"
37+
#include "extmod/btstack/btstack_hci_uart.h"
38+
39+
#include "mpbtstackport.h"
40+
41+
// Implements a btstack btstack_uart_block_t on top of the mphciuart.h
42+
// interface to an HCI UART provided by the port.
4043

4144
// We pass the bytes directly to the UART during a send, but then notify btstack in the next poll.
4245
STATIC bool send_done;
@@ -48,42 +51,29 @@ STATIC size_t recv_len;
4851
STATIC size_t recv_idx;
4952
STATIC void (*recv_handler)(void);
5053

51-
// The IRQ functionality in btstack_run_loop_embedded.c is not used, so the
52-
// following three functions are empty.
53-
54-
void hal_cpu_disable_irqs(void) {
55-
}
56-
57-
void hal_cpu_enable_irqs(void) {
58-
}
59-
60-
void hal_cpu_enable_irqs_and_sleep(void) {
61-
}
62-
63-
uint32_t hal_time_ms(void) {
64-
return mp_hal_ticks_ms();
65-
}
66-
6754
STATIC int btstack_uart_init(const btstack_uart_config_t *uart_config) {
55+
(void)uart_config;
56+
6857
send_done = false;
6958
recv_len = 0;
7059
recv_idx = 0;
7160
recv_handler = NULL;
7261
send_handler = NULL;
7362

74-
// Set up the UART periperhal.
75-
mp_bluetooth_hci_uart_init(MICROPY_HW_BLE_UART_ID);
63+
// Set up the UART peripheral, attach IRQ and power up the HCI controller.
64+
// We haven't been told the baud rate yet, so defer that until btstack_uart_set_baudrate.
65+
mp_bluetooth_hci_uart_init(MICROPY_HW_BLE_UART_ID, 0);
66+
mp_bluetooth_hci_controller_init();
7667

7768
return 0;
7869
}
7970

8071
STATIC int btstack_uart_open(void) {
81-
// Attach IRQ and power up the HCI controller.
82-
mp_bluetooth_hci_uart_activate();
8372
return 0;
8473
}
8574

8675
STATIC int btstack_uart_close(void) {
76+
mp_bluetooth_hci_controller_deinit();
8777
return 0;
8878
}
8979

@@ -101,10 +91,12 @@ STATIC int btstack_uart_set_baudrate(uint32_t baudrate) {
10191
}
10292

10393
STATIC int btstack_uart_set_parity(int parity) {
94+
(void)parity;
10495
return 0;
10596
}
10697

10798
STATIC int btstack_uart_set_flowcontrol(int flowcontrol) {
99+
(void)flowcontrol;
108100
return 0;
109101
}
110102

@@ -123,14 +115,16 @@ STATIC int btstack_uart_get_supported_sleep_modes(void) {
123115
}
124116

125117
STATIC void btstack_uart_set_sleep(btstack_uart_sleep_mode_t sleep_mode) {
118+
(void)sleep_mode;
126119
// printf("btstack_uart_set_sleep %u\n", sleep_mode);
127120
}
128121

129122
STATIC void btstack_uart_set_wakeup_handler(void (*wakeup_handler)(void)) {
123+
(void)wakeup_handler;
130124
// printf("btstack_uart_set_wakeup_handler\n");
131125
}
132126

133-
STATIC const btstack_uart_block_t btstack_uart_block = {
127+
const btstack_uart_block_t mp_bluetooth_btstack_hci_uart_block = {
134128
&btstack_uart_init,
135129
&btstack_uart_open,
136130
&btstack_uart_close,
@@ -146,15 +140,9 @@ STATIC const btstack_uart_block_t btstack_uart_block = {
146140
&btstack_uart_set_wakeup_handler,
147141
};
148142

149-
STATIC const hci_transport_config_uart_t hci_transport_config_uart = {
150-
HCI_TRANSPORT_CONFIG_UART,
151-
MICROPY_HW_BLE_UART_BAUDRATE,
152-
3000000,
153-
0,
154-
NULL,
155-
};
143+
void mp_bluetooth_btstack_hci_uart_process(void) {
144+
bool host_wake = mp_bluetooth_hci_controller_woken();
156145

157-
STATIC void btstack_uart_process(void) {
158146
if (send_done) {
159147
// If we'd done a TX in the last interval, notify btstack that it's complete.
160148
send_done = false;
@@ -176,48 +164,10 @@ STATIC void btstack_uart_process(void) {
176164
}
177165
}
178166
}
179-
}
180-
181-
void mp_bluetooth_hci_poll(void) {
182-
if (mp_bluetooth_btstack_state == MP_BLUETOOTH_BTSTACK_STATE_OFF) {
183-
return;
184-
}
185167

186-
// Process uart data.
187-
bool host_wake = mp_bluetooth_hci_controller_woken();
188-
btstack_uart_process();
189168
if (host_wake) {
190169
mp_bluetooth_hci_controller_sleep_maybe();
191170
}
192-
193-
// Call the BTstack run loop.
194-
btstack_run_loop_embedded_execute_once();
195-
}
196-
197-
void mp_bluetooth_btstack_port_init(void) {
198-
static bool run_loop_init = false;
199-
if (!run_loop_init) {
200-
run_loop_init = true;
201-
btstack_run_loop_init(btstack_run_loop_embedded_get_instance());
202-
} else {
203-
btstack_run_loop_embedded_get_instance()->init();
204-
}
205-
206-
// hci_dump_open(NULL, HCI_DUMP_STDOUT);
207-
const hci_transport_t *transport = hci_transport_h4_instance(&btstack_uart_block);
208-
hci_init(transport, &hci_transport_config_uart);
209-
210-
// TODO: Probably not necessary for BCM (we have our own firmware loader),
211-
// but might be worth investigating for other controllers in the future.
212-
// hci_set_chipset(btstack_chipset_bcm_instance());
213-
}
214-
215-
void mp_bluetooth_btstack_port_deinit(void) {
216-
hci_power_control(HCI_POWER_OFF);
217-
}
218-
219-
void mp_bluetooth_btstack_port_start(void) {
220-
hci_power_control(HCI_POWER_ON);
221171
}
222172

223173
#endif // MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_BTSTACK

extmod/nimble/nimble/nimble_hci_uart.h renamed to extmod/btstack/btstack_hci_uart.h

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
*
44
* The MIT License (MIT)
55
*
6-
* Copyright (c) 2019 Damien P. George
6+
* Copyright (c) 2020 Damien P. George
7+
* Copyright (c) 2020 Jim Mussared
78
*
89
* Permission is hereby granted, free of charge, to any person obtaining a copy
910
* of this software and associated documentation files (the "Software"), to deal
@@ -23,18 +24,16 @@
2324
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2425
* THE SOFTWARE.
2526
*/
26-
#ifndef MICROPY_INCLUDED_EXTMOD_NIMBLE_NIMBLE_NIMBLE_HCI_UART_H
27-
#define MICROPY_INCLUDED_EXTMOD_NIMBLE_NIMBLE_NIMBLE_HCI_UART_H
2827

29-
// Extensions to extmod/modbluetooth_hci.h specific to NimBLE.
28+
#ifndef MICROPY_INCLUDED_EXTMOD_BTSTACK_HCI_UART_H
29+
#define MICROPY_INCLUDED_EXTMOD_BTSTACK_HCI_UART_H
3030

31-
#include "extmod/nimble/hal/hal_uart.h"
31+
#include "lib/btstack/src/btstack.h"
3232

33-
// Helpers called from ports.
34-
void mp_bluetooth_nimble_hci_uart_process(void);
33+
// --- Used by the port to create the HCI transport ---------------------------
34+
extern const btstack_uart_block_t mp_bluetooth_btstack_hci_uart_block;
3535

36-
// Must be provided by the port.
37-
void mp_bluetooth_nimble_hci_uart_rx(hal_uart_rx_cb_t rx_cb, void *rx_arg);
38-
void mp_bluetooth_nimble_hci_uart_tx_strn(const char *str, uint len);
36+
// --- Called by the MicroPython port when UART data is available -------------
37+
void mp_bluetooth_btstack_hci_uart_process(void);
3938

40-
#endif // MICROPY_INCLUDED_EXTMOD_NIMBLE_NIMBLE_NIMBLE_HCI_UART_H
39+
#endif // MICROPY_INCLUDED_EXTMOD_BTSTACK_MODBLUETOOTH_BTSTACK_H

extmod/btstack/modbluetooth_btstack.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ STATIC const uint16_t BTSTACK_GAP_DEVICE_NAME_HANDLE = 3;
5353

5454
volatile int mp_bluetooth_btstack_state = MP_BLUETOOTH_BTSTACK_STATE_OFF;
5555

56+
#define ERRNO_BLUETOOTH_NOT_ACTIVE MP_ENODEV
57+
5658
STATIC int btstack_error_to_errno(int err) {
5759
DEBUG_printf(" --> btstack error: %d\n", err);
5860
if (err == ERROR_CODE_SUCCESS) {
@@ -300,6 +302,9 @@ STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t
300302
if (state == HCI_STATE_WORKING) {
301303
// Signal that initialisation has completed.
302304
mp_bluetooth_btstack_state = MP_BLUETOOTH_BTSTACK_STATE_ACTIVE;
305+
} else if (state == HCI_STATE_HALTING) {
306+
// Signal that de-initialisation has begun.
307+
mp_bluetooth_btstack_state = MP_BLUETOOTH_BTSTACK_STATE_HALTING;
303308
} else if (state == HCI_STATE_OFF) {
304309
// Signal that de-initialisation has completed.
305310
mp_bluetooth_btstack_state = MP_BLUETOOTH_BTSTACK_STATE_OFF;

extmod/btstack/modbluetooth_btstack.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ enum {
5656
MP_BLUETOOTH_BTSTACK_STATE_OFF,
5757
MP_BLUETOOTH_BTSTACK_STATE_STARTING,
5858
MP_BLUETOOTH_BTSTACK_STATE_ACTIVE,
59+
MP_BLUETOOTH_BTSTACK_STATE_HALTING,
5960
MP_BLUETOOTH_BTSTACK_STATE_TIMEOUT,
6061
};
6162

extmod/mpbthci.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2020 Jim Mussared
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
// Default definitions in case a controller doesn't implement this.
28+
29+
#include "py/mphal.h"
30+
31+
#if MICROPY_PY_BLUETOOTH
32+
33+
#define DEBUG_printf(...) // printf(__VA_ARGS__)
34+
35+
#include "extmod/mpbthci.h"
36+
37+
38+
#endif // MICROPY_PY_BLUETOOTH

extmod/modbluetooth_hci.h renamed to extmod/mpbthci.h

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,15 @@
2424
* THE SOFTWARE.
2525
*/
2626

27-
#ifndef MICROPY_INCLUDED_EXTMOD_MODBLUETOOTH_HCI_H
28-
#define MICROPY_INCLUDED_EXTMOD_MODBLUETOOTH_HCI_H
27+
#ifndef MICROPY_INCLUDED_EXTMOD_MPBTHCI_H
28+
#define MICROPY_INCLUDED_EXTMOD_MPBTHCI_H
2929

30-
#include "uart.h"
30+
// --- Optionally can be implemented by the driver. ---------------------------
3131

32-
// Optionally can be implemented by the driver.
32+
// Start/stop the HCI controller.
33+
// Requires the UART to this HCI controller is available.
3334
int mp_bluetooth_hci_controller_init(void);
34-
int mp_bluetooth_hci_controller_activate(void);
35-
int mp_bluetooth_hci_controller_deactivate(void);
35+
int mp_bluetooth_hci_controller_deinit(void);
3636

3737
// Tell the controller to go to sleep (e.g. on RX if we don't think we're expecting anything more).
3838
int mp_bluetooth_hci_controller_sleep_maybe(void);
@@ -41,16 +41,11 @@ bool mp_bluetooth_hci_controller_woken(void);
4141
// Wake up the controller (e.g. we're about to TX).
4242
int mp_bluetooth_hci_controller_wakeup(void);
4343

44-
// Storage and bindings that need to be implemented by the port.
45-
// These are used by the stack bindings (e.g. nimble/hal_uart.c)
46-
// as well as potentially the driver (e.g. cywbt.c).
47-
extern uint8_t mp_bluetooth_hci_cmd_buf[4 + 256];
48-
extern pyb_uart_obj_t mp_bluetooth_hci_uart_obj;
49-
50-
int mp_bluetooth_hci_uart_init(uint32_t port);
51-
int mp_bluetooth_hci_uart_activate(void);
44+
// --- Bindings that need to be implemented by the port. ----------------------
45+
int mp_bluetooth_hci_uart_init(uint32_t port, uint32_t baudrate);
46+
int mp_bluetooth_hci_uart_deinit(void);
5247
int mp_bluetooth_hci_uart_set_baudrate(uint32_t baudrate);
5348
int mp_bluetooth_hci_uart_readchar(void);
5449
int mp_bluetooth_hci_uart_write(const uint8_t *buf, size_t len);
5550

56-
#endif // MICROPY_INCLUDED_EXTMOD_MODBLUETOOTH_HCI_H
51+
#endif // MICROPY_INCLUDED_EXTMOD_MPBTHCI_H

0 commit comments

Comments
 (0)