杰理 SDK 文档中心
首页
首页
  • 概述

    • SDK 概览与产品定位
    • 支持芯片平台与蓝牙认证
    • SDK 架构与目录分层
  • 快速开始

    • 环境搭建与编译工具链
    • 编译构建系统
    • 板级工程与配置
    • 烧录与固件升级工具
  • 应用工程

    • 应用选择与工程总览
    • SPP + BLE 数传应用框架
    • 透传与 AT 指令示例
    • BLE 广播/中心与定位示例
    • 2.4G 私有协议与 Dongle 示例
    • 云平台接入示例
    • HID 人机交互应用框架
    • HID 示例工程(键盘/鼠标/遥控器/手柄)
    • Bluetooth Mesh 应用框架
    • Mesh 模型与 Mesh DFU 固件升级
    • Mesh 音频编解码演示
  • 芯片平台与硬件抽象

    • 芯片平台总览与差异
    • 音频编解码与时钟管理
    • 外设驱动接口(ADC/IIC/SPI/PWM/LED/充电)
    • 芯片配置工具与下载支持
  • 蓝牙协议栈

    • 蓝牙控制器层(btctrler)
    • 蓝牙协议栈与 Profile(btstack)
    • 蓝牙模块选择与配置
  • 媒体与音频框架

    • 音频流框架
    • 音频编解码与 A2DP 媒体
    • 音频效果处理(EQ/频谱/变调/环绕/超低音)
    • 本地 TWS 与音频同步
  • 系统服务与运行时

    • 实时操作系统与任务调度
    • 消息事件机制
    • 电源管理与低功耗
    • 存储与配置系统
    • 设备驱动框架(USB/RTC)
  • 应用公共组件

    • 音频应用组件
    • 设备外设抽象(按键/触摸/传感器/存储)
    • 蓝牙公共模块与消息联动
    • 调试与配置组件
    • 杰理关键词唤醒(jl_kws)
  • 第三方协议与云平台接入

    • 杰理 RCSP 私有协议
    • 低功耗蓝牙 Mesh 方案(llsync_mesh)
    • Sig Mesh 方案
    • 涂鸦协议接入
    • 腾讯连连接入
    • 华为 HiLink 接入
  • 固件升级与维护

    • OTA 升级机制
    • 升级补丁与版本维护
    • 升级工具链(BLE OTA / USB Dongle OTA)
  • 文档与开发资源

    • 数据手册与架构文档
    • 协议与云平台开发文档
    • 常见问题与技术支持

蓝牙模块选择与配置

本文档讲解 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))

来源:btcontroller_modules.h

  • 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

来源:lib_btctrler_config.c (apps/hid)

推导规则形成一张四象限决策表:

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;

来源:lib_btctrler_config.c (apps/hid)

  • 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))

来源:btcontroller_modules.h

其中 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);

来源:btcontroller_modules.h

与模块裁剪不同,版本号是运行时可调的——同一固件可以按产品需求上报 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

来源:lib_btctrler_config.c (apps/hid)

  • 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

来源:lib_btctrler_config.c (apps/hid)

角色配置的含义:

  • 启用 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;

来源:lib_btctrler_config.c (apps/hid)

硬件链路数(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;

来源:lib_btctrler_config.c (apps/hid)

  • 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;

来源:lib_btctrler_config.c (apps/hid)

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;

来源:lib_btctrler_config.c (apps/hid)

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();
    }
}

来源:testbox_update.c

设计意图: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");
}

来源:app_keyboard.c

设计意图:BLE 功能需要控制器层(config_btctler_modules)与协议栈层(config_stack_modules)同时使能,两层配置独立裁剪;双校验把「配置不完整」问题在运行时显式暴露给开发者,而不是静默失败。

示例三:运行时修改蓝牙版本号

在产品初始化完成事件中,根据出货目标修改上报的蓝牙版本:

// 在 BT_STATUS_INIT_OK 事件中调用
set_bt_version(BLUETOOTH_CORE_SPEC_52);   // 上报 5.2

来源:btcontroller_modules.h

配置选项

以下表格汇总「蓝牙模块选择与配置」涉及的主要编译期常量,均定义于各工程 config/lib_btctrler_config.c(表中以 apps/hid 默认值为准)。

模块与模式

选项类型默认值说明
TCFG_USER_BLE_ENABLEint 宏按应用应用层 BLE 总开关(app_config.h)
TCFG_USER_EDR_ENABLEint 宏按应用应用层经典蓝牙总开关(app_config.h)
config_btctler_modulesconst int推导值控制器模块位掩码,BT_MODULE_CLASSIC/BT_MODULE_LE 组合
config_stack_modulesconst int按应用协议栈模块位掩码,供 STACK_MODULES_IS_SUPPORT 查询
config_btctler_modeconst intCONFIG_BT_MODE控制器运行模式(如 BT_NORMAL)
config_btctler_hci_standardconst int非 NORMAL 时为 1是否启用标准 HCI 接口
config_bt_functionconst int0功能位:BT_ENCTRY_TASK/BT_MASTER_AFH/BT_MASTER_QOS

LE 相关

选项类型默认值说明
CONFIG_BT_GATT_CONNECTION_NUMint 宏按应用最大 GATT 连接数,驱动 hw/rx/acl 资源推导
CONFIG_BT_GATT_SERVER_NUMint 宏按应用GATT Server 数量,决定从机角色与 slave_multilink
CONFIG_BT_GATT_CLIENT_NUMint 宏按应用GATT Client 数量,决定主机角色与 master_multilink
CONFIG_BLE_HIGH_SPEEDint 宏0高速模式:LE_2M_PHY+DLE,ACL 包长 251
CONFIG_BT_EXT_ADV_MODEint 宏0扩展广播/周期广播/CSA#2,额外占用 2 条硬件链路
CONFIG_BT_SM_SUPPORT_ENABLEint 宏按应用安全管理(加密),置位 LE_ENCRYPTION
config_btctler_le_rolesconst int推导值LE_ADV/LE_SLAVE/LE_SCAN/LE_INIT/LE_MASTER 位或
config_btctler_le_hw_numsconst int推导值BLE 硬件链路数
config_btctler_le_rx_numsconst int推导值BLE RX 缓冲数
config_btctler_le_acl_packet_lengthconst int27LE ACL 包长(高速模式 251)
config_btctler_le_acl_total_numsconst int推导值LE ACL 总链路数
config_btctler_le_slave_multilinkconst int推导值从机多链路使能
config_btctler_le_master_multilinkconst int推导值主机多链路使能
config_btctler_le_afh_enconst int有 Client 时为 1LE 自适应跳频
config_btctler_coded_typeconst intCONN_SET_PHY_OPTIONS_S2coded PHY 选项
config_btctler_le_slave_conn_update_windenconst int500从机连接参数更新窗口(100~2500)
config_vendor_le_bbu320LE vendor 基带选项

Classic 相关

选项类型默认值说明
CONFIG_PAGE_POWERconst int4Page 发射功率档
CONFIG_PAGE_SCAN_POWERconst int7Page Scan 发射功率档
CONFIG_INQUIRY_POWERconst int7Inquiry 发射功率档
CONFIG_INQUIRY_SCAN_POWERconst int7Inquiry Scan 发射功率档
CONFIG_TEST_DUT_CODEconst int1DUT 测试码使能
CONFIG_TEST_FCC_CODEconst int1FCC 测试码使能
CONFIG_TEST_DUT_ONLY_BOX_CODEconst int0仅测试盒模式
CONFIG_LMP_NAME_REQ_ENABLEconst int1LMP Name Request
CONFIG_LMP_PASSKEY_ENABLEconst int1LMP Passkey
CONFIG_LMP_MASTER_ESCO_ENABLEconst int1主设备 eSCO
CONFIG_ESCO_MUX_RX_BULK_ENABLEconst int0eSCO RX 批量复用
CONFIG_BREDR_INQUIRYconst int0BR/EDR Inquiry 支持
config_btctler_bredr_masterconst int0强制 BR/EDR 主设备
config_btctler_dual_a2dpconst int0双 A2DP
config_bredr_afh_userconst int0AFH 使用 APP 设置 map
config_bt_temperature_pll_trimconst int0PLL 温度跟随 trim
config_delete_link_keyconst int按应用连接失败返回 PIN/LinkKey Missing 时删除 linkKey
config_dut_protocol_modeconst int0DUT 通信模式:0=HCI,1=2-wire
CONFIG_A2DP_DATA_CACHE_LOW/HIconst int120/160A2DP 数据缓存低/高水位(AAC/SBC 各有独立值)
CONFIG_A2DP_DELAY_TIMEconst int200A2DP 延时参数

各常量默认值来源: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
//不支持同时打开

来源:app_config.h (apps/hid)

部分应用工程(如 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)流程,分别见蓝牙协议栈目录下的对应页面。

Prev
蓝牙协议栈与 Profile(btstack)