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 <jim.mussared@gmail.com>
This commit is contained in:
Jim Mussared 2020-11-04 14:37:16 +11:00 committed by Damien George
parent efc0800132
commit a64121b0d4
1 changed files with 15 additions and 19 deletions

View File

@ -31,6 +31,7 @@
#include "py/mperrno.h" #include "py/mperrno.h"
#include "py/mphal.h" #include "py/mphal.h"
#include "py/runtime.h" #include "py/runtime.h"
#include "extmod/modbluetooth.h"
#include "rtc.h" #include "rtc.h"
#include "rfcore.h" #include "rfcore.h"
@ -40,6 +41,10 @@
#define DEBUG_printf(...) // printf("rfcore: " __VA_ARGS__) #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 to 1 to print traces of HCI packets
#define HCI_TRACE (0) #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 tl_list_node_t ipcc_mem_ble_evt_queue; // mem1
STATIC uint8_t ipcc_membuf_ble_hci_acl_data_buf[272]; // mem2 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 // 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) { 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)) { if (LL_C2_IPCC_IsActiveFlag_CHx(IPCC, ch)) {
tl_process_msg(head, ch, parse); 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) { 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; tl_list_node_t *n = (tl_list_node_t *)cmd;
n->next = n; 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) { STATIC int tl_ble_wait_resp(void) {
uint32_t t0 = mp_hal_ticks_ms(); 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) { if (mp_hal_ticks_ms() - t0 > BLE_ACK_TIMEOUT_MS) {
printf("tl_ble_wait_resp: timeout\n"); printf("tl_ble_wait_resp: timeout\n");
return -MP_ETIMEDOUT; return -MP_ETIMEDOUT;
@ -480,14 +475,16 @@ STATIC int tl_ble_wait_resp(void) {
} }
// C2 set IPCC flag. // 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; return 0;
} }
// Synchronously send a BLE command. // Synchronously send a BLE command.
STATIC void tl_ble_hci_cmd_resp(uint16_t opcode, const uint8_t *buf, size_t len) { 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_hci_cmd(ipcc_membuf_ble_cmd_buf, IPCC_CH_BLE, HCI_KIND_BT_CMD, opcode, buf, len);
tl_ble_wait_resp(); tl_ble_wait_resp();
LL_C1_IPCC_EnableReceiveChannel(IPCC, IPCC_CH_BLE);
} }
/******************************************************************************/ /******************************************************************************/
@ -554,11 +551,10 @@ static const struct {
void rfcore_ble_init(void) { void rfcore_ble_init(void) {
DEBUG_printf("rfcore_ble_init\n"); 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(&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_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); 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) { void rfcore_ble_check_msg(int (*cb)(void *, const uint8_t *, size_t), void *env) {
parse_hci_info_t parse = { cb, env, false }; 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 // Intercept HCI_Reset events and reconfigure the controller following the reset
if (parse.was_hci_reset_evt) { if (parse.was_hci_reset_evt) {
@ -629,9 +625,9 @@ void IPCC_C1_TX_IRQHandler(void) {
void IPCC_C1_RX_IRQHandler(void) { void IPCC_C1_RX_IRQHandler(void) {
IRQ_ENTER(IPCC_C1_RX_IRQn); IRQ_ENTER(IPCC_C1_RX_IRQn);
if (LL_C2_IPCC_IsActiveFlag_CHx(IPCC, IPCC_CH_BLE)) { DEBUG_printf("IPCC_C1_RX_IRQHandler\n");
had_ble_irq = true;
if (LL_C2_IPCC_IsActiveFlag_CHx(IPCC, IPCC_CH_BLE)) {
LL_C1_IPCC_ClearFlag_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. // Queue up the scheduler to process UART data and run events.