drivers: bluetooth: silabs: Add separate thread for BT Link Layer

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 <kalle.kietavainen@silabs.com>
This commit is contained in:
Kalle Kietäväinen 2025-01-13 15:06:42 +02:00 committed by Benjamin Cabé
commit fe5abd0344
3 changed files with 46 additions and 10 deletions

View file

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

View file

@ -5,6 +5,7 @@
*/
#include <zephyr/drivers/bluetooth.h>
#include <zephyr/kernel.h>
#include <sl_btctrl_linklayer.h>
#include <sl_hci_common_transport.h>
@ -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();

View file

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