蓝牙控制器
蓝牙控制器(btctrler)是 AC630N 蓝牙 SoC 中负责射频(RF)收发、基带(Baseband)处理、链路层(Link Layer)与 HCI(Host Controller Interface)传输的底层协议栈实体。它以静态库形式随固件链接,通过 btctrler_task 任务与应用层(Host)交互,并提供经典蓝牙(BR/EDR)与低功耗蓝牙(BLE)双模能力。
目的与范围
本页面向「蓝牙控制器」这一目录项,覆盖以下内容:
- 控制器在协议栈中的分层位置与职责边界(HCI 传输 → 链路层 → 基带 → RF)。
btcontroller_mode.h/btcontroller_modules.h定义的测试模式(BQB / FCC / 定频 / 性能)与 LTO 模块裁剪机制。- 控制器对外暴露的核心 API(
hci_controller_init、le_controller_set_mac、bt_reset_cap、bt_set_tx_power等)。 port/bd29/btcontroller_config.h中的端口级配置(LE 特性、LE 角色、低功耗唤醒参数lp_ws_t)。- 应用侧
btctrler任务的注册方式与控制器库的链接方式。
以下内容属于其他目录页的范畴,本页只做交叉引用而不展开:HCI 命令/事件的具体语义(见 HCI 传输层)、BLE GATT/GAP 上层服务、经典蓝牙 Profile(A2DP/HFP/SPP 等)、TWS 双耳互联协议。
概述
AC630N 是杰理科技(Jieli)推出的低功耗蓝牙音频 SoC,其 SDK 采用"控制器(Controller)+ 主机(Host)"的分层协议栈架构。蓝牙控制器位于协议栈最底层,向上通过 HCI 与 btstack(主机协议栈)通信,向下直接驱动射频与基带硬件。
控制器代码以预编译库(btctler_lib_text.ld 链接脚本片段可见其为库文本段)形式提供给应用工程,应用通过头文件(include_lib/btctrler/)中的声明调用其 API,并通过链接期常量(config_btctler_mode、config_btctler_modules、config_btctler_hci_standard)在 LTO(Link Time Optimization)下裁剪未使用的代码路径,从而优化代码空间——这对 Flash/RAM 受限的嵌入式设备至关重要。
设计上,控制器支持两种工作内核(Classic BR/EDR 与 LE),两者通过位掩码开关独立使能;同时支持六种工作模式,覆盖从量产默认到实验室认证(BQB/FCC)、定频与性能测试等场景。这种"编译期裁剪 + 运行期模式"的双重设计,使同一套 SDK 可适配耳机、音箱、键鼠(HID)、Mesh 节点等多种产品形态。
架构
flowchart TD
subgraph sg_App["应用层 (apps/*)"]
AppTask["app_main / 应用任务"]
AppBsp["app_*.c (app_keyboard / app_spp_and_le ...)"]
end
subgraph sg_Host["主机协议栈 (btstack)"]
HostStack["btstack 任务<br/>GAP / GATT / SPP / A2DP / HFP"]
end
subgraph sg_Ctl["蓝牙控制器 (btctrler)"]
CtlTask["btctrler_task<br/>(优先级4, 栈512B, 队列256)"]
HCI["HCI 传输层<br/>(hci_transport.h)"]
LL["链路层<br/>LE LL / Classic LM"]
BB["基带与射频<br/>(Baseband / RF)"]
end
subgraph sg_Cfg["编译期配置"]
ModeH["btcontroller_mode.h<br/>BT_NORMAL/BT_BQB/BT_FCC..."]
ModH["btcontroller_modules.h<br/>BT_MODULE_CLASSIC / BT_MODULE_LE"]
CfgH["port/bd29/btcontroller_config.h<br/>CONFIG_LE_ROLES / CONFIG_LE_FEATURES / lp_ws_t"]
end
AppTask --> AppBsp
AppBsp -->|"btctrler_task.h API"| CtlTask
HostStack -->|"HCI 命令/事件"| HCI
CtlTask --> HCI
HCI --> LL
LL --> BB
CtlTask -.->|"LTO 裁剪"| ModeH
CtlTask -.->|"LTO 裁剪"| ModH
CtlTask -.->|"端口适配"| CfgH
架构说明:
- 应用层:各应用工程(
apps/hid、apps/spp_and_le、apps/mesh等)在app_main.c的任务表中注册{"btctrler", 4, 512, 256},即控制器任务优先级 4、栈大小 512、消息队列深度 256,并通过btctrler/btctrler_task.h调用控制器功能。 - 主机协议栈(btstack):负责 BR/EDR Profile 与 LE 上层服务,通过 HCI 传输层与控制器交换命令、事件与 ACL 数据。
- 控制器:
btctrler_task承载控制器运行上下文;HCI 传输层(hci_transport.h)实现控制器与主机的数据通道;链路层(ble/ll_config.h与classic/lmp_config.h对应的 LE Link Layer / Classic Link Manager)完成连接管理、加密、跳频等;基带与射频层直接操作硬件。 - 编译期配置:三个头文件共同决定编译产物。其中
config_btctler_mode/config_btctler_modules是extern const int,由应用侧定义初值,libs 侧的 LTO 依据这些常量裁剪代码——这正是btcontroller_config.h头部注释"优化代码需要,libs 依赖 app 定义变量,由 app 定义变量值决定 libs 优化"的含义。
工作模式:从量产到实验室认证
include_lib/btctrler/btcontroller_mode.h 用一组位掩码定义控制器的运行模式。CONFIG_BT_MODE 默认配置为 BT_NORMAL,即量产默认模式。不同模式对应不同测试/认证场景,编译期即确定,运行期不可切换。
#define BT_NORMAL 0x01
#define BT_BQB 0x02
#define BT_FCC 0x04
#define BT_FRE 0x10
#define BT_PER 0x20
#define BT_BQB_PROFILE 0x40
#define CONFIG_BT_MODE BT_NORMAL
| 模式宏 | 值 | 适用场景 | 行为说明 |
|---|---|---|---|
BT_NORMAL | 0x01 | 量产默认 | 正常协议栈流程,可通过外部操作调用 bredr_set_dut_enble() 按需进入 DUT 测试 |
BT_BQB | 0x02 | 实验室 RF/BQB 认证 | 提供蓝牙资格认证(Bluetooth Qualification Body)所需的射频测试通道 |
BT_FCC | 0x04 | 实验室 RF/FCC 认证 | 提供 FCC 认证所需射频行为 |
BT_FRE | 0x10 | 定频测试 | 固定频点 2402 MHz、发射功率最大,供产线定频测试 |
BT_PER | 0x20 | 性能测试 | 可直接用仪器连接测试;测试完毕后需复位或重新上电才恢复正常流程,否则只支持连接一个设备 |
BT_BQB_PROFILE | 0x40 | BQB Profile 测试 | 需与 BT_NORMAL 组合(BT_NORMAL | BT_BQB_PROFILE),会多编译部分代码 |
头文件注释中还给出两个重要的产线测试 API 用法:
void bredr_set_dut_enble(u8 en, u8 phone):使能 BR/EDR DUT(Device Under Test)模式后即可用仪器连接测试;phone为 1 时允许手机连接、为 0 时禁止。进入 DUT 前通常需要配合关闭耳机快速链接、开启可发现与可连接:
tws_cancle_all_noconn(); // 取消 TWS 快速连接
user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_ENABLE, 0, NULL); // 关闭可发现
user_send_cmd_prepare(USER_CTRL_WRITE_CONN_ENABLE, 0, NULL); // 关闭可连接
void bt_fix_fre_api(void):一键定频(2402 MHz、最大发射功率),调用后不可恢复之前状态,仅用于量产测试,测试完必须复位或重新上电。
设计意图
将测试模式做进固件而非依赖外部工具,是因为 AC630N 是单芯片方案,射频测试需要复用正常协议栈的射频通路。通过编译期模式选择,量产固件(BT_NORMAL)不包含 BQB/FCC 测试代码以节省空间;认证固件则按需启用。而 BT_PER 需要"复位才能恢复正常"的说明提醒开发者:性能测试会改变链路状态机,不能作为运行时功能开关使用。
LTO 模块化与模式裁剪机制
include_lib/btctrler/btcontroller_modules.h 是控制器的"总开关"头文件:它聚合了 HCI 传输层定义与模式定义,并对外暴露三组链接期常量与对应宏,供 LTO 裁剪代码空间。
#include "hci_transport.h"
#include "btcontroller_mode.h"
/* 控制器功能模块 */
#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))
/* 运行模式 */
extern const int config_btctler_mode;
#define BT_MODE_IS(x) (config_btctler_mode & (x))
/* HCI 标准支持 */
extern const int config_btctler_hci_standard;
#define BT_HCI_STANDARD_IS_SUPPORT(x) (config_btctler_hci_standard)
工作机制
extern const int声明:这些常量不在此头文件中定义,而是由应用工程定义初值(默认见btcontroller_mode.h的CONFIG_BT_MODE,模块默认值在库内)。这样 libs(预编译库)与 app(应用)共享同一组编译期可求值常量。- LTO 常量折叠:链接期优化时,
BT_MODULES_IS_SUPPORT(x)这类宏展开为config_btctler_modules & (x),若常量为 0 则整个if分支被判定为死代码而被消除。 - 双模块开关:
BT_MODULE_CLASSIC(经典蓝牙)与BT_MODULE_LE(低功耗蓝牙)独立控制,双模产品两者都开,纯 LE 产品(如 HID 键鼠)可只开 LE,进一步缩小固件。
设计意图
嵌入式蓝牙 SoC 的 Flash 空间极其有限,而经典蓝牙与 BLE 的链路层实现、测试模式的附加代码差异巨大。将裁剪点收敛为"应用定义常量 + 库内 LTO 优化"而非"预处理器宏",是因为预编译库的 .c 文件已编译为 .a/.o,#ifdef 无法再作用于库内部;extern const int 则允许链接期进行跨编译单元(app → libs)的常量传播与死代码消除,这正是 btcontroller_config.h 注释"libs 依赖 app 定义变量,由 app 定义变量值决定 libs 优化"的由来。
控制器核心 API
btcontroller_modules.h 末尾声明了控制器对外暴露的四个核心 API,它们是应用与控制器交互的主要入口:
void hci_controller_init(void);
int le_controller_set_mac(void *addr);
void bt_reset_cap(u8 sel_l, u8 sel_r);
void bt_set_tx_power(u8 txpower);
hci_controller_init(void)
- 职责:初始化 HCI 控制器子系统,包括 HCI 传输层、链路层与基带/射频的启动配置。它是控制器侧(而非主机侧)的初始化入口,通常在系统启动早期、
btctrler_task任务建立后调用一次。 - 返回:void。
- 使用场景:系统上电初始化序列中,与应用自身的
board_init类流程配合;调用后控制器才能响应主机的 HCI 命令。
le_controller_set_mac(void *addr)
- 职责:设置 LE 控制器的 MAC 地址(48 位公共/随机地址)。
addr指向至少 6 字节的地址缓冲。 - 返回:
int,0 表示成功,非 0 表示参数非法或地址写入失败。 - 使用场景:量产写号、多设备共址区分(如 TWS 左右耳)时,在控制器初始化后、启动广播/扫描前调用。MAC 一旦设定即作为 LE 链路层地址源使用。
bt_reset_cap(u8 sel_l, u8 sel_r)
- 职责:复位蓝牙射频电容校准参数(左右通道各一个选择值)。
sel_l/sel_r分别为左右声道的电容档位选择,用于射频匹配校准。 - 返回:void。
- 使用场景:产线射频校准流程中,当外部校准数据写入后调用,使新校准值立即生效,无需整机复位。
bt_set_tx_power(u8 txpower)
- 职责:设置蓝牙发射功率档位。
txpower为功率档索引(具体 dBm 映射在射频驱动内实现)。 - 返回:void。
- 使用场景:动态功率控制(如距离检测降功率、FCC 传导测试限功率)、产线射频测试中调整发射功率。
端口级配置:bd29 平台
include_lib/btctrler/port/bd29/btcontroller_config.h 是针对 bd29(AC630N 所属系列)芯片的控制器适配配置,位于 include_lib/btctrler/port/<chip>/ 目录结构下,体现"库通用 + 端口定制"的分层设计。
#include "btcontroller_modules.h"
#include "ble/ll_config.h"
// #define CONFIG_LE_FEATURES \
(LE_ENCRYPTION | LE_CORE_V50_FEATURES)
#define CONFIG_LE_FEATURES 0//(LE_ENCRYPTION)
// #define CONFIG_LE_ROLES (LE_ADV|LE_SCAN|LE_INIT|LE_SLAVE|LE_MASTER)
// #define CONFIG_LE_ROLES (LE_ADV|LE_SCAN)
#define CONFIG_LE_ROLES (LE_ADV)
#include "classic/lmp_config.h"
#define CONFIG_CL_FEATURES
#define CONFIG_CL_EX_FEATURES
#define TWS_BLE_ESCO_CONNECT //通话过程进行连接使能
关键配置项
| 配置宏 | 默认值 | 含义 |
|---|---|---|
CONFIG_LE_FEATURES | 0 | LE 特性集合,默认关闭(注释示例给出 LE_ENCRYPTION、LE_CORE_V50_FEATURES 的写法)。置 0 可最小化 LE 代码,适合不需要加密的广播应用 |
CONFIG_LE_ROLES | (LE_ADV) | LE 角色集合。默认仅广播(ADV)角色,代码最小;注释给出全角色 LE_ADV|LE_SCAN|LE_INIT|LE_SLAVE|LE_MASTER 或广播+扫描的裁剪方案 |
CONFIG_CL_FEATURES | 空 | 经典蓝牙特性集合(空表示使用库默认经典特性集) |
CONFIG_CL_EX_FEATURES | 空 | 经典蓝牙扩展特性集合 |
TWS_BLE_ESCO_CONNECT | 定义 | TWS 通话过程中允许 eSCO 连接使能,保证通话与 TWS 互联并存 |
低功耗基带运行参数:lp_ws_t
该头文件还定义了蓝牙基带低功耗(Low Power)运行时的唤醒窗口参数结构,由射频/基带低功耗模块使用:
struct lp_ws_t {
u16 lrc_ws_inc; // LRC 唤醒窗口递增步长
u16 lrc_ws_init; // LRC 唤醒窗口初始值
u16 bt_osc_ws_inc; // 蓝牙振荡器唤醒窗口递增步长
u16 bt_osc_ws_init; // 蓝牙振荡器唤醒窗口初始值
u8 osc_change_mode; // 振荡器切换模式
};
设计意图:低功耗蓝牙为省电会在连接事件/广播事件之间关闭射频与振荡器,唤醒窗口(wakeup window)参数决定提前多长时间开启 LRC(低频 RC 时钟)与蓝牙高频振荡器,以保证时钟稳定后射频准时收发。inc(递增步长)与 init(初始值)配合使用:初始值给出首次唤醒提前量,递增步长用于补偿晶振/温度漂移。这些参数因芯片与晶振方案而异,因此放在 port/<chip>/ 目录中,由硬件工程师按平台调整。
应用集成:btctrler 任务
控制器在应用工程中以独立任务(btctrler)形式运行。各应用(HID、SPP+LE、Mesh 等)在 app_main.c 的系统任务表中注册该任务,例如:
{"btctrler", 4, 512, 256 },
{"btstack", 3, 768, 256 },
任务表项的四个字段依次为:任务名、优先级、栈大小、消息队列深度。btctrler 任务优先级为 4,高于 btstack(3)——这是因为控制器承载射频基带实时性要求高的处理,必须优先于主机协议栈。注意 app_main.c 中数值越小优先级越高(与常见 RTOS 约定一致)。
应用源码通过 #include "btctrler/btctrler_task.h" 使用控制器任务接口:
#include "btcontroller_config.h"
#include "btctrler/btctrler_task.h"
#include "config/config_transport.h"
控制器库的代码段通过链接脚本片段并入固件镜像。cpu/bd29/sdk_ld.c 中:
#include "btctrler/btctler_lib_text.ld"
这证实控制器以预编译静态库方式参与链接,其文本段(.text)由专门链接脚本安排到固定/优化位置,而头文件中的 extern const int 配置常量则由应用定义——这是"库内 LTO 裁剪"机制能够工作的物理基础。
核心流程:控制器启动与 HCI 交互
sequenceDiagram
participant APP as 应用任务 (app_main)
participant CTL as btctrler 任务
participant HCI as HCI 传输层
participant LL as 链路层 (LE LL / Classic LM)
participant RF as 基带/射频
APP->>APP: 定义 config_btctler_mode / modules<br/>(LTO 裁剪决策)
APP->>CTL: 创建任务并启动
CTL->>HCI: hci_controller_init()
HCI->>LL: 初始化链路层状态机
LL->>RF: 配置基带与射频 (频率/功率/电容校准)
RF-->>LL: 硬件就绪
LL-->>HCI: 控制器就绪
HCI-->>CTL: 初始化完成
CTL-->>APP: 任务进入消息循环<br/>(队列深度 256)
Note over HCI,RF: 运行期
APP->>CTL: le_controller_set_mac(addr)
CTL->>LL: 写入 LE 地址
APP->>CTL: bt_set_tx_power(txpower)
CTL->>RF: 设置发射功率档位
HCI->>LL: HCI 命令 (来自 btstack)
LL->>RF: 执行链路操作 (广播/连接/跳频)
RF-->>LL: 射频事件/数据
LL-->>HCI: HCI 事件/ACL 数据
HCI-->>CTL: 上报主机 (btstack)
流程解读:
- 编译期:应用定义
config_btctler_mode、config_btctler_modules等常量,LTO 据此裁剪库代码——这是"软件开关"。 - 启动期:系统创建
btctrler任务(优先级 4),任务初始化阶段调用hci_controller_init()完成 HCI 传输、链路层与基带/射频的初始化。 - 配置期:应用按需调用
le_controller_set_mac()(写 MAC)、bt_set_tx_power()(调功率)、bt_reset_cap()(校准电容),或进入产线测试模式(bredr_set_dut_enble/bt_fix_fre_api)。 - 运行期:
btstack主机通过 HCI 传输层下发命令;控制器链路层执行广播、扫描、连接、跳频等操作;基带/射频事件经链路层封装为 HCI 事件与 ACL 数据上报主机。所有跨任务交互经由btctrler任务的 256 深度消息队列串行化,避免并发访问基带寄存器。
失败模式、边界情况与并发
不可逆的测试模式
bt_fix_fre_api()定频后不可恢复,必须复位/重新上电;BT_PER模式下测试完同样需要复位,且只支持连接一个设备。将这类接口设计为"一次性"是为了避免定频状态与协议栈状态机互相污染,产线流程必须把复位纳入测试步骤。
DUT 模式下的连接控制
bredr_set_dut_enble(en, phone)中phone=0时仪器可连而手机不可连;配合关闭扫描/连接使能(USER_CTRL_WRITE_SCAN_ENABLE/USER_CTRL_WRITE_CONN_ENABLE)与取消 TWS 快速连接,才能让 DUT 状态不被产品级逻辑干扰。若未关闭耳机快速连接,可能出现仪器连上后又被快速连接逻辑抢占的问题。
LTO 常量不一致的风险
- 裁剪依赖应用与库对同一
extern const int的一致理解。若应用改动了config_btctler_mode/config_btctler_modules的初值而未重新链接库(或库版本不匹配),可能出现被裁剪掉的功能在运行期被调用而行为异常。升级 SDK 时应同步核对配置头文件与库版本。
并发与实时性
- 控制器任务优先级(4)高于主机协议栈(3),保证射频基带事件优先处理;所有对链路层/基带的访问集中在
btctrler任务内通过消息队列串行执行,应用不得在中断上下文直接调用链路层 API,以免破坏基带时序。 lp_ws_t唤醒窗口参数若配置过小,低功耗模式下可能出现射频唤醒不及时导致丢包;配置过大则耗电增加。属于典型的功耗/性能权衡点,需结合晶振精度实测调整。
配置裁剪的影响
CONFIG_LE_FEATURES = 0(默认)意味着 LE 加密功能被裁剪:若产品需要 LE 加密连接,必须改为LE_ENCRYPTION(可配合LE_CORE_V50_FEATURES)。CONFIG_LE_ROLES = (LE_ADV)默认仅支持广播角色:需要做 LE 从机(Slave)或主机(Master)的产品必须扩展该宏(如LE_ADV|LE_SCAN|LE_INIT|LE_SLAVE|LE_MASTER),否则相关 HCI 命令会因代码被裁剪而失败。
性能与运维考虑
- 代码空间优化:控制器以"位掩码模块开关 +
extern const intLTO 裁剪 + 端口配置宏"三级机制控制固件体积。量产固件应保持BT_NORMAL、最小化CONFIG_LE_FEATURES/CONFIG_LE_ROLES,可显著缩小镜像。 - 任务资源:
btctrler任务栈 512 字节、队列 256 条消息,是控制器吞吐的硬上限。高频 HCI 流量(如大块 ACL 数据)下若出现丢事件,应优先检查队列是否溢出,而非盲目加大栈。 - 射频校准:
bt_reset_cap(sel_l, sel_r)支持产线写入校准数据后热更新电容档位,避免每台设备复位,提升产测节拍;bt_set_tx_power()支持按测试项动态调功率。 - 测试模式的选择:
- BQB/FCC 认证 → 编译
BT_BQB/BT_FCC专用固件; - 定频产测 →
BT_FRE(固定 2402 MHz、最大功率)或运行期bt_fix_fre_api(); - 整机性能 →
BT_PER用仪器直连,测后必须复位; - 量产 →
BT_NORMAL+ 运行期bredr_set_dut_enble()按需进入 DUT。
- BQB/FCC 认证 → 编译
- 低功耗:
lp_ws_t的lrc_ws_*与bt_osc_ws_*参数决定睡眠唤醒提前量,osc_change_mode决定振荡器切换策略;在待机电流与连接稳定性之间需按平台实测调优。
扩展点
- 新增芯片平台:仿照
include_lib/btctrler/port/bd29/新建port/<chip>/btcontroller_config.h,重定义CONFIG_LE_FEATURES、CONFIG_LE_ROLES、经典特性宏与lp_ws_t默认参数,并在cpu/<chip>/sdk_ld.c中引入对应库链接脚本。 - 裁剪/新增 LE 角色:通过修改
CONFIG_LE_ROLES组合LE_ADV | LE_SCAN | LE_INIT | LE_SLAVE | LE_MASTER使能对应角色代码;新增产品特性时优先以"新位掩码 +BT_MODULES_IS_SUPPORT(x)条件编译"的方式接入,保持与既有 LTO 机制一致。 - 产线测试入口:在应用层按键/串口命令中调用
bredr_set_dut_enble()、bt_fix_fre_api(),配合tws_cancle_all_noconn()与USER_CTRL_WRITE_SCAN_ENABLE/USER_CTRL_WRITE_CONN_ENABLE即可扩展自定义产测流程,无需改动控制器库。 - HCI 扩展:
config_btctler_hci_standard与BT_HCI_STANDARD_IS_SUPPORT(x)为 HCI 标准特性提供裁剪开关,支持向控制器追加自定义 HCI 厂商命令时保持标准兼容。
相关链接
- btcontroller_mode.h — 工作模式与测试模式定义
- btcontroller_modules.h — 模块宏与核心 API 声明
- port/bd29/btcontroller_config.h — bd29 平台控制器配置
- apps/hid/app_main.c — btctrler 任务注册示例
- apps/spp_and_le/app_spp_and_le.c — SPP+LE 应用集成示例
- cpu/bd29/sdk_ld.c — 控制器库链接脚本引入
- 相关目录页:HCI 传输层(
hci_transport.h语义)、BLE 协议栈(GAP/GATT 上层服务)、经典蓝牙 Profile(A2DP/HFP/SPP)、TWS 双耳互联。