蓝牙模块选择与配置
本文档讲解 fw-AC63_BT_SDK 中蓝牙控制器(btctrler)的模块选择机制与配置体系:如何通过应用层宏开关决定编译进固件的蓝牙模块(经典蓝牙 Classic / 低功耗蓝牙 LE),如何通过 config_btctler_* 系列配置常量裁剪代码、设定模式与功能位,以及这些配置在运行时如何被业务代码查询。
Purpose and Scope
本页面向 SDK 二次开发者,完整覆盖「蓝牙模块选择与配置」这一能力边界内的内容:
- 模块开关模型:
BT_MODULE_CLASSIC/BT_MODULE_LE位定义、config_btctler_modules的推导规则(由TCFG_USER_BLE_ENABLE/TCFG_USER_EDR_ENABLE组合而来)。 - 运行时查询宏:
BT_MODULES_IS_SUPPORT、STACK_MODULES_IS_SUPPORT、BT_MODE_IS、BT_HCI_STANDARD_IS_SUPPORT、BT_FUNCTION_IS的语义与使用场景。 - 控制器模式与 HCI 标准:
config_btctler_mode(CONFIG_BT_MODE)、config_btctler_hci_standard的取值逻辑。 - LE 侧细化配置:角色(roles)、特性(features)、硬件链路数(hw_nums)、RX 缓冲数、ACL 包长、多链路(multilink)的自动推导。
- Classic 侧细化配置:发射功率、DUT/FCC 测试开关、LMP 选项、AFH、TWS 相关 slot 配置。
- 运行时调节 API:
set_bt_version、bt_max_pwr_set、ble_set_fix_pwr、bredr_set_fix_pwr、bt_osc_offset_ext_*等。
不在本页范围:HCI 传输层(hci_transport.h 相关内容)、蓝牙协议栈上层应用(GATT 服务编写、SPP 业务、HID 报告)属于兄弟页面;本页只负责「选什么模块、怎么配」,不展开「配好之后如何写业务」。
Overview
杰理 AC63 系列蓝牙 SDK 采用**「编译期裁剪 + 运行时查询」的模块化设计。蓝牙控制器库(btctrler)以静态库/源码形式接入工程,通过链接期优化(LTO)在链接时删除未被启用的模块代码,从而节省 Flash 空间。因此,模块选择必须在编译前**通过宏配置完成,业务代码再通过一组位运算宏在运行时判断当前固件是否支持某个模块,避免调用到未链接的代码导致链接错误或运行异常。
这套机制的核心是一组 extern const int 配置常量(由各应用工程的 lib_btctrler_config.c 提供定义)与一组位掩码宏(由 btcontroller_modules.h 声明)。配置常量一旦确定,就被 LTO 视为常量传播的输入:未使用的分支与函数会被整体裁剪。业务代码必须使用 BT_MODULES_IS_SUPPORT(x) 这类宏来查询能力,而不是直接假设模块存在——这正是 apps/hid/examples/keyboard/app_keyboard.c 中「not support ble, make sure config !!!」告警的由来。
典型使用场景:
- 纯 BLE 产品(如 Mesh 灯控、HID 键盘)只需
BT_MODULE_LE,可裁剪全部 EDR 协议栈; - 经典蓝牙音箱需要
BT_MODULE_CLASSIC,按需决定是否同时启用 LE; - 双模产品(如 SPP + LE 透传)同时启用两个模块;
- 产测/认证场景需要打开 DUT/FCC 测试码与固定功率配置。
Architecture
flowchart TD
subgraph sg_App["应用层 (apps/*)"]
AppCfg["app_config.h<br/>TCFG_USER_BLE_ENABLE / TCFG_USER_EDR_ENABLE"]
AppCode["业务代码<br/>testbox_update.c / app_keyboard.c"]
end
subgraph sg_Cfg["控制器配置层 (各工程 config/ 目录)"]
CfgModules["lib_btctrler_config.c<br/>config_btctler_modules"]
CfgMode["config_btctler_mode / config_btctler_hci_standard"]
CfgLE["config_btctler_le_* 系列"]
CfgClassic["CONFIG_* / config_bredr_* 系列"]
end
subgraph sg_Hdr["模块定义头文件 (include_lib/btctrler)"]
HdrMacro["btcontroller_modules.h<br/>BT_MODULE_CLASSIC / BT_MODULE_LE"]
HdrCheck["BT_MODULES_IS_SUPPORT(x) 等查询宏"]
end
subgraph sg_LTO["链接期优化 (LTO)"]
LTO["未启用的模块代码被整体裁剪<br/>Flash / RAM 空间优化"]
end
AppCfg -->|"编译期宏开关"| CfgModules
CfgModules -->|"extern const int 定义"| HdrMacro
HdrCheck -->|"位与运算查询"| HdrMacro
AppCode -->|"运行时能力判断"| HdrCheck
HdrMacro --> LTO
CfgMode --> LTO
CfgLE --> LTO
CfgClassic --> LTO
架构说明:应用层开关(TCFG_USER_BLE_ENABLE / TCFG_USER_EDR_ENABLE)是唯一需要开发者手工编辑的入口;配置层 lib_btctrler_config.c 把它们翻译成控制器库可识别的位掩码常量(config_btctler_modules),并进一步推导出 LE/Classic 的资源数量;头文件层把这些常量暴露为宏,供业务代码在运行时做能力查询;LTO 编译器依据常量值裁剪未启用的代码。开发者只应修改应用层开关与各常量定义,不应绕过宏直接调用控制器内部函数。
模块选择机制
模块位定义
include_lib/btctrler/btcontroller_modules.h 定义了两种蓝牙模块的位掩码,以及查询宏。文件头注释明确说明这套机制是为 LTO(链接期优化)下的代码空间优化 而设计:
/*
*-------------------Module SUPPORT
* brief : 运行时优化(LTO)下,代码空间优化;
*/
#define BT_MODULE_CLASSIC BIT(0)
#define BT_MODULE_LE BIT(1)
extern const int config_btctler_modules;
#define BT_MODULES_IS_SUPPORT(x) (config_btctler_modules & (x))
/*-----------------------------------------------------------*/
extern const int config_stack_modules;
#define STACK_MODULES_IS_SUPPORT(x) (config_stack_modules & (x))
BT_MODULE_CLASSIC = BIT(0):经典蓝牙(EDR/BR)模块;BT_MODULE_LE = BIT(1):低功耗蓝牙(BLE)模块;config_btctler_modules是控制器库的模块开关,定义权在应用工程;config_stack_modules是协议栈(btstack)的模块开关,对应上层BT_BTSTACK_LE等能力位。
由于两个模块位互不重叠(BIT(0) / BIT(1)),config_btctler_modules 可以同时置位实现双模,查询宏使用简单的位与即可判断,开销为零,可安全用于热路径。
应用层开关到模块常量的推导
config_btctler_modules 不是手工维护的,而是由应用工程 app_config.h 中的两个宏推导而来。以 apps/hid/config/lib_btctrler_config.c 为例:
/**
* @brief Bluetooth Module
*/
#if (TCFG_USER_BLE_ENABLE)
#if (TCFG_USER_EDR_ENABLE)
const int config_btctler_modules = BT_MODULE_CLASSIC | BT_MODULE_LE;
#else
const int config_btctler_modules = BT_MODULE_LE;
#endif
#else
#if (TCFG_USER_EDR_ENABLE)
const int config_btctler_modules = BT_MODULE_CLASSIC;
#else
const int config_btctler_modules = 0;
#endif
#endif
推导规则形成一张四象限决策表:
flowchart TD
Start(["app_config.h 编译期宏"]) --> BLE{"TCFG_USER_BLE_ENABLE?"}
BLE -->|"是"| EDR1{"TCFG_USER_EDR_ENABLE?"}
EDR1 -->|"是"| Both["config_btctler_modules =<br/>BT_MODULE_CLASSIC | BT_MODULE_LE<br/>(双模)"]
EDR1 -->|"否"| OnlyLE["config_btctler_modules = BT_MODULE_LE<br/>(纯 BLE)"]
BLE -->|"否"| EDR2{"TCFG_USER_EDR_ENABLE?"}
EDR2 -->|"是"| OnlyEDR["config_btctler_modules = BT_MODULE_CLASSIC<br/>(纯经典)"]
EDR2 -->|"否"| None["config_btctler_modules = 0<br/>(无蓝牙)"]
Both --> Use["BT_MODULES_IS_SUPPORT(x)<br/>运行时能力查询"]
OnlyLE --> Use
OnlyEDR --> Use
None --> Use
设计意图:把「产品形态」与「库裁剪」解耦。产品经理/驱动工程师只需在 app_config.h 声明 TCFG_USER_BLE_ENABLE 与 TCFG_USER_EDR_ENABLE,控制器库的裁剪配置自动跟随,避免两处开关不一致导致链接错误。例如 apps/mesh/lib_config/lib_btctrler_config.c 中 Mesh 工程直接固定为 BT_MODULE_LE(Mesh 仅依赖 BLE),而 apps/spp_and_le 与 apps/hid 则按同一套 TCFG_USER_* 推导。
来源:lib_btctrler_config.c (apps/mesh) | lib_btctrler_config.c (apps/spp_and_le)
模式选择与 HCI 标准
除模块开关外,控制器还有模式(Mode)与HCI 标准两个维度:
#if (CONFIG_BT_MODE != BT_NORMAL)
const int config_btctler_hci_standard = 1;
#else
const int config_btctler_hci_standard = 0;
#endif
const int config_btctler_mode = CONFIG_BT_MODE;
config_btctler_mode直接透传CONFIG_BT_MODE,业务代码用BT_MODE_IS(x)查询(例如是否为BT_NORMAL);config_btctler_hci_standard在非BT_NORMAL模式下置 1,表示控制器使用标准 HCI 接口(供外部 MCU/产测工具通过 HCI 命令访问),查询宏为BT_HCI_STANDARD_IS_SUPPORT(x)。
功能位开关
config_bt_function 是面向控制器内部特性的位掩码:
extern const int config_bt_function ;
#define BT_ENCTRY_TASK BIT(0)
#define BT_MASTER_AFH BIT(1)
#define BT_MASTER_QOS BIT(2)
#define BT_FUNCTION_IS(x) (config_bt_function & (x))
其中 BT_MASTER_AFH 与 BT_MASTER_QOS 分别控制主设备自适应跳频与 QoS 能力,默认配置 config_bt_function = 0(全部关闭),需要时按位或开启。
蓝牙版本号运行时设置
头文件同时暴露了蓝牙核心规范版本号常量与运行时设置接口,应用可在 BT_STATUS_INIT_OK 事件中调用:
/* app 层修改蓝牙版本,可在BT_STATUS_INIT_OK case
调用 set_bt_version 函数更改蓝牙版本号
*/
#define BLUETOOTH_CORE_SPEC_42 0x08
#define BLUETOOTH_CORE_SPEC_50 0x09
#define BLUETOOTH_CORE_SPEC_51 0x0a
#define BLUETOOTH_CORE_SPEC_52 0x0b
extern void set_bt_version(u8 version);
与模块裁剪不同,版本号是运行时可调的——同一固件可以按产品需求上报 4.2 / 5.0 / 5.1 / 5.2,无需重新编译。
LE 侧细化配置
当 TCFG_USER_BLE_ENABLE 打开时,lib_btctrler_config.c 会根据上层宏自动推导 BLE 控制器的能力位、角色与硬件资源数量。这些常量直接决定 LTO 后 BLE 协议栈的规模与并发能力。
能力位(features)与 ACL 包长
#if CONFIG_BLE_HIGH_SPEED
const uint64_t config_btctler_le_features = SET_ENCRYPTION_CFG | SET_SELECT_PHY_CFG | LE_DATA_PACKET_LENGTH_EXTENSION | LE_2M_PHY | EXT_ADV_CFG;
const int config_btctler_le_acl_packet_length = 251;
#else
const uint64_t config_btctler_le_features = SET_ENCRYPTION_CFG | SET_SELECT_PHY_CFG | EXT_ADV_CFG;
const int config_btctler_le_acl_packet_length = 27;
#endif
CONFIG_BLE_HIGH_SPEED = 1时启用LE_DATA_PACKET_LENGTH_EXTENSION(DLE)与LE_2M_PHY(2M 物理层),ACL 数据包长提升到 251 字节,适合高速透传;- 默认 27 字节标准包长,节省 RAM 缓冲;
EXT_ADV_CFG由CONFIG_BT_EXT_ADV_MODE决定,开启后追加LE_EXTENDED_ADVERTISING | LE_PERIODIC_ADVERTISING | CHANNEL_SELECTION_ALGORITHM_2,同时EXT_ADV_CFG_HW = 2(扩展广播/扫描/建链各占硬件资源)。
角色(roles)与多链路(multilink)
#if CONFIG_BT_GATT_SERVER_NUM
#define SET_SLAVE_ROLS_CFG (LE_ADV | LE_SLAVE)
#else
#define SET_SLAVE_ROLS_CFG 0
#endif
#if CONFIG_BT_GATT_CLIENT_NUM
#define SET_MASTER_ROLS_CFG (LE_SCAN | LE_INIT | LE_MASTER)
const int config_btctler_le_afh_en = 1;
#else
#define SET_MASTER_ROLS_CFG 0
const int config_btctler_le_afh_en = 0;
#endif
// multi-link config, 带主从多机只开slave_multilink就可以
#if (CONFIG_BT_GATT_SERVER_NUM > 1)
const int config_btctler_le_slave_multilink = 1;
const int config_btctler_le_master_multilink = 0;
#elif (CONFIG_BT_GATT_SERVER_NUM && CONFIG_BT_GATT_CLIENT_NUM)
const int config_btctler_le_slave_multilink = 1;
const int config_btctler_le_master_multilink = 0;
#elif (CONFIG_BT_GATT_CLIENT_NUM > 1)
const int config_btctler_le_slave_multilink = 0;
const int config_btctler_le_master_multilink = 1;
#else
const int config_btctler_le_slave_multilink = 0;
const int config_btctler_le_master_multilink = 0;
#endif
角色配置的含义:
- 启用 GATT Server(
CONFIG_BT_GATT_SERVER_NUM > 0)→ 控制器支持广播LE_ADV与从机LE_SLAVE角色; - 启用 GATT Client(
CONFIG_BT_GATT_CLIENT_NUM > 0)→ 支持扫描LE_SCAN、发起连接LE_INIT与主机LE_MASTER角色,并同时打开config_btctler_le_afh_en(LE 自适应跳频); - 多链路策略:从机数多于 1 或主从并存时优先开 slave_multilink,仅当纯多主机时开 master_multilink。注释「带主从多机只开 slave_multilink」点明了设计取舍:从机多链路在 AC63 架构下资源收益更高,避免主从同时多链路导致硬件资源冲突。
硬件资源数量推导
const int config_btctler_le_roles = SET_SLAVE_ROLS_CFG | SET_MASTER_ROLS_CFG;
const int config_btctler_le_hw_nums = CONFIG_BT_GATT_CONNECTION_NUM + EXT_ADV_CFG_HW;
const int config_btctler_le_rx_nums = ((CONFIG_BT_GATT_CONNECTION_NUM + EXT_ADV_CFG_HW) * 3) + 2;
const int config_btctler_le_acl_total_nums = ((CONFIG_BT_GATT_CONNECTION_NUM + EXT_ADV_CFG_HW) * 3) + 1;
硬件链路数(le_hw_nums)以 CONFIG_BT_GATT_CONNECTION_NUM 为基数,叠加扩展广播占用的 2 条硬件资源;RX 缓冲数与 ACL 总链路数按「每链路 3 倍 + 固定余量」的经验公式分配,保证多链路下数据路径不丢包。改动 CONFIG_BT_GATT_CONNECTION_NUM 后这些常量自动跟随,无需手工同步,这是该设计的核心价值。
flowchart TD
Svr["CONFIG_BT_GATT_SERVER_NUM > 0"] --> RolesS["roles 置位 LE_ADV | LE_SLAVE"]
Cli["CONFIG_BT_GATT_CLIENT_NUM > 0"] --> RolesM["roles 置位 LE_SCAN | LE_INIT | LE_MASTER<br/>le_afh_en = 1"]
RolesS --> Hw["le_hw_nums = CONN_NUM + EXT_ADV_CFG_HW"]
RolesM --> Hw
Hw --> Rx["le_rx_nums = (CONN_NUM + EXT_ADV_CFG_HW)*3 + 2"]
Hw --> Acl["le_acl_total_nums = (CONN_NUM + EXT_ADV_CFG_HW)*3 + 1"]
SvrN["SERVER_NUM > 1 或 主从并存"] --> MLs["slave_multilink = 1"]
CliN["CLIENT_NUM > 1 且无 SERVER"] --> MLm["master_multilink = 1"]
HS["CONFIG_BLE_HIGH_SPEED"] --> Feat["features 追加 LE_2M_PHY / DLE<br/>ACL 包长 251"]
SM["CONFIG_BT_SM_SUPPORT_ENABLE"] --> Enc["features 置位 LE_ENCRYPTION"]
Ext["CONFIG_BT_EXT_ADV_MODE"] --> Adv["features 置位 EXT_ADV<br/>EXT_ADV_CFG_HW = 2"]
其他 LE 参数
config_btctler_coded_type = CONN_SET_PHY_OPTIONS_S2:长距离 coded PHY 选项;config_btctler_le_slave_conn_update_winden = 500(范围 100~2500):从机连接参数更新窗口;config_btctler_single_carrier_en:仅单模 BLE 时置 1(载波设置);config_vendor_le_bb = 0:LE vendor 基带选项,可置VENDOR_BB_MD_CLOSE | VENDOR_BB_CONNECT_SLOT;- 无 BLE 支持时,上述常量全部归零(
#else分支),保证 LTO 可以整段删除 BLE 代码。
Classic(EDR)侧细化配置
Classic 侧配置集中在测试、功率、LMP 行为三块:
测试与认证开关
const int CONFIG_TEST_DUT_CODE = 1;
const int CONFIG_TEST_FCC_CODE = 1;
const int CONFIG_TEST_DUT_ONLY_BOX_CODE = 0;
const int CONFIG_BREDR_INQUIRY = 0;
const int CONFIG_INQUIRY_PAGE_OFFSET_ADJUST = 0;
const int CONFIG_LMP_NAME_REQ_ENABLE = 1;
const int CONFIG_LMP_PASSKEY_ENABLE = 1;
const int CONFIG_LMP_MASTER_ESCO_ENABLE = 1;
CONFIG_TEST_DUT_CODE/CONFIG_TEST_FCC_CODE:DUT(蓝牙测试模式)与 FCC 认证测试码,产测固件必须打开;CONFIG_TEST_DUT_ONLY_BOX_CODE:仅测试盒模式(默认关);- LMP 选项默认开启(名字请求、Passkey、Master eSCO),提供更好的互操作性。
发射功率配置
const int CONFIG_PAGE_POWER = 4;
const int CONFIG_PAGE_SCAN_POWER = 7;
const int CONFIG_INQUIRY_POWER = 7;
const int CONFIG_INQUIRY_SCAN_POWER = 7;
//固定使用正常发射功率的等级:0-使用不同模式的各自等级;1~10-固定发射功率等级
const int config_force_bt_pwr_tab_using_normal_level = 0;
Page / Inquiry 及其扫描态的发射功率等级相互独立,便于在不影响连接成功率的前提下降低待连接功耗;config_force_bt_pwr_tab_using_normal_level 置 1~10 可强制所有模式使用统一功率档,用于产测一致性。运行期还可通过 bt_max_pwr_set()、ble_set_fix_pwr()、bredr_set_fix_pwr() 动态调整(见 API 参考)。
A2DP 数据缓冲与 TWS 时隙
const int CONFIG_A2DP_DATA_CACHE_LOW = 120;
const int CONFIG_A2DP_DATA_CACHE_HI = 160;
const int CONFIG_A2DP_DATA_CACHE_LOW_AAC = 100;
const int CONFIG_A2DP_DATA_CACHE_HI_AAC = 150;
const int CONFIG_A2DP_DATA_CACHE_LOW_SBC = 120;
const int CONFIG_A2DP_DATA_CACHE_HI_SBC = 160;
const int CONFIG_A2DP_DELAY_TIME = 200;
A2DP 数据缓存水位(LOW/HI)与延时参数按 AAC/SBC 编码器分别配置,低水位触发补包、高水位触发丢帧,保证蓝牙音频链路在射频波动下不卡顿。CONFIG_NEW_BREDR_ENABLE 时还会分配 TWS/Phone 的 run slot(如 CONFIG_TWS_RUN_SLOT = 200、CONFIG_PHONE_LOW_LATENCY_RUN_SLOT = 150),用于 TWS 对耳时隙调度。
使用示例
示例一:升级流程中的模块能力判断
apps/common/update/testbox_update.c 在读取 LE MAC 与销毁 HCI 前先判断当前固件是否支持 LE 模块,避免在纯经典固件上调用未链接的 BLE 代码:
extern int le_controller_get_mac(void *addr);
if (BT_MODULES_IS_SUPPORT(BT_MODULE_LE) && UPDATE_MODULE_IS_SUPPORT(UPDATE_BLE_TEST_EN)) {
le_controller_get_mac(addr);
...
}
...
{
if (BT_MODULES_IS_SUPPORT(BT_MODULE_LE) && UPDATE_MODULE_IS_SUPPORT(UPDATE_BLE_TEST_EN)) {
ll_hci_destory();
}
}
设计意图:ll_hci_destory() 只在 BLE 固件中存在;若固件未启用 LE 却直接调用,链接期 LTO 会报未定义符号。用 BT_MODULES_IS_SUPPORT 做守卫既满足编译期裁剪,又让同一份升级代码兼容所有产品形态。
示例二:BLE 与协议栈能力的双重校验
apps/hid/examples/keyboard/app_keyboard.c 在应用选择 BLE 模式时同时校验控制器层与协议栈层的能力,不满足时打印明确告警:
log_info("---------app select ble--------\n");
if (!STACK_MODULES_IS_SUPPORT(BT_BTSTACK_LE) || !BT_MODULES_IS_SUPPORT(BT_MODULE_LE)) {
log_info("not surpport ble,make sure config !!!\n");
}
设计意图:BLE 功能需要控制器层(config_btctler_modules)与协议栈层(config_stack_modules)同时使能,两层配置独立裁剪;双校验把「配置不完整」问题在运行时显式暴露给开发者,而不是静默失败。
示例三:运行时修改蓝牙版本号
在产品初始化完成事件中,根据出货目标修改上报的蓝牙版本:
// 在 BT_STATUS_INIT_OK 事件中调用
set_bt_version(BLUETOOTH_CORE_SPEC_52); // 上报 5.2
配置选项
以下表格汇总「蓝牙模块选择与配置」涉及的主要编译期常量,均定义于各工程 config/lib_btctrler_config.c(表中以 apps/hid 默认值为准)。
模块与模式
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
TCFG_USER_BLE_ENABLE | int 宏 | 按应用 | 应用层 BLE 总开关(app_config.h) |
TCFG_USER_EDR_ENABLE | int 宏 | 按应用 | 应用层经典蓝牙总开关(app_config.h) |
config_btctler_modules | const int | 推导值 | 控制器模块位掩码,BT_MODULE_CLASSIC/BT_MODULE_LE 组合 |
config_stack_modules | const int | 按应用 | 协议栈模块位掩码,供 STACK_MODULES_IS_SUPPORT 查询 |
config_btctler_mode | const int | CONFIG_BT_MODE | 控制器运行模式(如 BT_NORMAL) |
config_btctler_hci_standard | const int | 非 NORMAL 时为 1 | 是否启用标准 HCI 接口 |
config_bt_function | const int | 0 | 功能位:BT_ENCTRY_TASK/BT_MASTER_AFH/BT_MASTER_QOS |
LE 相关
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
CONFIG_BT_GATT_CONNECTION_NUM | int 宏 | 按应用 | 最大 GATT 连接数,驱动 hw/rx/acl 资源推导 |
CONFIG_BT_GATT_SERVER_NUM | int 宏 | 按应用 | GATT Server 数量,决定从机角色与 slave_multilink |
CONFIG_BT_GATT_CLIENT_NUM | int 宏 | 按应用 | GATT Client 数量,决定主机角色与 master_multilink |
CONFIG_BLE_HIGH_SPEED | int 宏 | 0 | 高速模式:LE_2M_PHY+DLE,ACL 包长 251 |
CONFIG_BT_EXT_ADV_MODE | int 宏 | 0 | 扩展广播/周期广播/CSA#2,额外占用 2 条硬件链路 |
CONFIG_BT_SM_SUPPORT_ENABLE | int 宏 | 按应用 | 安全管理(加密),置位 LE_ENCRYPTION |
config_btctler_le_roles | const int | 推导值 | LE_ADV/LE_SLAVE/LE_SCAN/LE_INIT/LE_MASTER 位或 |
config_btctler_le_hw_nums | const int | 推导值 | BLE 硬件链路数 |
config_btctler_le_rx_nums | const int | 推导值 | BLE RX 缓冲数 |
config_btctler_le_acl_packet_length | const int | 27 | LE ACL 包长(高速模式 251) |
config_btctler_le_acl_total_nums | const int | 推导值 | LE ACL 总链路数 |
config_btctler_le_slave_multilink | const int | 推导值 | 从机多链路使能 |
config_btctler_le_master_multilink | const int | 推导值 | 主机多链路使能 |
config_btctler_le_afh_en | const int | 有 Client 时为 1 | LE 自适应跳频 |
config_btctler_coded_type | const int | CONN_SET_PHY_OPTIONS_S2 | coded PHY 选项 |
config_btctler_le_slave_conn_update_winden | const int | 500 | 从机连接参数更新窗口(100~2500) |
config_vendor_le_bb | u32 | 0 | LE vendor 基带选项 |
Classic 相关
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
CONFIG_PAGE_POWER | const int | 4 | Page 发射功率档 |
CONFIG_PAGE_SCAN_POWER | const int | 7 | Page Scan 发射功率档 |
CONFIG_INQUIRY_POWER | const int | 7 | Inquiry 发射功率档 |
CONFIG_INQUIRY_SCAN_POWER | const int | 7 | Inquiry Scan 发射功率档 |
CONFIG_TEST_DUT_CODE | const int | 1 | DUT 测试码使能 |
CONFIG_TEST_FCC_CODE | const int | 1 | FCC 测试码使能 |
CONFIG_TEST_DUT_ONLY_BOX_CODE | const int | 0 | 仅测试盒模式 |
CONFIG_LMP_NAME_REQ_ENABLE | const int | 1 | LMP Name Request |
CONFIG_LMP_PASSKEY_ENABLE | const int | 1 | LMP Passkey |
CONFIG_LMP_MASTER_ESCO_ENABLE | const int | 1 | 主设备 eSCO |
CONFIG_ESCO_MUX_RX_BULK_ENABLE | const int | 0 | eSCO RX 批量复用 |
CONFIG_BREDR_INQUIRY | const int | 0 | BR/EDR Inquiry 支持 |
config_btctler_bredr_master | const int | 0 | 强制 BR/EDR 主设备 |
config_btctler_dual_a2dp | const int | 0 | 双 A2DP |
config_bredr_afh_user | const int | 0 | AFH 使用 APP 设置 map |
config_bt_temperature_pll_trim | const int | 0 | PLL 温度跟随 trim |
config_delete_link_key | const int | 按应用 | 连接失败返回 PIN/LinkKey Missing 时删除 linkKey |
config_dut_protocol_mode | const int | 0 | DUT 通信模式:0=HCI,1=2-wire |
CONFIG_A2DP_DATA_CACHE_LOW/HI | const int | 120/160 | A2DP 数据缓存低/高水位(AAC/SBC 各有独立值) |
CONFIG_A2DP_DELAY_TIME | const int | 200 | A2DP 延时参数 |
各常量默认值来源:lib_btctrler_config.c (apps/hid)
API 参考
以下接口声明于 btcontroller_modules.h。
查询宏
| 宏 | 语义 |
|---|---|
BT_MODULES_IS_SUPPORT(x) | 控制器是否支持模块 x(config_btctler_modules & x) |
STACK_MODULES_IS_SUPPORT(x) | 协议栈是否支持模块 x(config_stack_modules & x) |
BT_MODE_IS(x) | 控制器当前模式是否为 x |
BT_HCI_STANDARD_IS_SUPPORT(x) | 是否启用标准 HCI |
BT_FUNCTION_IS(x) | 功能位查询(加密任务/主设备 AFH/QoS) |
void set_bt_version(u8 version)
运行时设置上报的蓝牙核心规范版本。version 取 BLUETOOTH_CORE_SPEC_42(0x08)/BLUETOOTH_CORE_SPEC_50(0x09)/BLUETOOTH_CORE_SPEC_51(0x0a)/BLUETOOTH_CORE_SPEC_52(0x0b)。建议在 BT_STATUS_INIT_OK 事件回调中调用。
void bt_max_pwr_set(u8 pwr, u8 pg_pwr, u8 iq_pwr, u8 ble_pwr)
初始化配置蓝牙发射功率最大值范围:
pwr:EDR 连接后发射功率档(range 0~9,随芯片不同:BD29 0~8、BD19/BR34 0~10、BR23/BR25 0~9、BR30 0~8);pg_pwr:EDR page 可连接状态发射功率;iq_pwr:EDR inquiry 可发现状态发射功率;ble_pwr:BLE 发射功率。
超过等级范围默认设置为最高档。
void ble_set_fix_pwr(u8 fix) / void bredr_set_fix_pwr(u8 fix)
动态调整 BLE / EDR 发射功率,fix 取值 0~max,用于运行时功率控制(如 SAR、产测)。
u8 rf_set_24g_hackable_coded(u32 coded) / rf_set_adv_24g_hackable_coded / rf_set_scan_24g_hackable_coded
设置 2.4G 私有模式的 coded 码(32 bits,0101 分布需相对均匀),分别作用于连接、广播、扫描。返回:1 失败,0 成功。
void bt_pll_para(u32 osc, u32 sys, u8 low_power, u8 xosc)
配置蓝牙 PLL 参数(晶振/系统时钟/低功耗/外部晶振),需与硬件时钟方案匹配。
void bt_osc_offset_ext_save(s32 offset) / void bt_osc_offset_ext_updata(s32 offset)
更新并保存 / 仅更新频偏(osc offset),前者会写入非易失存储。
void bt_production_test(u8 en)
使能/关闭蓝牙产测模式(配合 DUT 测试码使用)。
void bt_set_rxtx_status_enable(u8 en)
使能 RX/TX 状态指示引脚输出,用于测量蓝牙收发时隙。不同芯片的指示引脚不同(如 AC696x 为 PC1/PC2,AC697x 为 PC2/PC3,AC632x 为 PA7/PA8),接线前请对照头文件引脚表。
void bt_set_ldos(u8 mode)
设置蓝牙相关 LDO 模式,用于低功耗场景的电源配置。
失败模式、边界与并发
配置不一致导致的链接失败
最常见的错误是应用层开关与库裁剪不一致:业务代码直接调用 BLE API,但 TCFG_USER_BLE_ENABLE 未打开(config_btctler_modules 不含 BT_MODULE_LE)。由于 LTO 会裁剪未启用模块的符号,链接期直接报未定义引用。规避方法:所有模块相关调用必须用 BT_MODULES_IS_SUPPORT(x)(控制器层)与 STACK_MODULES_IS_SUPPORT(x)(协议栈层)双重守卫,如 app_keyboard.c 所示。
双模配置的隐性约束
apps/hid/include/app_config.h 中可见约束:
#if TCFG_USER_EDR_ENABLE && TCFG_USER_BLE_ENABLE
//不支持同时打开
部分应用工程(如 hid)在 EDR 与 BLE 同开时存在资源限制,需要先关闭部分功能再打开;开发者应阅读本工程 app_config.h 中对应的条件编译注释,确认双模组合在当前工程下是否被允许。
多链路资源超配
config_btctler_le_hw_nums、le_rx_nums、le_acl_total_nums 由 CONFIG_BT_GATT_CONNECTION_NUM 自动推导。若手工提高连接数而不关注 RAM 预算,可能导致 RX 缓冲不足或内存超限。多链路策略是互斥的:主从同时多链路不受支持,配置代码优先保证 slave_multilink(见 LE 多链路推导分支)。修改连接数后应回归测试多机并发场景。
运行时并发注意
set_bt_version、bt_max_pwr_set等运行期接口应在蓝牙协议栈初始化完成事件(BT_STATUS_INIT_OK)中调用,避免与控制器初始化竞争;bt_osc_offset_ext_save涉及非易失写入,不应在高频路径反复调用,防止 Flash 磨损;- 模块查询宏为纯位运算(无锁、无副作用),可在任意上下文(中断/任务)安全使用。
性能与运维建议
- 代码空间:纯 BLE 产品务必保持
config_btctler_modules = BT_MODULE_LE,让 LTO 裁剪整个 EDR 协议栈;纯经典产品同理关闭 BLE。这是本套配置体系最大的收益点。 - RAM 预算:
CONFIG_BLE_HIGH_SPEED把 ACL 包长从 27 提升到 251,CONFIG_BT_EXT_ADV_MODE额外占用 2 条硬件链路,两者都会显著增加缓冲占用——仅在真正需要高速/扩展广播时开启。 - 产测一致性:产测固件建议打开
CONFIG_TEST_DUT_CODE/CONFIG_TEST_FCC_CODE,并通过config_force_bt_pwr_tab_using_normal_level固定功率档,保证每台机器测试条件一致;出货固件再关闭测试码。 - 功率与功耗:Page/Inquiry 功率档(
CONFIG_PAGE_POWER等)可独立下调以降低待连接功耗,但过低会缩短可发现/可连接距离,需实测权衡。
扩展点
- 新增模块位:
btcontroller_modules.h中BT_MODULE_*使用 BIT(n) 递增定义,新增模块只需占用下一个位并在config_btctler_modules推导中增加分支,查询宏自动生效。 - 新增功能位:
config_bt_function已预留BT_ENCTRY_TASK/BT_MASTER_AFH/BT_MASTER_QOS三个位,BT_FUNCTION_IS(x)直接支持扩展。 - 新增运行期调节 API:
bt_max_pwr_set/ble_set_fix_pwr/bredr_set_fix_pwr构成功率调节 API 族,可仿照其签名扩展 SAR、温控等策略接口。 - 按芯片差异化:发射功率档位表按芯片(BD29/BD19/BR23/BR25/BR30/BR34)不同,换芯片方案时核对
btcontroller_modules.h中的功率表注释,避免档位越界被强制设为最高档。
测试
- 配置交叉验证:
apps/hid、apps/mesh、apps/spp_and_le三个工程分别覆盖双模、纯 BLE、经典+LE 的配置组合,可作为「不同TCFG_USER_*组合下config_btctler_modules推导正确性」的参照样本。 - 运行时能力守卫:
testbox_update.c与app_keyboard.c中的BT_MODULES_IS_SUPPORT断言模式,是业务代码应遵循的统一测试/防御写法。 - 产测验证:
CONFIG_TEST_DUT_CODE/CONFIG_TEST_FCC_CODE/bt_production_test提供产测路径,配合CONFIG_DUT_POWER与config_dut_protocol_mode(HCI 或 2-wire)验证射频指标。
Related Links
- btcontroller_modules.h(模块宏与运行期 API 声明)
- lib_btctrler_config.c (apps/hid,模块/LE/Classic 配置实现)
- lib_btctrler_config.c (apps/spp_and_le)
- lib_btctrler_config.c (apps/mesh,纯 BLE 变体)
- app_config.h (apps/hid,应用层开关 TCFG_USER_*)
- testbox_update.c(模块能力守卫使用示例)
- app_keyboard.c(控制器层+协议栈层双重校验示例)
相关主题:HCI 传输层配置、蓝牙协议栈(btstack)上层配置、产测(DUT/FCC)流程,分别见蓝牙协议栈目录下的对应页面。