@ -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.