Commit fe5abd03 authored by Kalle Kietäväinen's avatar Kalle Kietäväinen Committed by Benjamin Cabé
Browse files

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: default avatarKalle Kietäväinen <kalle.kietavainen@silabs.com>
parent cfe91b8d
Loading
Loading
Loading
Loading
+5 −0
Changes for drivers/bluetooth/hci/Kconfig.silabs: 5 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -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
+38 −10
Changes for drivers/bluetooth/hci/hci_silabs_efr32.c: 38 added lines, 10 removed lines.
Original line number Diff line number Diff line
@@ -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();
+3 −0
Changes for soc/silabs/Kconfig.defconfig: 3 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -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