杰理 SDK 文档中心
首页
首页
  • 概述与快速入门

    • 芯片平台与 SDK 概述
    • 环境搭建与编译工具链
    • 快速开始:选型、编译与烧录
    • 烧录与量产工具
  • 构建系统与板级工程

    • 顶层 Makefile 与编译目标
    • 板级工程与配置
    • 后处理与配置工具
  • HID 人机交互应用

    • HID 应用架构总览
    • 键盘、翻页器与遥控应用
    • 鼠标应用:单模、双模与低延迟
    • 空闲应用与初始化流程
  • BLE 透传与数传应用

    • 透传应用总览
    • 多连接与无连接传输
    • AT 命令模组应用
    • Dongle 适配器应用
  • BSP 公共模块

    • 蓝牙公共处理
    • 按键、LED 与红外
    • 传感器与编码器
    • 存储、VM 与文件系统
    • 电源管理与低功耗
    • 消息调度与通信外设
  • 协议栈与预编译库

    • 蓝牙协议栈库
    • 设备驱动与文件系统库
    • 音频、升级与其他库
  • 开发资料与补丁发布

    • 文档资料中心
    • 版本补丁与兼容性修复

蓝牙公共处理

蓝牙公共处理(bt_common)是 AW31N BLE SDK 中面向应用层复用的蓝牙能力抽象层:它统一封装 EDR(经典蓝牙)与 BLE 的初始化配置结构、HCI 事件/错误码定义、连接控制与配对辅助接口,以及用于射频认证的 BLE DUT(Direct Test Mode)测试 API,使 HID、Transfer 等不同应用可以基于同一套公共接口接入杰理 btstack 协议栈与蓝牙控制器库。

Purpose and Scope

本页面说明「蓝牙公共处理」这一子系统在 SDK 中的位置与职责,具体包括:

  • app_comm_bt.h 中定义的 EDR/BLE 公共初始化配置结构(edr_init_cfg_t、ble_init_cfg_t、edr_sniff_par_t)
  • HCI 事件码与蓝牙错误码的公共映射(配对、连接、断开等场景)
  • 公共 API(BLE 启动/退出、事件分发、连接控制、简易配对开关、重连广播配置)
  • bt_common/ble_test_api.c 中实现的 BLE DUT 测试模式(定频/连续发射)

以下相关主题属于兄弟页面,不在本页展开:具体应用的业务流程(HID/Transfer 应用逻辑)、btstack 协议栈与控制器库内部实现(apps/include_lib/bt_controller_include/)、以及各 demo 的 lib_btstack_config.c / lib_btctrler_config.c 裁剪配置。本页只覆盖它们共同依赖的「公共处理」部分。

Overview

在 AW31N 的软件架构中,应用(HID、Transfer 等 demo)与杰理 btstack/控制器库之间隔着一层公共适配代码。这层代码解决三个共性问题:

  1. 初始化契约统一:BLE 与 EDR 共存的芯片上,BLE 和经典蓝牙共享射频与地址管理。ble_init_cfg_t 中的 same_address 字段专门用于声明 BLE 与 EDR 是否使用相同地址,这决定了控制器层如何分配 BD_ADDR,是双模共存的关键开关。
  2. 事件与错误语义统一:应用通过 struct bt_event 收到协议栈上报的事件,公共层把 HCI 事件码(HCI_EVENT_CONNECTION_COMPLETE 等)和错误码(ERROR_CODE_*)定义为可读常量,并区分「应用主动取消 Page」与「基带取消 Page」两种自定义事件(CUSTOM_BB_AUTO_CANCEL_PAGE / BB_CANCEL_PAGE),避免上层与库层语义混淆。
  3. 测试/产测能力挂载:ble_test_api.c 在 TCFG_NORMAL_SET_DUT_MODE_API 宏开启时提供 BLE 定频、DUT 模式入口,供产测或认证(FCC/CE 等)使用,与正常业务路径隔离。

公共层刻意保持「薄」:它只做参数组织、事件分发与状态机入口,不承载具体业务逻辑,因此所有 demo 都可以安全复用。

Architecture

flowchart TD
    subgraph sg_App["应用层 (apps/demo)"]
        HID["HID 应用"]
        Transfer["Transfer 应用"]
    end

    subgraph sg_Common["蓝牙公共处理层 (bt_common)"]
        CommBT["app_comm_bt.h<br/>配置结构 / 事件码 / 错误码 / 公共 API"]
        DUT["ble_test_api.c<br/>BLE DUT 定频测试模式"]
    end

    subgraph sg_Lib["SDK 库层 (apps/include_lib)"]
        BTStack["btstack 协议栈库<br/>(IRQ_BTSTACK_MSG_IP)"]
        Ctrl["蓝牙控制器库 btctler<br/>(btctrler_task.h / hci_transport.h)"]
    end

    subgraph sg_HW["硬件层"]
        RF["BLE/EDR 射频收发器"]
    end

    HID -->|"引用 app_comm_bt.h"| CommBT
    Transfer -->|"引用 app_comm_bt.h"| CommBT
    CommBT -->|"启动/退出/事件分发"| BTStack
    CommBT -->|"连接/扫描控制"| Ctrl
    DUT -->|"ll_hci_destory / __ble_dut_ops"| Ctrl
    BTStack -->|"HCI 传输"| Ctrl
    Ctrl -->|"空口收发"| RF

架构说明:app_comm_bt.h 是纯接口头文件(无实现依赖),被各 demo 直接 include;它声明的 API 指向 btstack/控制器库提供的服务。ble_test_api.c 位于 apps/app/bsp/common/bt_common/,编译期由 TCFG_NORMAL_SET_DUT_MODE_API 门控,仅在产测/认证固件中编入,正常业务固件不携带 DUT 代码。这样既保证公共 API 的单一来源,又避免测试代码进入量产固件。

核心数据结构

EDR 初始化配置

edr_init_cfg_t 聚合了经典蓝牙建立连接所需的核心参数:

  • class_type:设备类别(CoD),决定对端搜索时显示的图标;
  • page_timeout / super_timeout:建链与监督超时(单位:时隙),影响连接失败时的等待时长;
  • io_capabilities / authentication_req / oob_data / passkey_enable:配对与安全相关位域,共同决定简易配对(SSP)流程;
  • report_map / report_map_size:HID 报告描述符指针与长度,供 HID 类设备上报;
  • sniff_param:指向 edr_sniff_par_t,配置低功耗 Sniff 模式参数。
typedef struct {
    u16 max_interval_slots;
    u16 min_interval_slots;
    u8 attempt_slots;
    u8 timeout_slots;
    u16 check_timer_period; //检查周期
    u8 cnt_time;//<空闲多少秒之后进入sniff模式
    u8 sniff_mode;
} edr_sniff_par_t;

typedef struct {
    u32 class_type;//搜索显示图标
    u16 page_timeout;
    u16 super_timeout;
    u8 io_capabilities: 2;
    u8 authentication_req: 3;
    u8 oob_data: 2;
    u8 passkey_enable: 1;
    u16 report_map_size;
    const u8 *report_map;
    const edr_sniff_par_t *sniff_param;
} edr_init_cfg_t;

来源:app_comm_bt.h

设计意图:sniff_param 与 report_map 使用指针而非内嵌数组,允许上层把大块数据(HID 报告描述符)放在只读段,减小栈上拷贝开销。sniff_mode 支持两种枚举值(SNIFF_MODE_DEF 与 SNIFF_MODE_ANCHOR),SNIFF_MODE_ANCHOR 用于对端支持锚点连接时进一步降低功耗。

BLE 初始化配置

typedef struct {
    //ble跟edr的地址一样
    u8 same_address;
    u16 appearance; //搜索显示图标
    u16 report_map_size;
    const u8 *report_map;

} ble_init_cfg_t;

来源:app_comm_bt.h

same_address 是双模共存的地址策略开关:置 1 时 BLE 与 EDR 共享同一 BD_ADDR,对端看到的两个接口地址一致,简化配对与绑定管理;置 0 时使用独立地址。appearance 决定 BLE 广播/扫描响应中对端显示的图标类型。

HCI 事件码与错误码定义

公共层把协议栈上报的事件与错误收敛为宏定义,应用的事件处理函数据此分发:

#define HCI_EVENT_INQUIRY_COMPLETE                            0x01
#define HCI_EVENT_CONNECTION_COMPLETE                         0x03
#define HCI_EVENT_DISCONNECTION_COMPLETE                      0x05
#define HCI_EVENT_PIN_CODE_REQUEST                            0x16
#define HCI_EVENT_IO_CAPABILITY_REQUEST                       0x31
#define HCI_EVENT_USER_CONFIRMATION_REQUEST                   0x33
#define HCI_EVENT_USER_PASSKEY_REQUEST                        0x34
#define HCI_EVENT_USER_PRESSKEY_NOTIFICATION                  0x3B
#define HCI_EVENT_VENDOR_NO_RECONN_ADDR                       0xF8
#define HCI_EVENT_VENDOR_REMOTE_TEST                          0xFE
#define BTSTACK_EVENT_HCI_CONNECTIONS_DELETE                  0x6D

#define ERROR_CODE_SUCCESS                                    0x00
#define ERROR_CODE_PAGE_TIMEOUT                               0x04
#define ERROR_CODE_AUTHENTICATION_FAILURE                     0x05
#define ERROR_CODE_PIN_OR_KEY_MISSING                         0x06
#define ERROR_CODE_CONNECTION_TIMEOUT                         0x08
#define ERROR_CODE_SYNCHRONOUS_CONNECTION_LIMIT_TO_A_DEVICE_EXCEEDED  0x0A
#define ERROR_CODE_ACL_CONNECTION_ALREADY_EXISTS                      0x0B
#define ERROR_CODE_CONNECTION_REJECTED_DUE_TO_LIMITED_RESOURCES       0x0D
#define ERROR_CODE_CONNECTION_REJECTED_DUE_TO_UNACCEPTABLE_BD_ADDR    0x0F
#define ERROR_CODE_CONNECTION_ACCEPT_TIMEOUT_EXCEEDED         0x10
#define ERROR_CODE_REMOTE_USER_TERMINATED_CONNECTION          0x13
#define ERROR_CODE_CONNECTION_TERMINATED_BY_LOCAL_HOST        0x16

#define CUSTOM_BB_AUTO_CANCEL_PAGE                            0xFD  //// app cancle page
#define BB_CANCEL_PAGE                                        0xFE  //// bb cancle page

来源:app_comm_bt.h

值得注意的设计细节:CUSTOM_BB_AUTO_CANCEL_PAGE(0xFD)与 BB_CANCEL_PAGE(0xFE)是杰理控制器库自定义的「取消 Page」事件——前者是应用发起取消、后者是基带(BB)因超时等原因自行取消。两者在 0xF0~0xFF 厂商保留区内取值,不会与标准 HCI 事件冲突;上层通常用 CUSTOM_BB_AUTO_CANCEL_PAGE 判断「用户主动停止搜索」,以区别被动失败。

WAIT_DISCONN_TIME_MS(1000ms)定义了默认断开等待时间,供公共层在收到断开请求后给协议栈留出完成断链动作的时间窗:

//默认断开BT等待时间
#define WAIT_DISCONN_TIME_MS     (1000)

来源:app_comm_bt.h

公共 API 接口

app_comm_bt.h 声明的全部公共接口如下(实现位于 SDK 库或应用源码,本页以接口契约为准):

void btstack_ble_start_before_init(const ble_init_cfg_t *cfg, int param);
void btstack_ble_start_after_init(int param);
void btstack_ble_exit(int param);
int bt_comm_ble_status_event_handler(struct bt_event *bt);
int bt_comm_ble_hci_event_handler(struct bt_event *bt);
void bt_wait_phone_connect_control_ext(u8 inquiry_en, u8 page_scan_en);
void bt_wait_phone_connect_control(u8 enable);

/*简易配对开关接口*/
void __set_simple_pair_flag(bool flag);

// void le_hogp_set_direct_adv_type(u8 type);
void le_hogp_set_reconnect_adv_cfg(u8 adv_type, u32 adv_timeout);

来源:app_comm_bt.h

按职责可将接口分为四组:

  1. 生命周期管理:btstack_ble_start_before_init(在控制器初始化前传入 ble_init_cfg_t)、btstack_ble_start_after_init(初始化完成后启动 BLE 任务)、btstack_ble_exit(退出 BLE)。before/after 的拆分是为了让地址策略(same_address)在控制器初始化阶段就生效,而协议栈任务在硬件就绪后才拉起。
  2. 事件分发:bt_comm_ble_status_event_handler / bt_comm_ble_hci_event_handler 接收 struct bt_event,返回 int 表示事件是否被消费。这是公共层与应用状态机之间的唯一事件入口。
  3. 连接控制:bt_wait_phone_connect_control(u8 enable) 统一开关「等待手机连接」状态;bt_wait_phone_connect_control_ext 进一步细分 inquiry 与 page scan 的独立开关,便于只开可被发现(Inquiry Scan)而暂不响应连接(Page Scan)的场景。
  4. 配对与重连:__set_simple_pair_flag 全局开关简易配对;le_hogp_set_reconnect_adv_cfg(adv_type, adv_timeout) 配置 HOGP 重连广播的类型与超时(adv_type 对应直连/可连接广播类型,adv_timeout 控制重连窗口时长)。

核心流程

BLE 启动与事件分发流程

flowchart TD
    Start(["应用启动"]) --> PreInit["btstack_ble_start_before_init<br/>(传入 ble_init_cfg_t)"]
    PreInit --> AfterInit["btstack_ble_start_after_init"]
    AfterInit --> WaitEvent["等待 bt_event 上报"]
    WaitEvent --> StatusHandler["bt_comm_ble_status_event_handler"]
    StatusHandler --> HciHandler["bt_comm_ble_hci_event_handler"]
    HciHandler --> Decide{"HCI 事件类型?"}
    Decide -->|"CONNECTION_COMPLETE 0x03"| Conn["连接建立<br/>记录对端地址"]
    Decide -->|"DISCONNECTION_COMPLETE 0x05"| Disconn["连接断开<br/>等待 WAIT_DISCONN_TIME_MS 复位状态"]
    Decide -->|"USER_CONFIRMATION_REQUEST 0x33"| Confirm["SSP 配对确认"]
    Decide -->|"VENDOR_NO_RECONN_ADDR 0xF8"| Reconn["重连地址丢失<br/>触发重新广播/回连"]
    Decide -->|"CUSTOM_BB_AUTO_CANCEL_PAGE 0xFD"| Cancel["应用取消 Page 成功"]
    Conn --> AppState["应用状态机更新"]
    Disconn --> AppState
    Confirm --> AppState
    Reconn --> AppState
    Cancel --> AppState

流程说明:公共层的两个 event handler 是串行的(同一 bt_event 先走 status 再走 hci 分发),保证状态机按顺序推进。厂商自定义事件(0xF8/0xFD/0xFE)在标准 HCI 事件之前被识别,避免落入默认分支。

BLE DUT 测试模式流程

sequenceDiagram
    participant App as 应用 (TCFG_NORMAL_SET_DUT_MODE_API)
    participant DUT as ble_test_api.c
    participant LL as 链路层 ll_hci_destory
    participant Ops as __ble_dut_ops 操作表
    participant HCI as HCI UART (115200)

    App->>DUT: ble_dut_mode_init()
    DUT->>LL: ll_hci_destory()
    DUT->>Ops: __ble_dut_ops->init()
    DUT->>HCI: 建立 HCI 传输 (hci_transport_config_uart_t)
    App->>DUT: ble_fix_fre_api()
    DUT->>HCI: bt_ble_adv_enable(0) 停止广播
    DUT->>HCI: ble_enter_dut_tx_mode(dut_param)
    Note over HCI: 连续发射 PRBS9/10101010/11110000<br/>等测试载荷 (ch_index 0~39)

BLE DUT 测试模式(ble_test_api.c)

apps/app/bsp/common/bt_common/ble_test_api.c 是整个 SDK 中位于 bt_common 目录下的实现文件,仅在 TCFG_NORMAL_SET_DUT_MODE_API 编译开关打开时编译(#if TCFG_NORMAL_SET_DUT_MODE_API 包裹)。它提供射频测试所需的载荷与 PHY 枚举、参数结构和入口函数。

载荷与 PHY 类型

enum  BLE_DUT_PAYLOAD_TYPE {
    PAYLOAD_TYPE_PRBS9 = 0,
    PAYLOAD_TYPE_11110000,
    PAYLOAD_TYPE_10101010,
    PAYLOAD_TYPE_PRBS15,
    PAYLOAD_TYPE_11111111,
    PAYLOAD_TYPE_00000000,
    PAYLOAD_TYPE_00001111,
    PAYLOAD_TYPE_01010101,

    PAYLOAD_TYPE_SINGLE_CARRIER = 0xf0,
};

enum BLE_DUT_PHY_TYPE {
    BLE_1M_UNCODED_PHY = 1,
    BLE_2M_UNCODED_PHY,
    BLE_1M_CODED_PHY_S8,
    BLE_1M_CODED_PHY_S2,
};

struct ble_dut_param_set {
    u8 ch_index;		//tx ch index;(0~39 -> 2402~2480)
    u8 payload_type;	//tx payload type
    u8 payload_len;		//payload_len(0~0xff) when continuous_tx = 0;
    u8 continuous_tx;	//enable or disable continuous transmission mode(0/1)
};

来源:ble_test_api.c

PAYLOAD_TYPE_PRBS9/PRBS15 是标准蓝牙测试载荷(伪随机序列),PAYLOAD_TYPE_SINGLE_CARRIER(0xF0)用于单载波测试;PHY 枚举覆盖 1M/2M 非编码与 1M 编码(S8/S2),对应 BLE 5.x 测试规范。ch_index 0~39 映射 2402~2480 MHz 的 40 个信道。

DUT 入口实现

static hci_transport_config_uart_t config = {
    HCI_TRANSPORT_CONFIG_UART,
    115200,
    0,  // main baudrate
    0,  // flow control
    NULL,
};

来源:ble_test_api.c

/* !!!Notice:when this api is called and sleep mode should be sure to exit; */
void ble_fix_fre_api()
{
#if TCFG_USER_BLE_ENABLE
#if (CONFIG_BT_MODE == BT_NORMAL)
    bt_ble_adv_enable(0);
#endif
    os_time_dly(10);

    struct ble_dut_param_set dut_param = {
        .ch_index = 0,
        .payload_type = PAYLOAD_TYPE_10101010,
        .payload_len = 0x20,
        .continuous_tx = 1,
    };
    ble_enter_dut_tx_mode(&dut_param);
#endif
}

void ble_dut_mode_init(void)
{
    if (!ble_dut_hdl) {
        ll_hci_destory();
        ble_dut_hdl = __ble_dut_ops->init();
        ...
    }
}

来源:ble_test_api.c

实现要点:

  • 先停广播再进 DUT:ble_fix_fre_api 先调用 bt_ble_adv_enable(0) 关闭正常广播,再延时 10 个 OS tick 让空口安静,随后注入测试参数——避免正常广播干扰频谱测量。
  • 销毁链路层再建测试会话:ble_dut_mode_init 通过 ll_hci_destory() 拆除正常协议栈的链路层实例,再用 __ble_dut_ops->init() 建立独立的测试控制通道,ble_dut_hdl 静态句柄保证同一时刻只有一条 DUT 会话(非空则跳过重复初始化,见 if (!ble_dut_hdl))。
  • 回调操作表:__ble_dut_ops 是控制器库导出的函数指针表(init 等成员),公共层不直接依赖具体函数,便于不同芯片/库版本替换——这是典型的 ops 表扩展点。
  • 注释明确约束:源码注释强调调用 DUT API 前必须退出睡眠模式("when this api is called and sleep mode should be sure to exit"),因为 DUT 连续发射与低功耗睡眠互斥。

文件头部还声明了经典蓝牙测试入口:bredr_fcc_init(u8 mode, u8 fre)、dut_hci_controller_init(const hci_transport_t *transport, const void *config)、bt_ble_adv_enable(u8 enable) 等,供产测工具通过 UART HCI 驱动控制器进入 FCC 定频模式。文件内的 bt_fix_fre_api/bt_dut_api 示例目前被 #if 0 注释禁用(演示用途),正式定频入口是上方的 ble_fix_fre_api。

模块内使用 static volatile u8 bt_test_status 记录测试状态,volatile 保证中断/任务上下文之间对状态的读取一致;LOG_TAG "[BT_DUT]" 配合 LOG_*_ENABLE 宏使 DUT 日志独立可裁剪。

配置选项

公共处理层的配置以编译期宏和头文件常量为主(运行期配置由 ble_init_cfg_t / edr_init_cfg_t 传入):

配置项类型默认值说明
TCFG_NORMAL_SET_DUT_MODE_API编译宏由 app_config 决定是否编入 BLE DUT 测试模式(ble_test_api.c 整体由 #if 包裹)
TCFG_USER_BLE_ENABLE编译宏由 app_config 决定是否启用 BLE 功能;DUT 入口内部以此判断是否执行 bt_ble_adv_enable(0)
CONFIG_BT_MODE编译宏BT_NORMAL蓝牙工作模式;BT_NORMAL 下 DUT 前先停广播
WAIT_DISCONN_TIME_MS常量1000默认断开 BT 等待时间(毫秒)
SNIFF_MODE_DEF / SNIFF_MODE_ANCHOR枚举SNIFF_MODE_DEFEDR Sniff 模式选择:默认 / 锚点模式
edr_sniff_par_t.check_timer_period结构体字段上层设定Sniff 检查周期
edr_sniff_par_t.cnt_time结构体字段上层设定空闲多少秒后进入 Sniff 模式
HCI_TRANSPORT_CONFIG_UART baudrate结构体字段115200DUT 模式下 HCI UART 波特率(ble_test_api.c 静态配置)

配置入口分散在:apps/demo/hid/config/、apps/demo/transfer/config/ 下的 lib_btstack_config.c / lib_btctrler_config.c(协议栈与控制器裁剪),以及各 app 的 app_config.h(TCFG_* 系列)。公共层本身不持有这些宏的默认值,而是按调用方编译配置生效——这保证了不同 demo 可以差异化裁剪而不改公共代码。

API 参考

生命周期与事件

void btstack_ble_start_before_init(const ble_init_cfg_t *cfg, int param) 在控制器初始化前配置 BLE 参数。cfg 中的 same_address 必须在此阶段生效,因为地址分配发生在控制器初始化时。param 为保留扩展参数。

void btstack_ble_start_after_init(int param) 控制器初始化完成后启动 BLE 协议栈任务。必须在 btstack_ble_start_before_init 之后调用。

void btstack_ble_exit(int param) 退出 BLE:停止协议栈任务并释放相关资源,用于切换模式(如仅 EDR)或关机流程。

int bt_comm_ble_status_event_handler(struct bt_event *bt) BLE 状态事件分发入口。bt 指向协议栈填充的事件结构;返回非 0 表示事件已被消费。与 HCI 事件处理器配合完成连接/断开/配对状态机推进。

int bt_comm_ble_hci_event_handler(struct bt_event *bt) HCI 层事件分发入口,负责按 HCI_EVENT_* 宏分发到具体处理分支(连接完成、断开、SSP 确认、重连地址等)。

连接与配对控制

void bt_wait_phone_connect_control(u8 enable) 统一开关「等待手机连接」:enable 非 0 打开可发现与可连接,0 关闭。适合按键进入配对模式的简单场景。

void bt_wait_phone_connect_control_ext(u8 inquiry_en, u8 page_scan_en) 细分控制:inquiry_en 控制 Inquiry Scan(被发现),page_scan_en 控制 Page Scan(被连接)。可独立实现「可被发现但暂不接受连接」的窗口逻辑。

void __set_simple_pair_flag(bool flag) 简易配对(SSP)总开关。关闭后回退到传统配对流程(PIN Code 输入),用于兼容老旧设备。

void le_hogp_set_reconnect_adv_cfg(u8 adv_type, u32 adv_timeout) HOGP(HID over GATT)重连广播配置:adv_type 选择广播类型(可连接直连广播等),adv_timeout 限制重连广播的持续时间,超时后停止广播以省电。

DUT 测试(ble_test_api.c)

void ble_dut_mode_init(void) 初始化 DUT 测试会话:ll_hci_destory() 拆除链路层后经 __ble_dut_ops->init() 建立测试控制通道。静态句柄保证单实例,重复调用直接返回。

void ble_fix_fre_api() 进入定频连续发射:先 bt_ble_adv_enable(0) 停止广播,延时 10 tick 后以 PAYLOAD_TYPE_10101010、continuous_tx = 1 调用 ble_enter_dut_tx_mode。调用前必须退出睡眠模式。

void ble_enter_dut_tx_mode(void *param)(库导出,外部声明) 按 struct ble_dut_param_set 参数启动 DUT TX。ch_index 0~39 对应 2402~2480 MHz,payload_type/payload_len/continuous_tx 决定载荷与是否连续发射。

void bt_ble_adv_enable(u8 enable)(库导出,外部声明) 使能/禁止 BLE 广播,DUT 入口用它先关闭正常广播。

失败模式与边界情况

  • Page 取消语义区分:CUSTOM_BB_AUTO_CANCEL_PAGE(0xFD,应用发起)与 BB_CANCEL_PAGE(0xFE,基带超时)必须分开处理——前者是用户主动行为(如按键停止搜索),后者是系统被动失败(如 ERROR_CODE_PAGE_TIMEOUT)。混淆两者会导致 UI 状态与空口行为不一致。
  • 配对失败码映射:ERROR_CODE_AUTHENTICATION_FAILURE/PIN_OR_KEY_MISSING/CONNECTION_ACCEPT_TIMEOUT_EXCEEDED 等错误码在事件处理器中应映射为不同的用户提示(PIN 错误、超时、对端拒绝),公共层只提供语义化常量,提示策略由应用决定。
  • 断开时序:WAIT_DISCONN_TIME_MS(1000ms)是断开动作的时间窗;若上层立即释放资源可能破坏正在进行的 L2CAP/SM 断链握手,公共层用它保证状态机在断链完成后才复位。
  • DUT 与睡眠互斥:DUT 连续发射期间必须退出睡眠(源码注释明确警告)。若固件在 DUT 会话中进入睡眠,射频发射将被挂起,频谱测量失败且可能卡死测试流程。
  • DUT 单实例约束:ble_dut_hdl 非空时 ble_dut_mode_init 不再重新初始化,重复进入 DUT 不会二次销毁链路层,避免悬挂指针。
  • 并发/中断:bt_test_status 声明为 volatile,因它可能被任务上下文与中断上下文同时读写;任何基于它的状态机判断都应视为弱同步(无原子保护),临界区需由调用方保证。
  • 双模地址冲突:ble_init_cfg_t.same_address = 0 时 BLE 与 EDR 地址独立,若上层未同步管理两份地址,跨协议(如手机先连 BLE 再连 EDR)的绑定记录可能失配;same_address = 1 可规避但限制地址自定义空间。

性能与运维注意

  • Sniff 功耗:check_timer_period 与 cnt_time 控制 EDR 空闲后进入 Sniff 的时机;cnt_time 越大空口越安静但省电越慢,timeout_slots 越小 Sniff 唤醒越频繁。量产固件应按平均连接间隔调参,避免过度频繁的 Sniff 尝试影响连接保持。
  • DUT 测试为独占模式:DUT 会话销毁正常链路层(ll_hci_destory),测试后需完整重启协议栈才能恢复业务,产测固件通常设计为测试完成即复位。
  • 日志裁剪:LOG_TAG "[BT_DUT]" 配合 LOG_DUMP_ENABLE 等宏,量产固件应关闭 DUMP 级日志以减小代码体积与日志吞吐开销。

扩展点

  1. __ble_dut_ops 操作表:DUT 控制通过函数指针表访问控制器能力,新芯片/库版本只需提供同签名实现即可复用 ble_test_api.c 全部逻辑。
  2. struct bt_event 事件分发:两个 event handler 是公共层留给应用的状态机钩子,应用可在其中挂接自己的连接/配对状态机,而无需修改协议栈。
  3. edr_init_cfg_t / ble_init_cfg_t:通过指针字段(report_map、sniff_param)注入业务特有数据,HID 类应用可在不修改公共层的前提下提供自定义报告描述符与 Sniff 参数。
  4. 编译期裁剪:TCFG_NORMAL_SET_DUT_MODE_API、TCFG_USER_BLE_ENABLE、CONFIG_BT_MODE 决定编入范围,同一份公共代码可服务产测固件与量产固件两种形态。

Related Links

  • app_comm_bt.h 公共接口头文件
  • ble_test_api.c DUT 测试实现
  • btcontroller_modules.h 控制器模块声明
  • btctrler_task.h 控制器任务/队列定义
  • hci_transport.h HCI 传输层接口
  • HID/Transfer demo 的协议栈裁剪配置(apps/demo/hid/config/lib_btstack_config.c、apps/demo/transfer/config/lib_btctrler_config.c)属于各应用页面的范围

使用示例

以下示例仅使用本页已核实的头文件契约与实现片段进行组装,展示应用如何把公共层的配置结构与 API 串联起来(实际接入点位于各 demo 应用源码,如 apps/demo/hid、apps/demo/transfer)。

组装 BLE 初始化配置并启动

BLE 启动分两步走:先 before_init 让地址策略生效,后 after_init 拉起协议栈:

/* 按 app_comm_bt.h 中的 ble_init_cfg_t 契约组装 */
ble_init_cfg_t ble_cfg = {
    .same_address    = 1,          /* BLE 与 EDR 共用地址,简化双模绑定 */
    .appearance      = 0x0040,     /* 搜索时显示的图标(Audio Sink 类) */
    .report_map_size = 0,          /* 非 HOGP 场景可不提供报告描述符 */
    .report_map      = NULL,
};

btstack_ble_start_before_init(&ble_cfg, 0);   /* 控制器初始化前配置 */
/* ... 控制器初始化由库完成 ... */
btstack_ble_start_after_init(0);              /* 初始化完成后启动 BLE 任务 */

来源:app_comm_bt.h、app_comm_bt.h

在事件处理器中按 HCI 事件码分发

事件处理器返回 int 表示是否消费,公共层用宏定义把裸事件码翻译成语义:

int app_bt_event_dispatch(struct bt_event *bt)
{
    /* 先经公共层状态事件,再走 HCI 事件分发 */
    bt_comm_ble_status_event_handler(bt);
    switch (bt->event) {
    case HCI_EVENT_CONNECTION_COMPLETE:        /* 0x03 连接建立 */
        /* 记录对端地址、更新 UI 为已连接 */
        return 1;
    case HCI_EVENT_DISCONNECTION_COMPLETE:     /* 0x05 连接断开 */
        /* 等待 WAIT_DISCONN_TIME_MS 后复位状态机 */
        return 1;
    case CUSTOM_BB_AUTO_CANCEL_PAGE:           /* 0xFD 用户主动取消搜索 */
        /* 区别于 BB_CANCEL_PAGE(0xFE) 被动取消 */
        return 1;
    }
    return 0;   /* 未消费,交由其他模块处理 */
}

来源:app_comm_bt.h、app_comm_bt.h

产测固件进入 BLE 定频发射

在 TCFG_NORMAL_SET_DUT_MODE_API 开启的产测固件中,初始化 DUT 会话后即可定频连续发射:

/* 1. 建立 DUT 会话(销毁正常链路层,经 __ble_dut_ops 创建测试通道) */
ble_dut_mode_init();

/* 2. 进入定频连续发射:停广播 → 延时 → 注入 10101010 连续载荷 */
ble_fix_fre_api();
/* 内部等价于:
 *   bt_ble_adv_enable(0);
 *   os_time_dly(10);
 *   struct ble_dut_param_set p = { .ch_index=0, .payload_type=PAYLOAD_TYPE_10101010,
 *                                  .payload_len=0x20, .continuous_tx=1 };
 *   ble_enter_dut_tx_mode(&p);
 */

来源:ble_test_api.c、ble_test_api.c

使用约束:上述 DUT 调用前必须确保已退出睡眠模式(源码注释的硬性要求),且测试完成后需复位系统才能恢复正常协议栈业务。

Next
按键、LED 与红外