summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2020-03-10 01:47:16 +1100
committerDamien George <damien.p.george@gmail.com>2020-03-10 01:53:42 +1100
commite965363b6b66785ff088c4e998a7e80783bdd97c (patch)
tree715ea19688b298c1966cf7291d566b3952425a89
parentd7259f6b1c746d352c658bf94a4e0d4c92712ba5 (diff)
stm32: Refactor Bluetooth HCI RX to be independent of transport layer.
Now all HCI specific code (eg UART vs WB55 internal messaging) is confined to modbluetooth_hci.c.
-rw-r--r--extmod/modbluetooth_hci.h1
-rw-r--r--extmod/nimble/nimble/npl_os.c4
-rw-r--r--ports/stm32/btstack.c5
-rw-r--r--ports/stm32/modbluetooth_hci.c42
-rw-r--r--ports/stm32/nimble.c23
-rw-r--r--ports/stm32/rfcore.c15
-rw-r--r--ports/stm32/rfcore.h2
7 files changed, 60 insertions, 32 deletions
diff --git a/extmod/modbluetooth_hci.h b/extmod/modbluetooth_hci.h
index 6d44761a4..d6b432d22 100644
--- a/extmod/modbluetooth_hci.h
+++ b/extmod/modbluetooth_hci.h
@@ -50,6 +50,7 @@ extern pyb_uart_obj_t mp_bluetooth_hci_uart_obj;
int mp_bluetooth_hci_uart_init(uint32_t port);
int mp_bluetooth_hci_uart_activate(void);
int mp_bluetooth_hci_uart_set_baudrate(uint32_t baudrate);
+int mp_bluetooth_hci_uart_readchar(void);
int mp_bluetooth_hci_uart_write(const uint8_t *buf, size_t len);
#endif // MICROPY_INCLUDED_EXTMOD_MODBLUETOOTH_HCI_H
diff --git a/extmod/nimble/nimble/npl_os.c b/extmod/nimble/nimble/npl_os.c
index 57ab689e6..620dcb0ae 100644
--- a/extmod/nimble/nimble/npl_os.c
+++ b/extmod/nimble/nimble/npl_os.c
@@ -235,7 +235,11 @@ ble_npl_error_t ble_npl_sem_pend(struct ble_npl_sem *sem, ble_npl_time_t timeout
if (sem->count == 0) {
uint32_t t0 = mp_hal_ticks_ms();
while (sem->count == 0 && mp_hal_ticks_ms() - t0 < timeout) {
+ // This function may be called at thread-level, so execute
+ // mp_bluetooth_nimble_hci_uart_process at raised priority.
+ MICROPY_PY_BLUETOOTH_ENTER
mp_bluetooth_nimble_hci_uart_process();
+ MICROPY_PY_BLUETOOTH_EXIT
if (sem->count != 0) {
break;
}
diff --git a/ports/stm32/btstack.c b/ports/stm32/btstack.c
index f7669d1fc..cbb15a86c 100644
--- a/ports/stm32/btstack.c
+++ b/ports/stm32/btstack.c
@@ -165,8 +165,9 @@ STATIC void btstack_uart_process(void) {
// Append any new bytes to the recv buffer, notifying bstack if we've got
// the number of bytes it was looking for.
- while (uart_rx_any(&mp_bluetooth_hci_uart_obj) && recv_idx < recv_len) {
- recv_buf[recv_idx++] = uart_rx_char(&mp_bluetooth_hci_uart_obj);
+ int chr;
+ while (recv_idx < recv_len && (chr = mp_bluetooth_hci_uart_readchar()) >= 0) {
+ recv_buf[recv_idx++] = chr;
if (recv_idx == recv_len) {
recv_idx = 0;
recv_len = 0;
diff --git a/ports/stm32/modbluetooth_hci.c b/ports/stm32/modbluetooth_hci.c
index c6937b2b2..4e016eae8 100644
--- a/ports/stm32/modbluetooth_hci.c
+++ b/ports/stm32/modbluetooth_hci.c
@@ -54,8 +54,13 @@ void mp_bluetooth_hci_poll_wrapper(uint32_t ticks_ms) {
/******************************************************************************/
// HCI over IPCC
+#include <string.h>
#include "rfcore.h"
+STATIC uint16_t hci_uart_rx_buf_cur;
+STATIC uint16_t hci_uart_rx_buf_len;
+STATIC uint8_t hci_uart_rx_buf_data[256];
+
int mp_bluetooth_hci_controller_deactivate(void) {
return 0;
}
@@ -79,6 +84,8 @@ int mp_bluetooth_hci_uart_init(uint32_t port) {
int mp_bluetooth_hci_uart_activate(void) {
rfcore_ble_init();
+ hci_uart_rx_buf_cur = 0;
+ hci_uart_rx_buf_len = 0;
return 0;
}
@@ -94,6 +101,31 @@ int mp_bluetooth_hci_uart_write(const uint8_t *buf, size_t len) {
return 0;
}
+// Callback to copy data into local hci_uart_rx_buf_data buffer for subsequent use.
+STATIC int mp_bluetooth_hci_uart_msg_cb(void *env, const uint8_t *buf, size_t len) {
+ (void)env;
+ if (hci_uart_rx_buf_len + len > MP_ARRAY_SIZE(hci_uart_rx_buf_data)) {
+ len = MP_ARRAY_SIZE(hci_uart_rx_buf_data) - hci_uart_rx_buf_len;
+ }
+ memcpy(hci_uart_rx_buf_data + hci_uart_rx_buf_len, buf, len);
+ hci_uart_rx_buf_len += len;
+ return 0;
+}
+
+int mp_bluetooth_hci_uart_readchar(void) {
+ if (hci_uart_rx_buf_cur >= hci_uart_rx_buf_len) {
+ hci_uart_rx_buf_cur = 0;
+ hci_uart_rx_buf_len = 0;
+ rfcore_ble_check_msg(mp_bluetooth_hci_uart_msg_cb, NULL);
+ }
+
+ if (hci_uart_rx_buf_cur < hci_uart_rx_buf_len) {
+ return hci_uart_rx_buf_data[hci_uart_rx_buf_cur++];
+ } else {
+ return -1;
+ }
+}
+
#else
/******************************************************************************/
@@ -153,6 +185,16 @@ int mp_bluetooth_hci_uart_write(const uint8_t *buf, size_t len) {
return 0;
}
+// This function expects the controller to be in the wake state via a previous call
+// to mp_bluetooth_hci_controller_woken.
+int mp_bluetooth_hci_uart_readchar(void) {
+ if (uart_rx_any(&mp_bluetooth_hci_uart_obj)) {
+ return uart_rx_char(&mp_bluetooth_hci_uart_obj);
+ } else {
+ return -1;
+ }
+}
+
#endif // defined(STM32WB)
#endif // MICROPY_PY_BLUETOOTH
diff --git a/ports/stm32/nimble.c b/ports/stm32/nimble.c
index ff78a0a1a..1f4aa4b2c 100644
--- a/ports/stm32/nimble.c
+++ b/ports/stm32/nimble.c
@@ -67,28 +67,13 @@ void mp_bluetooth_nimble_port_start(void) {
ble_hs_start();
}
-#if defined(STM32WB)
-
-#include "rfcore.h"
-
-void mp_bluetooth_nimble_hci_uart_rx(hal_uart_rx_cb_t rx_cb, void *rx_arg) {
- // Protect in case it's called from ble_npl_sem_pend at thread-level
- MICROPY_PY_LWIP_ENTER
- rfcore_ble_check_msg(rx_cb, rx_arg);
- MICROPY_PY_LWIP_EXIT
-}
-
-#else
-
-#include "uart.h"
-
void mp_bluetooth_nimble_hci_uart_rx(hal_uart_rx_cb_t rx_cb, void *rx_arg) {
bool host_wake = mp_bluetooth_hci_controller_woken();
- while (uart_rx_any(&mp_bluetooth_hci_uart_obj)) {
- uint8_t data = uart_rx_char(&mp_bluetooth_hci_uart_obj);
+ int chr;
+ while ((chr = mp_bluetooth_hci_uart_readchar()) >= 0) {
//printf("UART RX: %02x\n", data);
- rx_cb(rx_arg, data);
+ rx_cb(rx_arg, chr);
}
if (host_wake) {
@@ -96,8 +81,6 @@ void mp_bluetooth_nimble_hci_uart_rx(hal_uart_rx_cb_t rx_cb, void *rx_arg) {
}
}
-#endif // defined(STM32WB)
-
void mp_bluetooth_nimble_hci_uart_tx_strn(const char *str, uint len) {
mp_bluetooth_hci_uart_write((const uint8_t *)str, len);
}
diff --git a/ports/stm32/rfcore.c b/ports/stm32/rfcore.c
index 822152765..9b513839c 100644
--- a/ports/stm32/rfcore.c
+++ b/ports/stm32/rfcore.c
@@ -56,7 +56,7 @@ typedef struct _tl_list_node_t {
} tl_list_node_t;
typedef struct _parse_hci_info_t {
- int (*cb_fun)(void *, uint8_t);
+ int (*cb_fun)(void *, const uint8_t *, size_t);
void *cb_env;
bool was_hci_reset_evt;
} parse_hci_info_t;
@@ -190,9 +190,7 @@ STATIC void tl_parse_hci_msg(const uint8_t *buf, parse_hci_info_t *parse) {
// Standard BT HCI ACL packet
kind = "HCI_ACL";
if (parse != NULL) {
- for (size_t i = 0; i < len; ++i) {
- parse->cb_fun(parse->cb_env, buf[i]);
- }
+ parse->cb_fun(parse->cb_env, buf, len);
}
break;
}
@@ -205,12 +203,11 @@ STATIC void tl_parse_hci_msg(const uint8_t *buf, parse_hci_info_t *parse) {
len -= 1;
fix = true;
}
- for (size_t i = 0; i < len; ++i) {
- parse->cb_fun(parse->cb_env, buf[i]);
- }
+ parse->cb_fun(parse->cb_env, buf, len);
if (fix) {
len += 1;
- parse->cb_fun(parse->cb_env, 0x00); // success
+ uint8_t data = 0x00; // success
+ parse->cb_fun(parse->cb_env, &data, 1);
}
// Check for successful HCI_Reset event
parse->was_hci_reset_evt = buf[1] == 0x0e && buf[2] == 0x04 && buf[3] == 0x01
@@ -403,7 +400,7 @@ void rfcore_ble_hci_cmd(size_t len, const uint8_t *src) {
IPCC->C1SCR = ch << 16;
}
-void rfcore_ble_check_msg(int (*cb)(void *, uint8_t), void *env) {
+void rfcore_ble_check_msg(int (*cb)(void *, const uint8_t *, size_t), void *env) {
parse_hci_info_t parse = { cb, env, false };
tl_check_msg(&ipcc_mem_ble_evt_queue, IPCC_CH_BLE, &parse);
diff --git a/ports/stm32/rfcore.h b/ports/stm32/rfcore.h
index 8a0407573..138c438f1 100644
--- a/ports/stm32/rfcore.h
+++ b/ports/stm32/rfcore.h
@@ -32,6 +32,6 @@ void rfcore_init(void);
void rfcore_ble_init(void);
void rfcore_ble_hci_cmd(size_t len, const uint8_t *src);
-void rfcore_ble_check_msg(int (*cb)(void *, uint8_t), void *env);
+void rfcore_ble_check_msg(int (*cb)(void *, const uint8_t *, size_t), void *env);
#endif // MICROPY_INCLUDED_STM32_RFCORE_H