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);