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:
parent
cfe91b8df1
commit
fe5abd0344
3 changed files with 46 additions and 10 deletions
|
@ -41,4 +41,9 @@ config BT_SILABS_EFR32_ACCEPT_LINK_LAYER_STACK_SIZE
|
||||||
default 1024
|
default 1024
|
||||||
help
|
help
|
||||||
Link layer stack size.
|
Link layer stack size.
|
||||||
|
|
||||||
|
config BT_SILABS_EFR32_LL_THREAD_PRIO
|
||||||
|
# Hidden option for Co-Operative Link Layer thread priority
|
||||||
|
def_int 0
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <zephyr/drivers/bluetooth.h>
|
#include <zephyr/drivers/bluetooth.h>
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
|
||||||
#include <sl_btctrl_linklayer.h>
|
#include <sl_btctrl_linklayer.h>
|
||||||
#include <sl_hci_common_transport.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 K_KERNEL_STACK_DEFINE(slz_ll_stack, CONFIG_BT_SILABS_EFR32_ACCEPT_LINK_LAYER_STACK_SIZE);
|
||||||
static struct k_thread slz_ll_thread;
|
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 */
|
/* Semaphore for Link Layer */
|
||||||
K_SEM_DEFINE(slz_ll_sem, 0, 1);
|
K_SEM_DEFINE(slz_ll_sem, 0, 1);
|
||||||
|
|
||||||
/* Events mask for Link Layer */
|
/* Events mask for Link Layer */
|
||||||
static atomic_t sli_btctrl_events;
|
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! */
|
/* FIXME: these functions should come from the SiSDK headers! */
|
||||||
void BTLE_LL_EventRaise(uint32_t events);
|
void BTLE_LL_EventRaise(uint32_t events);
|
||||||
void BTLE_LL_Process(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)
|
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;
|
struct net_buf *buf;
|
||||||
uint8_t packet_type = data[0];
|
uint8_t packet_type = data[0];
|
||||||
uint8_t event_code;
|
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);
|
net_buf_add_mem(buf, data, len);
|
||||||
hci->recv(dev, buf);
|
k_fifo_put(&slz_rx_fifo, buf);
|
||||||
|
|
||||||
sl_btctrl_hci_transmit_complete(0);
|
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
|
* 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.
|
* 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(p1);
|
||||||
ARG_UNUSED(p2);
|
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)
|
static int slz_bt_open(const struct device *dev, bt_hci_recv_t recv)
|
||||||
{
|
{
|
||||||
struct hci_data *hci = dev->data;
|
struct hci_data *hci = dev->data;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Start RX thread */
|
BUILD_ASSERT(CONFIG_NUM_METAIRQ_PRIORITIES > 0,
|
||||||
k_thread_create(&slz_ll_thread, slz_ll_stack,
|
"Config NUM_METAIRQ_PRIORITIES must be greater than 0");
|
||||||
K_KERNEL_STACK_SIZEOF(slz_ll_stack),
|
BUILD_ASSERT(CONFIG_BT_SILABS_EFR32_LL_THREAD_PRIO < CONFIG_NUM_METAIRQ_PRIORITIES,
|
||||||
slz_thread_func, NULL, NULL, NULL,
|
"Config BT_SILABS_EFR32_LL_THREAD_PRIO must be a meta-IRQ priority");
|
||||||
K_PRIO_COOP(CONFIG_BT_DRIVER_RX_HIGH_PRIO), 0,
|
|
||||||
K_NO_WAIT);
|
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();
|
rail_isr_installer();
|
||||||
sl_rail_util_pa_init();
|
sl_rail_util_pa_init();
|
||||||
|
|
|
@ -19,4 +19,7 @@ config CORTEX_M_SYSTICK
|
||||||
config IDLE_STACK_SIZE
|
config IDLE_STACK_SIZE
|
||||||
default 512 if SOC_GECKO_PM_BACKEND_PMGR
|
default 512 if SOC_GECKO_PM_BACKEND_PMGR
|
||||||
|
|
||||||
|
configdefault NUM_METAIRQ_PRIORITIES
|
||||||
|
default 1 if BT_SILABS_EFR32
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue