From a64121b0d48ccd2d7212b6ff996d730eb85bfaad Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Wed, 4 Nov 2020 14:37:16 +1100 Subject: [PATCH] stm32/rfcore: Make RX IRQ schedule the NimBLE handler. This commit switches the STM32WB HCI interface (between the two CPUs) to require the use of MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS, and as a consequence to require NimBLE. IPCC RX IRQs now schedule the NimBLE handler to run via mp_sched_schedule. Signed-off-by: Jim Mussared --- ports/stm32/rfcore.c | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/ports/stm32/rfcore.c b/ports/stm32/rfcore.c index 08338fcdc2..550e5323e8 100644 --- a/ports/stm32/rfcore.c +++ b/ports/stm32/rfcore.c @@ -31,6 +31,7 @@ #include "py/mperrno.h" #include "py/mphal.h" #include "py/runtime.h" +#include "extmod/modbluetooth.h" #include "rtc.h" #include "rfcore.h" @@ -40,6 +41,10 @@ #define DEBUG_printf(...) // printf("rfcore: " __VA_ARGS__) +#if !MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS +#error "STM32WB must use synchronous events in the BLE implementation." +#endif + // Define to 1 to print traces of HCI packets #define HCI_TRACE (0) @@ -191,9 +196,6 @@ STATIC uint8_t ipcc_membuf_ble_cs_buf[272]; // mem2 STATIC tl_list_node_t ipcc_mem_ble_evt_queue; // mem1 STATIC uint8_t ipcc_membuf_ble_hci_acl_data_buf[272]; // mem2 -// Set by the RX IRQ handler on incoming HCI payload. -STATIC volatile bool had_ble_irq = false; - /******************************************************************************/ // Transport layer linked list @@ -408,6 +410,7 @@ STATIC void tl_process_msg(volatile tl_list_node_t *head, unsigned int ch, parse } } +// 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) { if (LL_C2_IPCC_IsActiveFlag_CHx(IPCC, ch)) { tl_process_msg(head, ch, parse); @@ -417,14 +420,6 @@ STATIC void tl_check_msg(volatile tl_list_node_t *head, unsigned int ch, parse_h } } -STATIC void tl_check_msg_ble(volatile tl_list_node_t *head, parse_hci_info_t *parse) { - if (had_ble_irq) { - tl_process_msg(head, IPCC_CH_BLE, parse); - - had_ble_irq = false; - } -} - STATIC void tl_hci_cmd(uint8_t *cmd, unsigned int ch, uint8_t hdr, uint16_t opcode, const uint8_t *buf, size_t len) { tl_list_node_t *n = (tl_list_node_t *)cmd; n->next = n; @@ -472,7 +467,7 @@ STATIC ssize_t tl_sys_hci_cmd_resp(uint16_t opcode, const uint8_t *buf, size_t l STATIC int tl_ble_wait_resp(void) { uint32_t t0 = mp_hal_ticks_ms(); - while (!had_ble_irq) { + while (!LL_C2_IPCC_IsActiveFlag_CHx(IPCC, IPCC_CH_BLE)) { if (mp_hal_ticks_ms() - t0 > BLE_ACK_TIMEOUT_MS) { printf("tl_ble_wait_resp: timeout\n"); return -MP_ETIMEDOUT; @@ -480,14 +475,16 @@ STATIC int tl_ble_wait_resp(void) { } // C2 set IPCC flag. - tl_check_msg_ble(&ipcc_mem_ble_evt_queue, NULL); + tl_check_msg(&ipcc_mem_ble_evt_queue, IPCC_CH_BLE, NULL); return 0; } // Synchronously send a BLE command. STATIC void tl_ble_hci_cmd_resp(uint16_t opcode, const uint8_t *buf, size_t len) { + LL_C1_IPCC_DisableReceiveChannel(IPCC, IPCC_CH_BLE); tl_hci_cmd(ipcc_membuf_ble_cmd_buf, IPCC_CH_BLE, HCI_KIND_BT_CMD, opcode, buf, len); tl_ble_wait_resp(); + LL_C1_IPCC_EnableReceiveChannel(IPCC, IPCC_CH_BLE); } /******************************************************************************/ @@ -554,11 +551,10 @@ static const struct { void rfcore_ble_init(void) { DEBUG_printf("rfcore_ble_init\n"); - // Clear any outstanding messages from ipcc_init + // Clear any outstanding messages from ipcc_init. tl_check_msg(&ipcc_mem_sys_queue, IPCC_CH_SYS, NULL); - tl_check_msg_ble(&ipcc_mem_ble_evt_queue, NULL); - // Configure and reset the BLE controller + // Configure and reset the BLE controller. tl_sys_hci_cmd_resp(HCI_OPCODE(OGF_VENDOR, OCF_BLE_INIT), (const uint8_t *)&ble_init_params, sizeof(ble_init_params), 0); tl_ble_hci_cmd_resp(HCI_OPCODE(0x03, 0x0003), NULL, 0); } @@ -597,7 +593,7 @@ 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) { parse_hci_info_t parse = { cb, env, false }; - tl_check_msg_ble(&ipcc_mem_ble_evt_queue, &parse); + tl_process_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) { @@ -629,9 +625,9 @@ void IPCC_C1_TX_IRQHandler(void) { void IPCC_C1_RX_IRQHandler(void) { IRQ_ENTER(IPCC_C1_RX_IRQn); - if (LL_C2_IPCC_IsActiveFlag_CHx(IPCC, IPCC_CH_BLE)) { - had_ble_irq = true; + DEBUG_printf("IPCC_C1_RX_IRQHandler\n"); + if (LL_C2_IPCC_IsActiveFlag_CHx(IPCC, IPCC_CH_BLE)) { LL_C1_IPCC_ClearFlag_CHx(IPCC, IPCC_CH_BLE); // Queue up the scheduler to process UART data and run events.