From fe5abd034469fcce6e05b1c74cc3152bf5128b58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kalle=20Kiet=C3=A4v=C3=A4inen?= Date: Mon, 13 Jan 2025 15:06:42 +0200 Subject: [PATCH] drivers: bluetooth: silabs: Add separate thread for BT Link Layer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The BT Link Layer needs to get runtime in a timely manner to keep connections alive and handle other time-critical tasks. This is achieved by adding a separate thread for it with a meta-IRQ priority, which means it can preempt other threads. The driver also has an RX thread that passes HCI messages from the controller to the host stack. This can be a lower priority cooperative thread, as it doesn't have strict timing requirements. Signed-off-by: Kalle Kietäväinen --- drivers/bluetooth/hci/Kconfig.silabs | 5 +++ drivers/bluetooth/hci/hci_silabs_efr32.c | 48 +++++++++++++++++++----- soc/silabs/Kconfig.defconfig | 3 ++ 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/drivers/bluetooth/hci/Kconfig.silabs b/drivers/bluetooth/hci/Kconfig.silabs index 8598a3fddee..9b91c47fbf5 100644 --- a/drivers/bluetooth/hci/Kconfig.silabs +++ b/drivers/bluetooth/hci/Kconfig.silabs @@ -41,4 +41,9 @@ config BT_SILABS_EFR32_ACCEPT_LINK_LAYER_STACK_SIZE default 1024 help Link layer stack size. + +config BT_SILABS_EFR32_LL_THREAD_PRIO + # Hidden option for Co-Operative Link Layer thread priority + def_int 0 + endmenu diff --git a/drivers/bluetooth/hci/hci_silabs_efr32.c b/drivers/bluetooth/hci/hci_silabs_efr32.c index 443a3d010b8..a593a618904 100644 --- a/drivers/bluetooth/hci/hci_silabs_efr32.c +++ b/drivers/bluetooth/hci/hci_silabs_efr32.c @@ -5,6 +5,7 @@ */ #include +#include #include #include @@ -36,12 +37,18 @@ struct hci_data { static K_KERNEL_STACK_DEFINE(slz_ll_stack, CONFIG_BT_SILABS_EFR32_ACCEPT_LINK_LAYER_STACK_SIZE); static struct k_thread slz_ll_thread; +static K_KERNEL_STACK_DEFINE(slz_rx_stack, CONFIG_BT_DRV_RX_STACK_SIZE); +static struct k_thread slz_rx_thread; + /* Semaphore for Link Layer */ K_SEM_DEFINE(slz_ll_sem, 0, 1); /* Events mask for Link Layer */ static atomic_t sli_btctrl_events; +/* FIFO for received HCI packets */ +static struct k_fifo slz_rx_fifo; + /* FIXME: these functions should come from the SiSDK headers! */ void BTLE_LL_EventRaise(uint32_t events); void BTLE_LL_Process(uint32_t events); @@ -73,8 +80,6 @@ void rail_isr_installer(void) */ uint32_t hci_common_transport_transmit(uint8_t *data, int16_t len) { - const struct device *dev = DEVICE_DT_GET(DT_DRV_INST(0)); - struct hci_data *hci = dev->data; struct net_buf *buf; uint8_t packet_type = data[0]; uint8_t event_code; @@ -99,7 +104,7 @@ uint32_t hci_common_transport_transmit(uint8_t *data, int16_t len) } net_buf_add_mem(buf, data, len); - hci->recv(dev, buf); + k_fifo_put(&slz_rx_fifo, buf); sl_btctrl_hci_transmit_complete(0); @@ -140,7 +145,7 @@ done: * or an HCI event to pass upstairs. The BTLE_LL_Process function call will * take care of all of them, and add HCI events to the HCI queue when applicable. */ -static void slz_thread_func(void *p1, void *p2, void *p3) +static void slz_ll_thread_func(void *p1, void *p2, void *p3) { ARG_UNUSED(p1); ARG_UNUSED(p2); @@ -155,17 +160,40 @@ static void slz_thread_func(void *p1, void *p2, void *p3) } } +static void slz_rx_thread_func(void *p1, void *p2, void *p3) +{ + const struct device *dev = p1; + struct hci_data *hci = dev->data; + + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + while (true) { + struct net_buf *buf = k_fifo_get(&slz_rx_fifo, K_FOREVER); + + hci->recv(dev, buf); + } +} + static int slz_bt_open(const struct device *dev, bt_hci_recv_t recv) { struct hci_data *hci = dev->data; int ret; - /* Start RX thread */ - k_thread_create(&slz_ll_thread, slz_ll_stack, - K_KERNEL_STACK_SIZEOF(slz_ll_stack), - slz_thread_func, NULL, NULL, NULL, - K_PRIO_COOP(CONFIG_BT_DRIVER_RX_HIGH_PRIO), 0, - K_NO_WAIT); + BUILD_ASSERT(CONFIG_NUM_METAIRQ_PRIORITIES > 0, + "Config NUM_METAIRQ_PRIORITIES must be greater than 0"); + BUILD_ASSERT(CONFIG_BT_SILABS_EFR32_LL_THREAD_PRIO < CONFIG_NUM_METAIRQ_PRIORITIES, + "Config BT_SILABS_EFR32_LL_THREAD_PRIO must be a meta-IRQ priority"); + + k_fifo_init(&slz_rx_fifo); + + k_thread_create(&slz_ll_thread, slz_ll_stack, K_KERNEL_STACK_SIZEOF(slz_ll_stack), + slz_ll_thread_func, NULL, NULL, NULL, + K_PRIO_COOP(CONFIG_BT_SILABS_EFR32_LL_THREAD_PRIO), 0, K_NO_WAIT); + + k_thread_create(&slz_rx_thread, slz_rx_stack, K_KERNEL_STACK_SIZEOF(slz_rx_stack), + slz_rx_thread_func, (void *)dev, NULL, NULL, + K_PRIO_COOP(CONFIG_BT_DRIVER_RX_HIGH_PRIO), 0, K_NO_WAIT); rail_isr_installer(); sl_rail_util_pa_init(); diff --git a/soc/silabs/Kconfig.defconfig b/soc/silabs/Kconfig.defconfig index 5c55a394c68..aaf363576f8 100644 --- a/soc/silabs/Kconfig.defconfig +++ b/soc/silabs/Kconfig.defconfig @@ -19,4 +19,7 @@ config CORTEX_M_SYSTICK config IDLE_STACK_SIZE default 512 if SOC_GECKO_PM_BACKEND_PMGR +configdefault NUM_METAIRQ_PRIORITIES + default 1 if BT_SILABS_EFR32 + endif