Skip to main content

BP10xx蓝牙开发日志

蓝牙运行框架图

BLE_SUPPORT 这个是ble蓝牙开启定义宏,设置

#ifdef CFG_TWS_SOUNDBAR_APP

#define BLE_SUPPORT ENABLE // BLE config

#else

#define BLE_SUPPORT ENABLE // BLE 启动定义宏

蓝牙config.h 配置选项表

根据代码中的配置选项,以下是整理出的配置选项及其说明的表格:

配置项描述
ENABLE / DISABLE定义了启用和禁用的宏,用于控制功能的开关。
BT_PROFILE_BQB_ENABLE是否启用BQB测试模式(蓝牙认证测试)。
BT_NAME蓝牙设备名称(默认为"Hanami-music")。
BT_NAME_SIZE蓝牙名称的最大长度(固定为40)。
BT_ADDR_SIZE蓝牙地址的长度(固定为6)。
FLASH_SAVE_REMOTE_BT_NAME是否保存已连接设备的蓝牙名称。
BT_TRIM_ECO0 / BT_TRIM老芯片和新芯片的trim值配置。
BT_SIMPLEPAIRING_FLAG配对模式(0:使用PIN码;1:简单配对)。
BT_PINCODE_LENPIN码长度(最大16字节,默认为4)。
BT_PINCODE默认PIN码(默认为"0000")。
BT_LSTO_DFT连接超时时间(单位为0.625ms,默认为8000,即5秒)。
BT_SNIFF_CLK_SELSniff模式的时钟选择(0:HOSC;1:RC;2:LOSC)。
BT_TX_POWER_LEVEL发射功率级别(默认为21,对应+4dbm)。
BT_PAGE_TX_POWER_LEVEL回连发射功率级别(默认为16)。
BT_INQUIRYSCAN_INTERVALInquiry扫描间隔(默认为0x100)。
BT_INQUIRYSCAN_WINDOWInquiry扫描窗口(默认为0x12)。
BT_PAGESCAN_INTERVALPage扫描间隔(默认为0x1000)。
BT_PAGESCAN_WINDOWPage扫描窗口(默认为0x12)。
BT_PAGE_TIMEOUTPage超时时间(默认为5120ms)。
BT_A2DP_SUPPORT是否支持A2DP协议(默认启用)。
BT_AVRCP_SUPPORT是否支持AVRCP协议(默认启用)。
BT_HFP_SUPPORT是否支持HFP协议(条件启用)。
BT_SPP_SUPPORT是否支持SPP协议(默认禁用)。
BT_HID_SUPPORT是否支持HID协议(默认禁用)。
BT_MFI_SUPPORT是否支持MFI功能(默认禁用)。
BT_OBEX_SUPPORT是否支持OBEX协议(默认禁用)。
BT_PBAP_SUPPORT是否支持PBAP协议(默认禁用)。
BLE_SUPPORT是否支持BLE功能(条件启用)。
BT_AUDIO_AAC_ENABLE是否启用AAC音频支持(条件启用)。
BT_AVRCP_ADVANCED是否启用高级AVRCP功能(默认启用)。
BT_AVRCP_VOLUME_SYNC是否启用音量同步功能(条件启用)。
BT_AVRCP_PLAYER_SETTING是否支持播放器设置功能(默认禁用)。
BT_AVRCP_SONG_PLAY_STATE是否支持歌曲播放状态反馈(默认禁用)。
BT_AVRCP_SONG_TRACK_INFOR是否支持歌曲ID3信息反馈(默认禁用)。
BT_AVRCP_BROWSER_FUNC是否启用AVRCP浏览器功能(默认禁用)。
BT_AUTO_PLAY_MUSICAVRCP连接成功后是否自动播放音乐(默认禁用)。
BT_HFP_SUPPORT_WBS是否支持宽频带语音(WBS)(默认启用)。
BT_HFP_AUDIO_DATAHFP音频数据格式(默认为mSBC)。
BT_HFP_QUIRY_PHONEBOOK是否启用通讯录请求功能(默认禁用)。
BT_HFP_CALL_DURATION_DISP是否显示通话时长(默认启用)。
BT_OBEX_UPDATE_FUNC_SUPPORT是否支持通过OBEX进行固件升级(条件启用)。
BB_EM_MAP_ADDR / BB_EM_SIZEBB EM的映射地址和大小配置。
BT_BASE_MEM_SIZE蓝牙基础内存大小(根据TWS支持情况调整)。
BT_BLE_MEM_SIZEBLE功能的内存大小(根据BLE支持情况调整)。
BT_AUDIO_AAC_MEM_SIZEAAC音频支持的内存大小(根据AAC支持情况调整)。
BT_AVRCP_TG_MEM_SIZEAVRCP TG功能的内存大小(根据相关功能启用情况调整)。
BT_AVRCP_BRWS_MEM_SIZEAVRCP浏览器功能的内存大小(根据功能启用情况调整)。
BT_HFP_MEM_SIZEHFP功能的内存大小(根据功能启用情况调整)。
BT_SPP_MEM_SIZESPP功能的内存大小(根据功能启用情况调整)。
BT_TWS_MEM_SIZETWS功能的内存大小(根据功能启用情况调整)。
BT_HID_MEM_SIZEHID功能的内存大小(根据功能启用情况调整)。
BT_MFI_MEM_SIZEMFI功能的内存大小(根据功能启用情况调整)。
BT_OBEX_MEM_SIZEOBEX功能的内存大小(根据功能启用情况调整)。
BT_PBAP_MEM_SIZEPBAP功能的内存大小(根据功能启用情况调整)。
BT_POR_TRY_COUNTS / BT_POR_INTERNAL_TIME开机自动重连的尝试次数和间隔时间。
BT_BLR_TRY_COUNTS / BT_BLR_INTERNAL_TIMEBB Lost后的自动重连尝试次数和间隔时间。
BT_TWS_TRY_COUNTS / BT_TWS_INTERNAL_TIMETWS自动重连的尝试次数和间隔时间(条件启用)。
BT_TWS_BLR_TRY_COUNTS / BT_TWS_BLR_INTERNAL_TIMETWS Link Loss后的自动重连尝试次数和间隔时间(条件启用)。
BT_FAST_POWER_ON_OFF_FUNC是否支持快速打开/关闭蓝牙功能(条件启用)。
BT_AUTO_CLEAR_LAST_PAIRING_LIST是否在手机端清除配对记录后,同步清理设备端的配对记录。
BT_MATCH_CHECK是否启用匹配检查(默认启用)。

蓝牙初始化函数解读

读懂bt_stack_service.c协议栈

这个C文件bt_stack_service.c是蓝牙协议栈服务的实现,主要功能是初始化和运行蓝牙(包括经典蓝牙BR/EDR和低功耗蓝牙BLE)的核心服务。以下是其核心作用的逐步分析:

  1. 初始化经典蓝牙和BLE协议栈。
  2. 管理协议栈主循环,处理连接、数据传输和音频解码。
  3. 适配硬件层(基带、UART),确保硬件与协议栈协同工作。
  4. 提供调试接口,支持通过串口控制BLE通知等功能。
  5. 状态监控与错误处理,保障蓝牙服务稳定运行。

适用于需要同时支持经典蓝牙(如A2DP音频)和低功耗蓝牙(如通知服务)的嵌入式设备。

1. 蓝牙协议栈初始化

  • BR/EDR初始化
    调用BtStackInit()初始化经典蓝牙模块。若失败,协议栈任务挂起(死循环);成功则继续初始化BLE。
  • BLE初始化
    通过InitBlePlaycontrolProfile()InitBleStack()初始化低功耗蓝牙服务和协议栈,支持BLE通知功能(如att_server_notify发送数据)。

2. 协议栈主循环

rw_main()是蓝牙协议栈的主要运行函数,它是 RW (RF Wireless) IP 协议栈的核心调度函数。从代码结构来看,它主要负责处理蓝牙协议栈的各种事件和消息。

让我们分析一下相关的关键点:

  1. 在主循环中的调用:
while(1)
{
rw_main(); // 运行蓝牙协议栈主循环 这个函数属于底层的蓝牙基带(Baseband)API,通常这部分代码是芯片厂商提供的闭源代码。
BTStackRun(); // 运行蓝牙协议栈上层服务
A2dp_Decode(); // 处理音频解码
}
  1. rw_main()的主要功能:
  • 处理蓝牙协议栈的底层事件
  • 管理蓝牙射频(RF)相关的操作
  • 处理蓝牙数据包的收发
  • 调度和执行各种蓝牙协议任务(如L2CAP, ATT, SMP等)
  1. 相关的重要API:
void Bt_init(void* params);     // 蓝牙初始化
void rw_main(void); // 蓝牙协议栈主循环
void rwip_reset(void); // 重置蓝牙协议栈
  1. 工作流程:
初始化
Bt_init() -> 配置蓝牙参数和初始化协议栈

运行时
硬件中断 -> 产生事件 -> rw_main()处理事件 -> 调用相应的回调函数(如att_write)

这是一个典型的事件驱动架构:

  • 硬件中断触发事件
  • rw_main()在主循环中轮询这些事件
  • 根据事件类型调用相应的处理函数
  • 处理完成后返回主循环继续轮询

所以rw_main()实际上是整个蓝牙协议栈的"心脏",它通过不断轮询和处理事件来保持蓝牙通信的正常运行。这种设计使得系统能够及时响应蓝牙通信事件,同时又不会在中断处理程序中执行过多的业务逻辑。

3. 服务管理与上下文

  • 状态管理
    使用BtStackServiceContext结构体跟踪服务状态(如初始化、错误模式),确保协议栈运行稳定性。
  • 内存与配置管理
    • 全局内存堆gBtHostStackMemHeap为协议栈提供动态内存。
    • BT_CONFIGURATION_PARAMS加载蓝牙配置参数(如设备地址、配对信息)。

4. 硬件层交互

  • 基带初始化
    Bt_init()配置蓝牙基带参数(BB层),确保硬件与协议栈正确通信。
  • 平台接口适配
    通过SetBtPlatformInterface()设置操作系统接口(如任务调度、内存管理),实现跨平台兼容。

5. 错误处理与恢复

  • 初始化异常处理
    初始化失败时进入死循环,防止协议栈异常运行。
  • BB层错误跟踪
    记录基带错误类型(bbErrorType),为后续诊断提供依据。

BLE的写入操作

从代码来看,BLE的写入操作确实是通过中断方式触发的。让我解释一下流程:

  1. BtStackServiceEntrance函数中,系统初始化了BLE栈:
#if (BLE_SUPPORT == ENABLE)
{
InitBlePlaycontrolProfile();
if(!InitBleStack(&g_playcontrol_app_context, &g_playcontrol_profile))
{
BT_DBG("error ble stack init\n");
}
}
#endif
  1. 在主循环中,系统通过rw_main()函数来处理蓝牙协议栈的事件:
while(1)
{
rw_main();
BTStackRun();
// ...
}
  1. 当BLE外设(比如手机)向设备写入数据时,会触发硬件中断。这个中断会被蓝牙协议栈捕获,然后在rw_main()的处理过程中,通过回调机制最终调用到我们之前看到的att_write函数。

调用链大致是这样的:

硬件中断 -> 蓝牙协议栈ISR -> rw_main() -> 协议栈回调 -> att_write()

这种设计是典型的中断驱动模型:

  • 底层硬件接收到BLE数据包会触发中断
  • 中断处理程序将数据包放入缓冲区
  • 主循环中的rw_main()会处理这些缓冲的数据包
  • 当识别到是写入操作时,就会调用att_write函数来处理

这样的设计有几个优点:

  1. 通过中断确保及时响应BLE通信
  2. 通过缓冲区和主循环处理机制避免在中断上下文中执行耗时操作
  3. 将底层的通信细节与应用层的数据处理分离

所以,虽然att_write本身不是直接在中断上下文中执行的,但它的触发确实源于BLE通信的硬件中断。