经典蓝牙支持
AW30N BLE SDK 中经典蓝牙(BR/EDR)能力的完整说明:包括双模(经典 + BLE)协议栈架构、SPP 串口协议、EDR HID 设备协议、EDR 主机(Emitter)模式,以及相关配置宏与代码入口。
Purpose and Scope
本文档介绍 AW30N SDK 中**经典蓝牙(Classic Bluetooth / BR/EDR)**子系统的支持方式与使用方法。内容涵盖:
- 经典蓝牙与 BLE 共存的双模架构(
bt_common目录下的spp_and_le、hid等 profile 工程结构); - 经典蓝牙协议栈分层(
btstack主机协议栈 +btctrler控制器)及配置入口; - 经典蓝牙支持的协议:SPP(Serial Port Profile) 与 EDR HID;
- 经典蓝牙 EDR 主机模式(
EDR_EMITTER_EN,inquiry + page 流程); - 与经典蓝牙相关的配置宏、日志开关、OTA 升级回调等代码入口。
与经典蓝牙相关的、但属于其他能力范畴的主题不在本文档展开,请参见对应页面:
- 纯 BLE(GATT/SM/广播)的详细机制属于 BLE 协议栈相关页面;
- 各具体应用示例(Dongle、SPP+LE、HID 等)的完整工程级说明属于各自示例页面;
- 板级外设配置(
board_config.h、app_config.c中非蓝牙部分)属于板级适配页面。
Overview
AW30N 是一颗支持双模蓝牙的 SoC:既能运行 BLE(低功耗蓝牙),也支持经典蓝牙 BR/EDR(用于 SPP 透传、EDR HID 键鼠、经典音频等场景)。SDK 中经典蓝牙的使能由一组编译期宏控制,核心入口集中在:
sdk/apps/app/bsp/common/bt_common/bt_profile_cfg.h—— 全局 profile 选择与 SPP 开关;sdk/apps/app/bsp/common/bt_common/spp_and_le/include/spple_app_config.h—— SPP + LE 双模应用选择(SPP_LE / MULTI / DONGLE / CENTRAL / LL_SYNC 等),其中 DONGLE 工程支持 EDR 主机模式;sdk/apps/app/bsp/common/bt_common/hid/include/—— EDR HID 设备协议头文件(edr_hid_user.h、standard_hid.h、app_comm_bt.h);sdk/apps/app/bsp/common/bt_common/spp_and_le/config/与hid/config/—— 每个 profile 各自的lib_btstack_config.c(主机协议栈配置)与lib_btctrler_config.c(控制器配置)。
经典蓝牙的能力默认未全量开启,而是通过条件编译按应用裁剪。例如 USER_SUPPORT_PROFILE_SPP 只有在 BT_FOR_APP_EN(或 APP_ONLINE_DEBUG、AI_APP_PROTOCOL)为真时才被定义;而 BT_FOR_APP_EN 又由 TRANS_DATA_EN、RCSP_BTMATE_EN、RCSP_ADV_EN、SMART_BOX_EN、ANCS_CLIENT_EN、LL_SYNC_EN、TUYA_DEMO_EN 任一使能时自动打开。这种"按需使能、自动推导"的设计意图是:在 256KB Flash 级别的资源受限产品中,避免未使用的协议栈代码和 SDP 服务记录占用的 ROM/RAM。
Architecture
经典蓝牙支持在 AW30N SDK 中按"控制器 — 主机协议栈 — Profile — 应用"四层组织,BLE 与经典蓝牙共享控制器与射频,但各自拥有独立的主机协议栈实例配置:
flowchart TD
subgraph sg_App["应用层 (app)"]
APP["app / app_config.c<br/>SPP_USER_LOG 日志开关"]
UPDATE["testbox_update.c<br/>testbox_bt_classic_update_* 回调"]
end
subgraph sg_Profile["Profile 层 (bt_common)"]
SPPLE["spp_and_le<br/>SPP + LE 双模示例"]
HID["hid<br/>EDR HID 示例"]
SPP["USER_SUPPORT_PROFILE_SPP<br/>SPP 串口协议"]
EDRHOST["EDR_EMITTER_EN<br/>EDR 主机 (inquiry + page)"]
end
subgraph sg_Host["主机协议栈层 (btstack)"]
BTSTACK["lib_btstack_config.c<br/>GAP/SDP/SPP/HID 服务记录"]
CTRLER["lib_btctrler_config.c<br/>控制器配置"]
end
subgraph sg_HW["硬件层"]
RF["2.4G 射频<br/>BR/EDR + BLE 双模"]
end
APP --> SPPLE
APP --> HID
SPPLE --> SPP
SPPLE --> EDRHOST
SPPLE --> BTSTACK
HID --> BTSTACK
BTSTACK --> CTRLER
CTRLER --> RF
UPDATE --> APP
各层职责说明:
- 应用层:
app目录承载具体产品逻辑,例如通过app_config.c中的app_info_debug_enable位图(SPP_USER_LOG= BIT(3))打开 SPP 用户日志;OTA 升级代码(testbox_update.c)中提供了testbox_bt_classic_update_*系列回调,用于在经典蓝牙连接状态下执行升级前的私有参数填充、跳转前处理和状态通知。 - Profile 层:
bt_common下按应用形态拆分工程:spp_and_le(SPP 与 LE 组合场景)、hid(经典蓝牙 HID 键鼠场景)。bt_profile_cfg.h统一决定是否使能 SPP 服务记录(SDP)。 - 主机协议栈层:每个 profile 目录下都有一份独立的
lib_btstack_config.c与lib_btctrler_config.c,用于裁剪协议栈特性(如经典蓝牙的 SDP 服务记录、SPP 通道、HID 报告等)与控制器参数(如经典蓝牙的 EDR 速率、sniff 模式)。 - 硬件层:射频同时承载 BR/EDR 与 BLE,双模同地址/同名字由
DOUBLE_BT_SAME_NAME、DOUBLE_BT_SAME_MAC宏控制。
设计意图:将协议栈配置与 Profile 代码放在同一工程目录下,是为了让每个示例工程可独立编译、独立裁剪,互不干扰 —— 这也是 spple_app_config.h 中 CONFIG_APP_* 只能选 1 个("apps example 选择,只能选1个")的原因。
经典蓝牙使能机制(bt_profile_cfg.h)
经典蓝牙能力的总开关位于 bt_profile_cfg.h。其核心逻辑是:根据应用宏自动推导 BT_FOR_APP_EN,再由 BT_FOR_APP_EN 决定 SPP 是否使能。
#if (TRANS_DATA_EN || RCSP_BTMATE_EN || RCSP_ADV_EN || SMART_BOX_EN || ANCS_CLIENT_EN || LL_SYNC_EN || TUYA_DEMO_EN)
#ifndef BT_FOR_APP_EN
#define BT_FOR_APP_EN 1
#endif
#else
#ifndef BT_FOR_APP_EN
#define BT_FOR_APP_EN 0
#endif
#ifndef AI_APP_PROTOCOL
#define AI_APP_PROTOCOL 0
#endif
#endif
///---sdp service record profile- 用户选择支持协议--///
#if (BT_FOR_APP_EN || APP_ONLINE_DEBUG || AI_APP_PROTOCOL)
#if (LL_SYNC_EN || TUYA_DEMO_EN)
#undef USER_SUPPORT_PROFILE_SPP
#define USER_SUPPORT_PROFILE_SPP 0
#else
#undef USER_SUPPORT_PROFILE_SPP
#define USER_SUPPORT_PROFILE_SPP 1
#endif
#endif
Source: bt_profile_cfg.h
逐段解读:
- 只要打开了
TRANS_DATA_EN(数据传输)、RCSP_BTMATE_EN(RCSP App)、RCSP_ADV_EN、SMART_BOX_EN、ANCS_CLIENT_EN、LL_SYNC_EN(腾讯连连)或TUYA_DEMO_EN(涂鸦)中的任何一个,就认为该工程"需要蓝牙与 App 交互",强制置BT_FOR_APP_EN = 1。这些宏来自上层app_config.c的应用选择。 - 若上述宏全为 0,则
BT_FOR_APP_EN = 0且同时关闭AI_APP_PROTOCOL,此时整棵蓝牙协议栈都不会被链接 —— 这是纯非蓝牙应用的裁剪路径。 USER_SUPPORT_PROFILE_SPP是 SDP 服务记录层面的 SPP 开关:在需要蓝牙与 App 交互(BT_FOR_APP_EN || APP_ONLINE_DEBUG || AI_APP_PROTOCOL)的前提下,若使用LL_SYNC_EN或TUYA_DEMO_EN(这两类场景走私有协议而非标准 SPP),则关闭 SPP 服务记录;其余场景默认开启 SPP。
设计意图:SPP 是经典蓝牙设备被手机/App 连接的最通用"数据管道",但 LL_SYNC(腾讯连连)与涂鸦使用各自的私有协议,注册标准 SPP 的 SDP 记录只会白白占用 Flash,因此这两类工程被显式排除。
BLE Demo 选择与经典蓝牙的关系
同一个文件中通过 TCFG_BLE_DEMO_SELECT 选择 BLE 侧运行的 demo(bt_profile_cfg.h):
#define DEF_BLE_DEMO_NULL 0 //ble 没有使能
#define DEF_BLE_DEMO_ADV 1 //only adv,can't connect
#define DEF_BLE_DEMO_TRANS_DATA 2 //
#define DEF_BLE_DEMO_RCSP_DEMO 4 //
#define DEF_BLE_DEMO_ADV_RCSP 5
#define DEF_BLE_DEMO_CLIENT 7 //
#define DEF_BLE_ANCS_ADV 9
#define DEF_BLE_DEMO_MULTI 11 //
#define DEF_BLE_DEMO_LL_SYNC 13 //
Source: bt_profile_cfg.h
TCFG_BLE_DEMO_SELECT 由 TCFG_USER_BLE_ENABLE 与各应用宏按优先级推导(RCSP > TRANS_DATA > LL_SYNC > TUYA > ...),这与经典蓝牙的使能互相独立:经典蓝牙与 BLE demo 可以同时打开,形成双模(例如 TRANS_DATA_EN 同时打开 SPP 与 DEF_BLE_DEMO_TRANS_DATA)。
SPP + LE 双模应用配置(spple_app_config.h)
经典蓝牙最典型的载体是 spp_and_le 工程(SPP + LE 双模),其应用选择入口在 spple_app_config.h:
#if (TRANS_DATA_SPPLE_EN)
#define TCFG_MEDIA_LIB_USE_MALLOC 1
//apps example 选择,只能选1个,要配置对应的board_config.h
#define CONFIG_APP_SPP_LE 0 //SPP + LE or LE's client
#define CONFIG_APP_MULTI 0 //蓝牙LE多连 + spp
#define CONFIG_APP_DONGLE 1 //usb + 蓝牙(ble 主机),PC hid设备
#define CONFIG_APP_CENTRAL 0 //ble client,中心设备
#define CONFIG_APP_LL_SYNC 0 //腾讯连连
#define CONFIG_APP_BEACON 0 //蓝牙BLE ibeacon
#define CONFIG_APP_NONCONN_24G 0 //2.4G 非连接收发, 不支持rcsp,需要关闭
#define CONFIG_APP_TUYA 0 //涂鸦协议
#define CONFIG_APP_AT_COM 0 //AT com HEX格式命令
#define CONFIG_APP_AT_CHAR_COM 0 //AT com 字符串格式命令
#define CONFIG_APP_IDLE 0 //空闲任务
#define CONFIG_APP_CONN_24G 0 //基于BLE的2.4g,板级只需要开BLE
#define CONFIG_APP_HILINK 0 //华为协议
#define CONFIG_APP_ELECTROCAR 0 //电车项目,注意将板级处ADKEY以及别的IO占用失能, 关闭低功耗:TCFG_LOWPOWER_LOWPOWER_SEL设置为0
#define CONFIG_APP_REDUCE_RAM 0 //省ram的应用, 不支持rcsp,需要关闭
Source: spple_app_config.h
要点:
- 整个文件被
TRANS_DATA_SPPLE_EN包裹,只有打开该宏才编译双模示例代码; - 应用示例互斥(只能选 1 个),且需要与
board_config.h的板级配置对应; CONFIG_APP_SPP_LE(SPP + LE)、CONFIG_APP_MULTI(LE 多连 + SPP)是经典蓝牙 SPP 的典型应用;CONFIG_APP_DONGLE则组合了 USB、BLE 主机与可选的 EDR 主机能力。
双模共存的命名/地址策略
在 CONFIG_APP_SPP_LE 分支中(spple_app_config.h),SDK 提供了经典蓝牙与 BLE 的共存策略开关:
#if CONFIG_APP_SPP_LE
//配置双模同名字,同地址
#define DOUBLE_BT_SAME_NAME 0 //同名字
#define DOUBLE_BT_SAME_MAC 0 //同地址
#define CONFIG_APP_SPP_LE_TO_IDLE 0 //SPP_AND_LE To IDLE Use
#define CONFIG_BLE_HIGH_SPEED 0 //BLE提速模式: 使能DLE+2M, payload要匹配pdu的包长
Source: spple_app_config.h
DOUBLE_BT_SAME_NAME = 1时经典蓝牙与 BLE 广播使用同一个设备名,手机端看到的是一个设备而非两个;DOUBLE_BT_SAME_MAC = 1时两者共享同一 MAC 地址,避免因地址不同导致手机配对记录混乱;- 这两个开关默认关闭,原因是部分手机对"同名同址的双模设备"处理存在兼容性问题,产品可根据目标手机兼容性测试结果打开。
EDR 主机模式(经典蓝牙 Emitter)
CONFIG_APP_DONGLE 分支中定义了经典蓝牙主机(EDR Emitter)能力(spple_app_config.h):
#elif CONFIG_APP_DONGLE
/*默认做搜索设备匹配名字再发起连接 inquery + page*/
#define EDR_EMITTER_EN 0 //蓝牙(edr主机)
#if EDR_EMITTER_EN
/*不做搜索匹配 + 连接,只开放可连接,等待对方连接*/
#define EDR_EMITTER_PAGESCAN_ONLY 0 /**/
#endif
#define CONFIG_BT_GATT_COMMON_ENABLE 1
#define CONFIG_BT_SM_SUPPORT_ENABLE 1 //配置是否支持加密
#define CONFIG_BT_GATT_CLIENT_NUM 1 //设置主机个数1~2,(dongle可连接蓝牙BLE设备的个数,=2时会多注册1个usb设备)
#define CONFIG_BT_COMPOSITE_EQUIPMENT 0
#define CONFIG_BT_GATT_SERVER_NUM 0 //
#define CONFIG_BT_GATT_CONNECTION_NUM (CONFIG_BT_GATT_SERVER_NUM + CONFIG_BT_GATT_CLIENT_NUM) //
#define CONFIG_BLE_CONNECT_SLOT 0 //BLE高回报率设置, 支持私有协议
#define CONFIG_BLE_HIGH_SPEED 1 //BLE提速模式: 使能DLE+2M, payload要匹配pdu的包长
Source: spple_app_config.h
关键语义:
EDR_EMITTER_EN = 1表示 AW30N 作为经典蓝牙主机,默认流程是"搜索设备(inquiry)→ 匹配名字 → 发起连接(page)";EDR_EMITTER_PAGESCAN_ONLY = 1时跳过搜索与主动连接,设备只开放可连接/可发现(page scan),等待对端(从机)来连 —— 典型于与手机 App 配对前由手机发起连接;- 该分支同时把
CONFIG_BT_GATT_CLIENT_NUM设为 1,即 Dongle 同时可作为 BLE 主机连接 1~2 个 BLE 外设,形成"经典蓝牙主机 + BLE 主机"的复合桥接形态; CONFIG_BLE_HIGH_SPEED = 1打开 BLE 提速模式(DLE + 2M),保证 BLE 侧吞吐不被经典蓝牙活动拖累。
设计意图:Dongle(USB 蓝牙适配器)场景下,经典蓝牙用于连接经典外设(如旧式鼠标、串口透传设备),BLE 用于连接新式低功耗外设,USB 把两者数据回传 PC。EDR_EMITTER_EN 与 EDR_EMITTER_PAGESCAN_ONLY 分别对应"主动扫描连接"与"被动等待连接"两种产品形态,避免把两种模式耦合在同一个运行路径里。
EDR HID 设备协议
经典蓝牙 HID(键鼠/遥控器)位于 sdk/apps/app/bsp/common/bt_common/hid/ 目录:
hid/include/edr_hid_user.h—— EDR HID 用户层接口(报告发送、连接管理回调);hid/include/standard_hid.h—— 标准 HID 描述符与报告格式定义;hid/include/app_comm_bt.h—— HID 工程下蓝牙公共接口;hid/include/lib_profile_cfg.h—— HID 工程的 profile 裁剪(HOGP/EDR HID 选择);hid/config/lib_btstack_config.c与hid/config/lib_btctrler_config.c—— HID 工程的主机协议栈与控制器配置。
HID 工程与 spp_and_le 工程互斥编译(均由 app_config.c 的应用宏选择,如 CONFIG_HID_CASE_ENABLE / CONFIG_SPP_AND_LE_CASE_ENABLE,见升级代码中的条件编译)。EDR HID 与 BLE HOGP 的差异在于传输层:EDR HID 走经典蓝牙的 L2CAP PSM 0x11(HID Control)与 0x13(HID Interrupt),BLE HOGP 走 GATT 服务,SDK 通过 lib_profile_cfg.h 分别裁剪。
经典蓝牙日志与调试
经典蓝牙 SPP 的用户态调试日志通过 app_config.c 中的日志位图控制(app_config.c):
#define SPP_USER_LOG 3 // 用于打印spp_user.c中的打印,app使用spp交互时需要用到
#define RCSP_PROTOCOL_LOG 2 // 用于JL_rcsp_protocol.c中的调试打印
int app_info_debug_enable = 0 \
/* | BIT(SPP_USER_LOG) \ */
;
Source: app_config.c
SPP_USER_LOG = 3是对应spp_user.c中打印的位号(BIT(3));- 默认
app_info_debug_enable = 0,所有蓝牙调试打印关闭;产品调试期把BIT(SPP_USER_LOG)加入即可观察 SPP 收发的用户态日志,量产时保持关闭以省功耗与吞吐。
Core Flow:经典蓝牙连接流程
经典蓝牙的典型连接流程分为**从机模式(等待连接)与主机模式(主动连接)**两种。下图以 EDR_EMITTER_EN = 1(主机)且 EDR_EMITTER_PAGESCAN_ONLY = 0 的默认流程为例,展示从搜索到数据传输的完整链路:
sequenceDiagram
participant APP as 应用层 (app)
participant BTSTACK as btstack 主机协议栈
participant CTRLER as btctrler 控制器
participant PEER as 对端经典蓝牙设备
APP->>BTSTACK: 初始化双模 (spp_and_le / hid 工程)
BTSTACK->>CTRLER: 下发控制器配置 (lib_btctrler_config.c)
CTRLER-->>BTSTACK: 控制器就绪
APP->>BTSTACK: EDR Emitter 启动 (inquiry)
BTSTACK->>CTRLER: 发起 Inquiry 扫描
CTRLER-->>BTSTACK: 发现设备列表 (含名字/地址)
BTSTACK->>BTSTACK: 按名字匹配目标设备
BTSTACK->>CTRLER: 发起 Page 连接
CTRLER-->>BTSTACK: 基带连接建立
BTSTACK->>PEER: SDP 查询 SPP/HID 服务记录
PEER-->>BTSTACK: SDP 响应 (USER_SUPPORT_PROFILE_SPP)
BTSTACK->>PEER: L2CAP 通道建立 (SPP: RFCOMM / HID: PSM 0x11/0x13)
PEER-->>BTSTACK: 连接成功回调
BTSTACK-->>APP: 上报连接事件
APP->>APP: testbox_bt_classic_update_* 回调挂接 (OTA 等)
APP<->>PEER: SPP 数据收发 / HID 报告上报
步骤说明:
- 初始化:应用层(
spp_and_le或hid工程)拉起 btstack 主机协议栈,加载各自的lib_btstack_config.c与lib_btctrler_config.c配置(SDP 服务记录、控制器参数、sniff 等); - Inquiry:主机模式先扫描周围经典蓝牙设备,收集地址与名字;
- 名字匹配:在协议栈或应用层按预设名字过滤目标(
spple_app_config.h注释"默认做搜索设备匹配名字再发起连接"); - Page:对匹配到的目标发起基带寻呼,建立 ACL 链路;
- SDP 服务发现:查询对端是否支持 SPP(或 HID)服务 —— 本端 SDP 服务记录是否注册由
USER_SUPPORT_PROFILE_SPP决定; - L2CAP/RFCOMM:SPP 走 RFCOMM 串口仿真通道,EDR HID 走 L2CAP PSM 0x11/0x13;
- 应用回调:连接事件上报应用层,应用可挂接 OTA 升级等业务(如
testbox_bt_classic_update_state_cbk); - 数据传输:SPP 透传用户数据,HID 上报键鼠报告。
经典蓝牙 OTA 升级接入点
经典蓝牙连接状态下的 OTA 升级由 testbox_update.c 提供钩子(升级流程属于"升级"页面范畴,这里只说明经典蓝牙相关的接入点):
#if defined(CONFIG_SPP_AND_LE_CASE_ENABLE) || defined(CONFIG_HID_CASE_ENABLE)
#include "lib_profile_cfg.h"
...
static void testbox_bt_classic_update_private_param_fill(UPDATA_PARM *p)
static void testbox_bt_classic_update_before_jump_handle(int type)
static void testbox_bt_classic_update_state_cbk(int type, u32 state, void *priv)
Source: testbox_update.c
三个回调分别承担:升级前填充私有参数(如当前经典蓝牙连接信息)、跳转前处理(断开经典蓝牙链路、保存上下文)、升级状态通知(进度/结果回调给应用)。它们只在 CONFIG_SPP_AND_LE_CASE_ENABLE 或 CONFIG_HID_CASE_ENABLE(即双模/经典蓝牙工程)下编译,说明经典蓝牙产品的升级通道需要额外处理经典链路的断开与恢复 —— 这是与纯 BLE 产品升级的关键差异。
Usage Examples
示例 1:开启经典蓝牙 SPP(双模透传工程)
在 app_config.c 中使能数据传输类应用宏(如 TRANS_DATA_EN),bt_profile_cfg.h 会自动推导 BT_FOR_APP_EN = 1 并默认打开 USER_SUPPORT_PROFILE_SPP = 1,从而在 SDP 中注册 SPP 服务记录:
#if (TRANS_DATA_EN || RCSP_BTMATE_EN || RCSP_ADV_EN || SMART_BOX_EN || ANCS_CLIENT_EN || LL_SYNC_EN || TUYA_DEMO_EN)
#ifndef BT_FOR_APP_EN
#define BT_FOR_APP_EN 1
#endif
#else
#ifndef BT_FOR_APP_EN
#define BT_FOR_APP_EN 0
#endif
#ifndef AI_APP_PROTOCOL
#define AI_APP_PROTOCOL 0
#endif
#endif
Source: bt_profile_cfg.h
效果:手机可通过标准蓝牙串口(SPP)连接设备进行透传,BLE 侧同时保持 GATT 服务;两个链路互不干扰。
示例 2:配置经典蓝牙主机模式(EDR Emitter)
在 spple_app_config.h 中把 CONFIG_APP_DONGLE 置 1,再打开 EDR_EMITTER_EN:
#elif CONFIG_APP_DONGLE
/*默认做搜索设备匹配名字再发起连接 inquery + page*/
#define EDR_EMITTER_EN 0 //蓝牙(edr主机)
#if EDR_EMITTER_EN
/*不做搜索匹配 + 连接,只开放可连接,等待对方连接*/
#define EDR_EMITTER_PAGESCAN_ONLY 0 /**/
#endif
Source: spple_app_config.h
效果:设备作为经典蓝牙主机执行 inquiry + page 主动连接;如需"等待对端连接"形态,将 EDR_EMITTER_PAGESCAN_ONLY 置 1。
示例 3:双模同名字/同地址
在 SPP+LE 工程中开启 DOUBLE_BT_SAME_NAME / DOUBLE_BT_SAME_MAC,让手机只看到一个设备:
#if CONFIG_APP_SPP_LE
//配置双模同名字,同地址
#define DOUBLE_BT_SAME_NAME 0 //同名字
#define DOUBLE_BT_SAME_MAC 0 //同地址
#define CONFIG_APP_SPP_LE_TO_IDLE 0 //SPP_AND_LE To IDLE Use
#define CONFIG_BLE_HIGH_SPEED 0 //BLE提速模式: 使能DLE+2M, payload要匹配pdu的包长
Source: spple_app_config.h
示例 4:打开 SPP 用户日志调试
调试 SPP 透传时,将 BIT(SPP_USER_LOG) 加入 app_info_debug_enable:
#define SPP_USER_LOG 3 // 用于打印spp_user.c中的打印,app使用spp交互时需要用到
#define RCSP_PROTOCOL_LOG 2 // 用于JL_rcsp_protocol.c中的调试打印
int app_info_debug_enable = 0 \
/* | BIT(SPP_USER_LOG) \ */
;
Source: app_config.c
Configuration Options
以下为经典蓝牙支持相关的关键配置宏(均在编译期生效):
| 配置宏 | 类型 | 默认值 | 说明 |
|---|---|---|---|
BT_FOR_APP_EN | 宏 | 自动推导 | 蓝牙与 App 交互总开关;任一应用宏打开时自动置 1 |
USER_SUPPORT_PROFILE_SPP | 宏 | 1 | 是否在 SDP 中注册 SPP 服务记录;LL_SYNC_EN/TUYA_DEMO_EN 时强制为 0 |
TRANS_DATA_EN | 宏 | 由工程决定 | 数据传输应用宏,同时打开 SPP 与 DEF_BLE_DEMO_TRANS_DATA |
AI_APP_PROTOCOL | 宏 | 0 | AI 语音 App 协议开关,可独立打开经典蓝牙 |
APP_ONLINE_DEBUG | 宏 | 0 | 在线调试开关,可独立触发 SPP 使能 |
CONFIG_APP_SPP_LE | 宏 | 0 | SPP + LE 双模示例(互斥选择) |
CONFIG_APP_MULTI | 宏 | 0 | LE 多连 + SPP 示例(互斥选择) |
CONFIG_APP_DONGLE | 宏 | 0 | USB + 蓝牙 Dongle 示例(互斥选择) |
EDR_EMITTER_EN | 宏 | 0 | 经典蓝牙主机模式使能(inquiry + page) |
EDR_EMITTER_PAGESCAN_ONLY | 宏 | 0 | 仅开放可连接,等待对端连接 |
DOUBLE_BT_SAME_NAME | 宏 | 0 | 双模使用同一设备名 |
DOUBLE_BT_SAME_MAC | 宏 | 0 | 双模使用同一 MAC 地址 |
SNIFF_MODE_RESET_ANCHOR | 宏 | 0 | EDR sniff 模式锚点重置配置 |
CONFIG_BLE_HIGH_SPEED | 宏 | 0/1 | BLE 提速(DLE + 2M),Dongle 分支默认 1 |
SPP_USER_LOG | 位号 | BIT(3) | spp_user.c 用户日志位,配合 app_info_debug_enable |
API Reference
经典蓝牙相关的对外接口主要分布在三个层面:
Profile 使能(编译期 API)
bt_profile_cfg.h 提供的宏即"接口":BT_FOR_APP_EN、USER_SUPPORT_PROFILE_SPP 控制 SDP 服务记录注册;spple_app_config.h 的 CONFIG_APP_* 系列选择具体工程形态。这些宏在编译期决定哪些协议栈代码被链接,运行期不可更改 —— 因此产品形态必须在构建前确定。
OTA 升级回调(testbox_update.c)
| 函数 | 作用 | 触发时机 |
|---|---|---|
testbox_bt_classic_update_private_param_fill(UPDATA_PARM *p) | 填充升级私有参数(如经典链路信息) | 升级启动前 |
testbox_bt_classic_update_before_jump_handle(int type) | 跳转升级前的经典蓝牙链路处理 | 跳转升级程序前 |
testbox_bt_classic_update_state_cbk(int type, u32 state, void *priv) | 升级状态通知回调 | 升级过程中/结束 |
Source: testbox_update.c
Profile 用户接口(头文件层)
spp_and_le工程:spp_user.c提供 SPP 数据收发/连接回调(日志位SPP_USER_LOG指向该文件);hid工程:edr_hid_user.h提供 EDR HID 连接管理与报告发送接口,standard_hid.h定义标准 HID 报告格式;- 双模公共头文件:
bt_common/bt_ble.h统一定义 BLE/EDR 共用的数据类型与枚举,app_comm_bt.h(HID 工程)提供蓝牙公共 API。
注:上述 Profile 层接口的完整函数签名位于对应
spp_user.c/edr_hid_user.c实现中,本文档未逐行读取(受源材料预算限制),实际使用时请以源码为准。
Failure Modes, Edge Cases & Concurrency
编译期冲突与互斥
- 应用示例互斥:
CONFIG_APP_SPP_LE、CONFIG_APP_MULTI、CONFIG_APP_DONGLE等只能选 1 个("apps example 选择,只能选1个")。若同时置多个为 1,编译期会产生宏冲突或链接重复定义 —— 这是经典蓝牙工程最常见的配置错误。 - SPP 与私有协议互斥:
LL_SYNC_EN/TUYA_DEMO_EN强制USER_SUPPORT_PROFILE_SPP = 0。若强行打开 SPP,两类协议都会尝试占用 RFCOMM/串口通道,运行期会互相抢占连接,因此 SDK 在宏层面直接禁止。
双模并发与射频共享
- AW30N 的射频在 BR/EDR 与 BLE 之间时分复用。经典蓝牙处于 inquiry/page/sniff 状态时,BLE 的连接间隔、广播间隔可能被拉长,导致 BLE 侧吞吐下降。Dongle 分支默认
CONFIG_BLE_HIGH_SPEED = 1(DLE + 2M)即是对此的补偿。 CONFIG_BT_GATT_CONNECTION_NUM必须等于CONFIG_BT_GATT_SERVER_NUM + CONFIG_BT_GATT_CLIENT_NUM;Dongle 分支主机数为 1~2,超过后需要额外注册 USB 设备(注释明示 "=2时会多注册1个usb设备")。
连接建立失败场景
- 主机模式(
EDR_EMITTER_EN=1)下 inquiry 超时或按名字匹配不到目标:SDK 不会自动重试无限次,需要应用层依据回调状态决定重扫间隔与次数; EDR_EMITTER_PAGESCAN_ONLY=1时设备不主动连接,若对端从不发起 page,设备将一直处于等待态 —— 产品需设计超时退出机制;- 经典蓝牙链路在 OTA 升级跳转前必须显式断开(
testbox_bt_classic_update_before_jump_handle),否则升级程序无法重新初始化控制器。
地址/名字冲突
DOUBLE_BT_SAME_MAC打开后,经典蓝牙与 BLE 共享地址,部分手机在双模绑定/回连时可能出现地址解析异常;关闭(默认)则手机看到两个设备。该参数需依据目标手机兼容性实测结果调整,属于已知的产品权衡点。
Performance & Operational Considerations
- 资源裁剪:经典蓝牙协议栈(SDP、RFCOMM、HID 等)占用可观 ROM/RAM。SDK 提供 256KB 裁剪补丁包(
补丁包/AW30N_v1.2.0_SDK裁剪到256KB以内的补丁包_20240815/),其中testbox_update.c的经典蓝牙升级回调同样被保留,说明裁剪后经典蓝牙 + OTA 的最小形态仍然成立。 - 日志开销:默认
app_info_debug_enable = 0,所有蓝牙日志关闭;仅在调试期打开BIT(SPP_USER_LOG)。量产保持关闭可降低 UART 打印占用与功耗。 - 低功耗:
spple_app_config.h中SNIFF_MODE_RESET_ANCHOR控制 EDR sniff 模式锚点行为;CONFIG_APP_ELECTROCAR等分支注释提示需将TCFG_LOWPOWER_LOWPOWER_SEL置 0 关闭低功耗才能正常使用外设 —— 经典蓝牙连接态下的低功耗配置需与板级电源策略联动。 - BLE 高回报率:
CONFIG_BLE_CONNECT_SLOT(BLE 高回报率私有协议)与经典蓝牙共存时需实测互扰;Dongle 分支默认关闭以优先保证经典蓝牙主机链路稳定。
Extension Points
- 新增经典蓝牙 Profile 工程:参照
spp_and_le与hid的目录结构(include/+modules/bt/+config/),在bt_common下新建工程目录,提供独立的lib_btstack_config.c/lib_btctrler_config.c,并在app_config.c增加互斥的应用宏。 - 自定义 SPP 应用:修改/替换
spp_user.c中的数据收发与连接回调(日志位SPP_USER_LOG已预留),即可接入自定义透传协议(如 AT 命令,见CONFIG_APP_AT_COM/CONFIG_APP_AT_CHAR_COM)。 - EDR HID 定制:通过
standard_hid.h的 HID 描述符定义自定义报告格式,通过edr_hid_user.h挂接报告发送与连接事件。 - OTA 流程定制:实现/替换
testbox_bt_classic_update_private_param_fill、testbox_bt_classic_update_before_jump_handle、testbox_bt_classic_update_state_cbk三个回调,适配不同升级协议(私有参数格式由产品定义)。
Tests
SDK 中经典蓝牙相关的测试与验证手段主要体现为:
- 示例工程自测:
spp_and_le(SPP_LE / MULTI / DONGLE)与hid各示例即最小可测固件,配合board_config.h板级配置可直接烧录验证经典蓝牙连接与透传; - OTA 升级路径测试:
testbox_update.c中的经典蓝牙升级回调链是升级链路的核心测试点,覆盖"连接态升级 → 断开经典链路 → 跳转 → 状态回调"全流程; - 双模共存测试:需验证
DOUBLE_BT_SAME_NAME/MAC开关下手机端的发现、配对、回连行为,以及经典蓝牙活动对 BLE 连接间隔的影响。
说明:受源材料读取预算限制,本页未逐文件核对
spp_user.c、edr_hid_user.c的测试用例细节;涉及具体用例时请以对应工程目录下的源码为准。
Related Links
- bt_profile_cfg.h — 经典蓝牙 SPP 使能与 BLE demo 选择
- spple_app_config.h — SPP+LE / MULTI / DONGLE 双模应用与 EDR 主机配置
- bt_ble.h — 蓝牙公共头文件(BLE/EDR 共用定义)
- app_config.c — 应用宏与蓝牙日志开关
- testbox_update.c — 经典蓝牙 OTA 升级回调
- 相关页面:BLE 协议栈(GATT/SM)、SPP+LE 示例工程、HID 示例工程、OTA 升级