nrf connect sdk(v2.3.0)在含定时器的BLE开发中出现的notify卡死问题

April 29, 2023

假如你所开发的BLE项目出现了用nrf connect这个app来连接nordic蓝牙,read方法可以读取,但是notify出现了:

在使用工作队列的情况下:

1.第一次点击notify enable按钮只能读取1-2个数据

2.第二次点击notify enable按钮可以读到几秒到几十秒数据(随蓝牙信号强度而变化),然后卡死

在只用定时器的情况下:

KERNEL报错,自动reset

那么,很有可能,你是遇到了本问题.

问题出现的原因是nrf connect sdk自身的bt_gatt_notify_cb()函数有bug,

该函数底层调用了bt_conn_tx()函数,使得它在conn层发送的时候,调用了下面的函数:

return k_fifo_get(&free_tx, K_FOREVER);

这个函数会在free_tx这个FIFO里以阻塞方式(K_FOREVER)读取数据.你的定时器可能会在其读数据前打断,并塞入新数据.

请注意,问题根源并不在于有些人所说的线程死锁,而是FIFO本身存储空间太小,要发送的包只能存储三个(BT_CONN_TX_MAX默认设置为3),导致您:

1.第一次要发的包过多,FIFO只能存储前三个,k_fifo_get()函数想要读取FIFO超过三次来发送,而导致阻塞.

2.后面有几次发包被定时器打断,导致送给FIFO存储的包大于三个,但是FIFO只能存三个,k_fifo_get()函数想要读取FIFO超过三次来发送,导致阻塞.

在只有定时器的情况下(即中断处理时运行),则会导致崩溃.

解决方法:

方法1:设置CONFIG_BT_CONN_TX_MAX=255[力大砖飞]

方法2:多线程,在另一个线程中进行bt_gatt_notify_cb()[不建议,线程lock与resume需要时间]


Profile picture

Written by Prosumer , an undergraduate student at ShanghaiTech.
Welcome to my GitHub:)