stm32/rfcore: Fix flow control for IPCC RX IRQ.

Don't clear the IPCC channel flag until we've actually handled the incoming
data, or else the wireless firmware may clobber the IPCC buffer if more
data arrives.  This requires masking the IRQ until the data is handled.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
This commit is contained in:
Jim Mussared 2021-01-29 17:45:33 +11:00 committed by Damien George
parent b8f4c623f9
commit 0f9a9129da
1 changed files with 12 additions and 5 deletions

View File

@ -434,10 +434,16 @@ 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)) {
// Process new data.
tl_process_msg(head, ch, parse);
// Clear receive channel.
// Clear receive channel (allows RF core to send more data to us).
LL_C1_IPCC_ClearFlag_CHx(IPCC, ch);
if (ch == IPCC_CH_BLE) {
// Renable IRQs for BLE now that we've cleared the flag.
LL_C1_IPCC_EnableReceiveChannel(IPCC, IPCC_CH_BLE);
}
}
}
@ -495,17 +501,17 @@ STATIC int tl_ble_wait_resp(void) {
}
}
// C2 set IPCC flag.
// C2 set IPCC flag -- process the data, clear the flag, and re-enable IRQs.
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) {
// Poll for completion rather than wait for IRQ->scheduler.
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);
}
/******************************************************************************/
@ -632,7 +638,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_process_msg(&ipcc_mem_ble_evt_queue, IPCC_CH_BLE, &parse);
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) {
@ -679,7 +685,8 @@ void IPCC_C1_RX_IRQHandler(void) {
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);
// Disable this IRQ until the incoming data is processed (in tl_check_msg).
LL_C1_IPCC_DisableReceiveChannel(IPCC, IPCC_CH_BLE);
#if MICROPY_PY_BLUETOOTH
// Queue up the scheduler to process UART data and run events.