From 8fb01be6cf33ffd20f9de935dec221fe11b0f609 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Wed, 25 May 2022 12:41:51 +1000 Subject: [PATCH] stm32/rfcore: Remove extra layer of buffering on BLE IPCC. Whole packets are now pushed up to the higher layer of the BLE stack, instead of buffering the packets so individual bytes can be requested. --- ports/stm32/mpbthciport.c | 35 +++++++++-------------------------- ports/stm32/mpconfigport.h | 6 ++++++ ports/stm32/rfcore.c | 19 ++++++++++++------- ports/stm32/rfcore.h | 4 +++- 4 files changed, 30 insertions(+), 34 deletions(-) diff --git a/ports/stm32/mpbthciport.c b/ports/stm32/mpbthciport.c index 89b04a540..d3ddb4042 100644 --- a/ports/stm32/mpbthciport.c +++ b/ports/stm32/mpbthciport.c @@ -24,6 +24,7 @@ * THE SOFTWARE. */ +#include #include "py/runtime.h" #include "py/mphal.h" #include "extmod/mpbthci.h" @@ -99,10 +100,6 @@ void mp_bluetooth_hci_poll_now_default(void) { #include #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_uart_init(uint32_t port, uint32_t baudrate) { (void)port; (void)baudrate; @@ -110,8 +107,6 @@ int mp_bluetooth_hci_uart_init(uint32_t port, uint32_t baudrate) { DEBUG_printf("mp_bluetooth_hci_uart_init (stm32 rfcore)\n"); rfcore_ble_init(); - hci_uart_rx_buf_cur = 0; - hci_uart_rx_buf_len = 0; // Start the HCI polling to process any initial events/packets. mp_bluetooth_hci_start_polling(); @@ -137,29 +132,17 @@ 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; +// Callback to forward data from rfcore to the bluetooth hci handler. +STATIC void mp_bluetooth_hci_uart_msg_cb(void *env, const uint8_t *buf, size_t len) { + mp_bluetooth_hci_uart_readchar_t handler = (mp_bluetooth_hci_uart_readchar_t)env; + for (size_t i = 0; i < len; ++i) { + handler(buf[i]); } - 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; - } +int mp_bluetooth_hci_uart_readpacket(mp_bluetooth_hci_uart_readchar_t handler) { + size_t len = rfcore_ble_check_msg(mp_bluetooth_hci_uart_msg_cb, (void *)handler); + return (len > 0) ? len : -1; } #else diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index 00b60b983..eb2344d07 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -384,6 +384,12 @@ static inline mp_uint_t disable_irq(void) { #define MICROPY_PY_BLUETOOTH_EXIT MICROPY_PY_PENDSV_EXIT #endif +#if defined(STM32WB) +#define MICROPY_PY_BLUETOOTH_HCI_READ_MODE MICROPY_PY_BLUETOOTH_HCI_READ_MODE_PACKET +#else +#define MICROPY_PY_BLUETOOTH_HCI_READ_MODE MICROPY_PY_BLUETOOTH_HCI_READ_MODE_BYTE +#endif + // We need an implementation of the log2 function which is not a macro #define MP_NEED_LOG2 (1) diff --git a/ports/stm32/rfcore.c b/ports/stm32/rfcore.c index 302f55d7e..55d6d17ad 100644 --- a/ports/stm32/rfcore.c +++ b/ports/stm32/rfcore.c @@ -105,7 +105,7 @@ typedef struct _tl_list_node_t { } tl_list_node_t; typedef struct _parse_hci_info_t { - int (*cb_fun)(void *, const uint8_t *, size_t); + rfcore_ble_msg_callback_t cb_fun; void *cb_env; bool was_hci_reset_evt; } parse_hci_info_t; @@ -408,11 +408,12 @@ STATIC size_t tl_parse_hci_msg(const uint8_t *buf, parse_hci_info_t *parse) { return len; } -STATIC void tl_process_msg(volatile tl_list_node_t *head, unsigned int ch, parse_hci_info_t *parse) { +STATIC size_t tl_process_msg(volatile tl_list_node_t *head, unsigned int ch, parse_hci_info_t *parse) { volatile tl_list_node_t *cur = head->next; bool added_to_free_queue = false; + size_t len = 0; while (cur != head) { - tl_parse_hci_msg((uint8_t *)cur->body, parse); + len += tl_parse_hci_msg((uint8_t *)cur->body, parse); volatile tl_list_node_t *next = tl_list_unlink(cur); @@ -436,13 +437,15 @@ STATIC void tl_process_msg(volatile tl_list_node_t *head, unsigned int ch, parse // Notify change in free pool. LL_C1_IPCC_SetFlag_CHx(IPCC, IPCC_CH_MM); } + return len; } // Only call this when IRQs are disabled on this channel. -STATIC void tl_check_msg(volatile tl_list_node_t *head, unsigned int ch, parse_hci_info_t *parse) { +STATIC size_t tl_check_msg(volatile tl_list_node_t *head, unsigned int ch, parse_hci_info_t *parse) { + size_t len = 0; if (LL_C2_IPCC_IsActiveFlag_CHx(IPCC, ch)) { // Process new data. - tl_process_msg(head, ch, parse); + len = tl_process_msg(head, ch, parse); // Clear receive channel (allows RF core to send more data to us). LL_C1_IPCC_ClearFlag_CHx(IPCC, ch); @@ -452,6 +455,7 @@ STATIC void tl_check_msg(volatile tl_list_node_t *head, unsigned int ch, parse_h LL_C1_IPCC_EnableReceiveChannel(IPCC, IPCC_CH_BLE); } } + return len; } STATIC void tl_hci_cmd(uint8_t *cmd, unsigned int ch, uint8_t hdr, uint16_t opcode, const uint8_t *buf, size_t len) { @@ -643,9 +647,9 @@ void rfcore_ble_hci_cmd(size_t len, const uint8_t *src) { LL_C1_IPCC_SetFlag_CHx(IPCC, ch); } -void rfcore_ble_check_msg(int (*cb)(void *, const uint8_t *, size_t), void *env) { +size_t rfcore_ble_check_msg(rfcore_ble_msg_callback_t cb, void *env) { parse_hci_info_t parse = { cb, env, false }; - tl_check_msg(&ipcc_mem_ble_evt_queue, IPCC_CH_BLE, &parse); + size_t len = tl_check_msg(&ipcc_mem_ble_evt_queue, IPCC_CH_BLE, &parse); // Intercept HCI_Reset events and reconfigure the controller following the reset if (parse.was_hci_reset_evt) { @@ -660,6 +664,7 @@ void rfcore_ble_check_msg(int (*cb)(void *, const uint8_t *, size_t), void *env) SWAP_UINT8(buf[4], buf[5]); tl_ble_hci_cmd_resp(HCI_OPCODE(OGF_VENDOR, OCF_WRITE_CONFIG), buf, 8); // set BDADDR } + return len; } // "level" is 0x00-0x1f, ranging from -40 dBm to +6 dBm (not linear). diff --git a/ports/stm32/rfcore.h b/ports/stm32/rfcore.h index fe29ac612..5c67f194e 100644 --- a/ports/stm32/rfcore.h +++ b/ports/stm32/rfcore.h @@ -28,11 +28,13 @@ #include +typedef void (*rfcore_ble_msg_callback_t)(void *, const uint8_t *, size_t); + 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 *, const uint8_t *, size_t), void *env); +size_t rfcore_ble_check_msg(rfcore_ble_msg_callback_t cb, void *env); void rfcore_ble_set_txpower(uint8_t level); void rfcore_start_flash_erase(void);