Skip to content

Commit fe5abd0

Browse files
kietavainenkartben
authored andcommitted
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>
1 parent cfe91b8 commit fe5abd0

File tree

3 files changed

+46
-10
lines changed

3 files changed

+46
-10
lines changed

drivers/bluetooth/hci/Kconfig.silabs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,9 @@ config BT_SILABS_EFR32_ACCEPT_LINK_LAYER_STACK_SIZE
4141
default 1024
4242
help
4343
Link layer stack size.
44+
45+
config BT_SILABS_EFR32_LL_THREAD_PRIO
46+
# Hidden option for Co-Operative Link Layer thread priority
47+
def_int 0
48+
4449
endmenu

drivers/bluetooth/hci/hci_silabs_efr32.c

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66

77
#include <zephyr/drivers/bluetooth.h>
8+
#include <zephyr/kernel.h>
89

910
#include <sl_btctrl_linklayer.h>
1011
#include <sl_hci_common_transport.h>
@@ -36,12 +37,18 @@ struct hci_data {
3637
static K_KERNEL_STACK_DEFINE(slz_ll_stack, CONFIG_BT_SILABS_EFR32_ACCEPT_LINK_LAYER_STACK_SIZE);
3738
static struct k_thread slz_ll_thread;
3839

40+
static K_KERNEL_STACK_DEFINE(slz_rx_stack, CONFIG_BT_DRV_RX_STACK_SIZE);
41+
static struct k_thread slz_rx_thread;
42+
3943
/* Semaphore for Link Layer */
4044
K_SEM_DEFINE(slz_ll_sem, 0, 1);
4145

4246
/* Events mask for Link Layer */
4347
static atomic_t sli_btctrl_events;
4448

49+
/* FIFO for received HCI packets */
50+
static struct k_fifo slz_rx_fifo;
51+
4552
/* FIXME: these functions should come from the SiSDK headers! */
4653
void BTLE_LL_EventRaise(uint32_t events);
4754
void BTLE_LL_Process(uint32_t events);
@@ -73,8 +80,6 @@ void rail_isr_installer(void)
7380
*/
7481
uint32_t hci_common_transport_transmit(uint8_t *data, int16_t len)
7582
{
76-
const struct device *dev = DEVICE_DT_GET(DT_DRV_INST(0));
77-
struct hci_data *hci = dev->data;
7883
struct net_buf *buf;
7984
uint8_t packet_type = data[0];
8085
uint8_t event_code;
@@ -99,7 +104,7 @@ uint32_t hci_common_transport_transmit(uint8_t *data, int16_t len)
99104
}
100105

101106
net_buf_add_mem(buf, data, len);
102-
hci->recv(dev, buf);
107+
k_fifo_put(&slz_rx_fifo, buf);
103108

104109
sl_btctrl_hci_transmit_complete(0);
105110

@@ -140,7 +145,7 @@ static int slz_bt_send(const struct device *dev, struct net_buf *buf)
140145
* or an HCI event to pass upstairs. The BTLE_LL_Process function call will
141146
* take care of all of them, and add HCI events to the HCI queue when applicable.
142147
*/
143-
static void slz_thread_func(void *p1, void *p2, void *p3)
148+
static void slz_ll_thread_func(void *p1, void *p2, void *p3)
144149
{
145150
ARG_UNUSED(p1);
146151
ARG_UNUSED(p2);
@@ -155,17 +160,40 @@ static void slz_thread_func(void *p1, void *p2, void *p3)
155160
}
156161
}
157162

163+
static void slz_rx_thread_func(void *p1, void *p2, void *p3)
164+
{
165+
const struct device *dev = p1;
166+
struct hci_data *hci = dev->data;
167+
168+
ARG_UNUSED(p2);
169+
ARG_UNUSED(p3);
170+
171+
while (true) {
172+
struct net_buf *buf = k_fifo_get(&slz_rx_fifo, K_FOREVER);
173+
174+
hci->recv(dev, buf);
175+
}
176+
}
177+
158178
static int slz_bt_open(const struct device *dev, bt_hci_recv_t recv)
159179
{
160180
struct hci_data *hci = dev->data;
161181
int ret;
162182

163-
/* Start RX thread */
164-
k_thread_create(&slz_ll_thread, slz_ll_stack,
165-
K_KERNEL_STACK_SIZEOF(slz_ll_stack),
166-
slz_thread_func, NULL, NULL, NULL,
167-
K_PRIO_COOP(CONFIG_BT_DRIVER_RX_HIGH_PRIO), 0,
168-
K_NO_WAIT);
183+
BUILD_ASSERT(CONFIG_NUM_METAIRQ_PRIORITIES > 0,
184+
"Config NUM_METAIRQ_PRIORITIES must be greater than 0");
185+
BUILD_ASSERT(CONFIG_BT_SILABS_EFR32_LL_THREAD_PRIO < CONFIG_NUM_METAIRQ_PRIORITIES,
186+
"Config BT_SILABS_EFR32_LL_THREAD_PRIO must be a meta-IRQ priority");
187+
188+
k_fifo_init(&slz_rx_fifo);
189+
190+
k_thread_create(&slz_ll_thread, slz_ll_stack, K_KERNEL_STACK_SIZEOF(slz_ll_stack),
191+
slz_ll_thread_func, NULL, NULL, NULL,
192+
K_PRIO_COOP(CONFIG_BT_SILABS_EFR32_LL_THREAD_PRIO), 0, K_NO_WAIT);
193+
194+
k_thread_create(&slz_rx_thread, slz_rx_stack, K_KERNEL_STACK_SIZEOF(slz_rx_stack),
195+
slz_rx_thread_func, (void *)dev, NULL, NULL,
196+
K_PRIO_COOP(CONFIG_BT_DRIVER_RX_HIGH_PRIO), 0, K_NO_WAIT);
169197

170198
rail_isr_installer();
171199
sl_rail_util_pa_init();

soc/silabs/Kconfig.defconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,7 @@ config CORTEX_M_SYSTICK
1919
config IDLE_STACK_SIZE
2020
default 512 if SOC_GECKO_PM_BACKEND_PMGR
2121

22+
configdefault NUM_METAIRQ_PRIORITIES
23+
default 1 if BT_SILABS_EFR32
24+
2225
endif

0 commit comments

Comments
 (0)