From a453b4f31d3b5928eeb48f50ce1d6314612538c1 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Wed, 10 May 2023 15:59:15 +0200 Subject: [PATCH] drivers/cyw43: Make the CYW43 Bluetooth HCI driver more portable. This commit allows other ports to reuse the CYW43 HCI driver, by replacing all Bluetooth UART and control named pins with defines in config files and using `mpbthci` abstract functions (i.e. `mp_bluetooth_hci_*`) instead of the STM32 specific UART functions. Note: the function `cywbt_wait_cts_low` does not need to switch the CTS pin from alternate function to GPIO to read it. At least on stm32, mimxrt it's possible to just read the pin input. For example, see the STM32F7 RM0410 section 6.3.11, and the `SION` for IMXRT. So this function can also be available for other ports if the pin mode switching is removed. Signed-off-by: iabdalkader --- drivers/cyw43/cywbt.c | 99 ++++++++++++++++++++-------------- ports/stm32/cyw43_configport.h | 7 +++ 2 files changed, 66 insertions(+), 40 deletions(-) diff --git a/drivers/cyw43/cywbt.c b/drivers/cyw43/cywbt.c index 006fd28e90..bc6674ea2e 100644 --- a/drivers/cyw43/cywbt.c +++ b/drivers/cyw43/cywbt.c @@ -29,8 +29,6 @@ #include "py/runtime.h" #include "py/mphal.h" -#include "pin_static_af.h" -#include "uart.h" #include "extmod/mpbthci.h" #if MICROPY_PY_NETWORK_CYW43 @@ -38,33 +36,41 @@ #include "lib/cyw43-driver/src/cyw43_config.h" #include "lib/cyw43-driver/firmware/cyw43_btfw_4343A1.h" -// Provided by the port. -extern pyb_uart_obj_t mp_bluetooth_hci_uart_obj; - // Provided by the port, and also possibly shared with the stack. extern uint8_t mp_bluetooth_hci_cmd_buf[4 + 256]; /******************************************************************************/ // CYW BT HCI low-level driver +#ifdef CYW43_PIN_BT_CTS +// This code is not portable and currently only builds on stm32 port. + +#include "pin_static_af.h" +#include "uart.h" + +// Provided by the port. +extern pyb_uart_obj_t mp_bluetooth_hci_uart_obj; + STATIC void cywbt_wait_cts_low(void) { - mp_hal_pin_config(pyb_pin_BT_CTS, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0); + mp_hal_pin_config(CYW43_PIN_BT_CTS, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0); for (int i = 0; i < 200; ++i) { - if (mp_hal_pin_read(pyb_pin_BT_CTS) == 0) { + if (mp_hal_pin_read(CYW43_PIN_BT_CTS) == 0) { break; } mp_hal_delay_ms(1); } - mp_hal_pin_config_alt(pyb_pin_BT_CTS, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, AF_FN_UART, mp_bluetooth_hci_uart_obj.uart_id); + mp_hal_pin_config_alt(CYW43_PIN_BT_CTS, MP_HAL_PIN_MODE_ALT, + MP_HAL_PIN_PULL_UP, AF_FN_UART, mp_bluetooth_hci_uart_obj.uart_id); } +#endif STATIC int cywbt_hci_cmd_raw(size_t len, uint8_t *buf) { - uart_tx_strn(&mp_bluetooth_hci_uart_obj, (void*)buf, len); - for (int i = 0; i < 6; ++i) { - while (!uart_rx_any(&mp_bluetooth_hci_uart_obj)) { + mp_bluetooth_hci_uart_write((void *)buf, len); + for (int c, i = 0; i < 6; ++i) { + while ((c = mp_bluetooth_hci_uart_readchar()) == -1) { MICROPY_EVENT_POLL_HOOK } - buf[i] = uart_rx_char(&mp_bluetooth_hci_uart_obj); + buf[i] = c; } // expect a command complete event (event 0x0e) @@ -80,11 +86,11 @@ STATIC int cywbt_hci_cmd_raw(size_t len, uint8_t *buf) { */ int sz = buf[2] - 3; - for (int i = 0; i < sz; ++i) { - while (!uart_rx_any(&mp_bluetooth_hci_uart_obj)) { + for (int c, i = 0; i < sz; ++i) { + while ((c = mp_bluetooth_hci_uart_readchar()) == -1) { MICROPY_EVENT_POLL_HOOK } - buf[i] = uart_rx_char(&mp_bluetooth_hci_uart_obj); + buf[i] = c; } return 0; @@ -150,12 +156,15 @@ STATIC int cywbt_download_firmware(const uint8_t *firmware) { // RF switch must select high path during BT patch boot #if MICROPY_HW_ENABLE_RF_SWITCH - mp_hal_pin_config(pyb_pin_WL_GPIO_1, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0); + mp_hal_pin_config(CYW43_PIN_WL_GPIO_1, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0); #endif mp_hal_delay_ms(10); // give some time for CTS to go high + #ifdef CYW43_PIN_BT_CTS cywbt_wait_cts_low(); + #endif #if MICROPY_HW_ENABLE_RF_SWITCH - mp_hal_pin_config(pyb_pin_WL_GPIO_1, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_DOWN, 0); // Select chip antenna (could also select external) + // Select chip antenna (could also select external) + mp_hal_pin_config(CYW43_PIN_WL_GPIO_1, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_DOWN, 0); #endif mp_bluetooth_hci_uart_set_baudrate(115200); @@ -168,25 +177,33 @@ STATIC int cywbt_download_firmware(const uint8_t *firmware) { int mp_bluetooth_hci_controller_init(void) { // This is called immediately after the UART is initialised during stack initialisation. - mp_hal_pin_output(pyb_pin_BT_REG_ON); - mp_hal_pin_low(pyb_pin_BT_REG_ON); - mp_hal_pin_input(pyb_pin_BT_HOST_WAKE); - mp_hal_pin_output(pyb_pin_BT_DEV_WAKE); - mp_hal_pin_low(pyb_pin_BT_DEV_WAKE); + mp_hal_pin_output(CYW43_PIN_BT_REG_ON); + mp_hal_pin_low(CYW43_PIN_BT_REG_ON); + #ifdef CYW43_PIN_BT_HOST_WAKE + mp_hal_pin_input(CYW43_PIN_BT_HOST_WAKE); + #endif + #ifdef CYW43_PIN_BT_DEV_WAKE + mp_hal_pin_output(CYW43_PIN_BT_DEV_WAKE); + mp_hal_pin_low(CYW43_PIN_BT_DEV_WAKE); + #endif #if MICROPY_HW_ENABLE_RF_SWITCH // TODO don't select antenna if wifi is enabled - mp_hal_pin_config(pyb_pin_WL_GPIO_4, MP_HAL_PIN_MODE_OUTPUT, MP_HAL_PIN_PULL_NONE, 0); // RF-switch power - mp_hal_pin_high(pyb_pin_WL_GPIO_4); // Turn the RF-switch on + mp_hal_pin_config(CYW43_PIN_WL_GPIO_4, MP_HAL_PIN_MODE_OUTPUT, MP_HAL_PIN_PULL_NONE, 0); // RF-switch power + mp_hal_pin_high(CYW43_PIN_WL_GPIO_4); // Turn the RF-switch on #endif uint8_t buf[256]; - mp_hal_pin_low(pyb_pin_BT_REG_ON); + mp_hal_pin_low(CYW43_PIN_BT_REG_ON); mp_bluetooth_hci_uart_set_baudrate(115200); mp_hal_delay_ms(100); - mp_hal_pin_high(pyb_pin_BT_REG_ON); + mp_hal_pin_high(CYW43_PIN_BT_REG_ON); + #ifdef CYW43_PIN_BT_CTS cywbt_wait_cts_low(); + #else + mp_hal_delay_ms(100); + #endif // Reset cywbt_hci_cmd(0x03, 0x0003, 0, NULL); @@ -197,7 +214,7 @@ int mp_bluetooth_hci_controller_init(void) { mp_bluetooth_hci_uart_set_baudrate(MICROPY_HW_BLE_UART_BAUDRATE_DOWNLOAD_FIRMWARE); #endif - cywbt_download_firmware((const uint8_t*)&cyw43_btfw_4343A1[0]); + cywbt_download_firmware((const uint8_t *)&cyw43_btfw_4343A1[0]); // Reset cywbt_hci_cmd(0x03, 0x0003, 0, NULL); @@ -219,31 +236,33 @@ int mp_bluetooth_hci_controller_init(void) { // cywbt_hci_cmd(0x03, 0x0013, 248, buf); // Configure sleep mode - cywbt_hci_cmd(0x3f, 0x27, 12, (const uint8_t*)"\x01\x02\x02\x00\x00\x00\x01\x00\x00\x00\x00\x00"); + cywbt_hci_cmd(0x3f, 0x27, 12, (const uint8_t *)"\x01\x02\x02\x00\x00\x00\x01\x00\x00\x00\x00\x00"); // HCI_Write_LE_Host_Support - cywbt_hci_cmd(3, 109, 2, (const uint8_t*)"\x01\x00"); + cywbt_hci_cmd(3, 109, 2, (const uint8_t *)"\x01\x00"); - mp_hal_pin_high(pyb_pin_BT_DEV_WAKE); // let sleep + #ifdef CYW43_PIN_BT_DEV_WAKE + mp_hal_pin_high(CYW43_PIN_BT_DEV_WAKE); // let sleep + #endif return 0; } int mp_bluetooth_hci_controller_deinit(void) { - mp_hal_pin_low(pyb_pin_BT_REG_ON); + mp_hal_pin_low(CYW43_PIN_BT_REG_ON); return 0; } -#ifdef pyb_pin_BT_DEV_WAKE +#ifdef CYW43_PIN_BT_DEV_WAKE STATIC uint32_t bt_sleep_ticks; #endif int mp_bluetooth_hci_controller_sleep_maybe(void) { - #ifdef pyb_pin_BT_DEV_WAKE - if (mp_hal_pin_read(pyb_pin_BT_DEV_WAKE) == 0) { + #ifdef CYW43_PIN_BT_DEV_WAKE + if (mp_hal_pin_read(CYW43_PIN_BT_DEV_WAKE) == 0) { if (mp_hal_ticks_ms() - bt_sleep_ticks > 500) { - mp_hal_pin_high(pyb_pin_BT_DEV_WAKE); // let sleep + mp_hal_pin_high(CYW43_PIN_BT_DEV_WAKE); // let sleep } } #endif @@ -251,8 +270,8 @@ int mp_bluetooth_hci_controller_sleep_maybe(void) { } bool mp_bluetooth_hci_controller_woken(void) { - #ifdef pyb_pin_BT_HOST_WAKE - bool host_wake = mp_hal_pin_read(pyb_pin_BT_HOST_WAKE); + #ifdef CYW43_PIN_BT_HOST_WAKE + bool host_wake = mp_hal_pin_read(CYW43_PIN_BT_HOST_WAKE); /* // this is just for info/tracing purposes static bool last_host_wake = false; @@ -268,11 +287,11 @@ bool mp_bluetooth_hci_controller_woken(void) { } int mp_bluetooth_hci_controller_wakeup(void) { - #ifdef pyb_pin_BT_DEV_WAKE + #ifdef CYW43_PIN_BT_DEV_WAKE bt_sleep_ticks = mp_hal_ticks_ms(); - if (mp_hal_pin_read(pyb_pin_BT_DEV_WAKE) == 1) { - mp_hal_pin_low(pyb_pin_BT_DEV_WAKE); // wake up + if (mp_hal_pin_read(CYW43_PIN_BT_DEV_WAKE) == 1) { + mp_hal_pin_low(CYW43_PIN_BT_DEV_WAKE); // wake up // Use delay_us rather than delay_ms to prevent running the scheduler (which // might result in more BLE operations). mp_hal_delay_us(5000); // can't go lower than this diff --git a/ports/stm32/cyw43_configport.h b/ports/stm32/cyw43_configport.h index 4b6dde3c43..f2a880603a 100644 --- a/ports/stm32/cyw43_configport.h +++ b/ports/stm32/cyw43_configport.h @@ -93,6 +93,13 @@ #define CYW43_PIN_WL_REG_ON pyb_pin_WL_REG_ON #define CYW43_PIN_WL_HOST_WAKE pyb_pin_WL_HOST_WAKE #define CYW43_PIN_WL_SDIO_1 pyb_pin_WL_SDIO_1 +#define CYW43_PIN_WL_GPIO_1 pyb_pin_WL_GPIO_1 +#define CYW43_PIN_WL_GPIO_4 pyb_pin_WL_GPIO_4 + +#define CYW43_PIN_BT_REG_ON pyb_pin_BT_REG_ON +#define CYW43_PIN_BT_HOST_WAKE pyb_pin_BT_HOST_WAKE +#define CYW43_PIN_BT_DEV_WAKE pyb_pin_BT_DEV_WAKE +#define CYW43_PIN_BT_CTS pyb_pin_BT_CTS #if MICROPY_HW_ENABLE_RF_SWITCH #define CYW43_PIN_WL_RFSW_VDD pyb_pin_WL_RFSW_VDD