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

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

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

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

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

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

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

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

蓝牙协议栈库

AW31N BLE SDK 中的蓝牙协议栈库,基于 BTStack 架构封装,为上层应用提供 BLE(低功耗蓝牙,含 LE 5.x 扩展)与 Classic(经典蓝牙)的 HCI、L2CAP、ATT、GATT、SM 等完整协议能力,并通过统一的事件/命令模型与控制器(Controller)和蓝牙任务(btstack_task)协作。

Purpose and Scope

本文档介绍 SDK 中蓝牙协议栈库的整体架构、分层结构、命令/事件机制、BLE 核心 API 及协议栈生命周期管理,覆盖以下内容:

  • 协议栈对外统一头文件 bluetooth.h 及其聚合的 LE 子模块(ble_api.h、att.h、gatt.h、sm.h、le_user.h、ble_data_types.h)
  • BLE 用户命令集(ble_cmd_type_e)与命令分发接口 ble_user_cmd_prepare
  • 协议栈初始化/退出生命周期回调(btstack_ble_start_before_init / btstack_ble_start_after_init / btstack_ble_exit)
  • BLE 地址管理、GATT Client、SM 安全配对等关键能力

以下主题属于其他目录页面的范围,本文不展开:具体业务 Profile(如 RCSP 私有协议、HID over GATT)请参见对应 Profile 文档;蓝牙配置工具 Lua 脚本(bluetooth_v1.lua、bluetooth_powerprofile.lua)属于配置章节;蓝牙应用层事件处理(如 app_comm_ble.c 中的测试盒逻辑)属于应用开发章节。

Overview

蓝牙协议栈库是 AW31N 芯片 BLE/EDR 双模蓝牙能力的内核部分。它位于应用(App)与射频控制器(Controller)之间,向上以 C 语言 API 的形式暴露广播、扫描、连接、GATT 读写、配对等能力,向下通过 HCI(Host Controller Interface)协议驱动底层控制器。

协议栈的设计延续了 BTStack 开源栈的经典风格:

  • 命令驱动:上层通过 ble_user_cmd_prepare(cmd, argc, ...) 下发命令,命令在协议栈任务(btstack_task)上下文中串行执行,避免并发竞争;
  • 事件回调:控制器上报的 HCI 事件(连接完成、断开、加密变化等)以及协议栈自身状态事件(如 BT_STATUS_INIT_OK)通过 packet handler 分发到应用注册的回调;
  • 分层聚合:bluetooth.h 一个头文件聚合了 LE 全部子模块,应用只需包含该头即可获得完整的 BLE API 面。

关键概念与术语:

术语含义
HCIHost Controller Interface,主机与控制器之间的命令/事件/数据通道
ATTAttribute Protocol,属性协议,GATT 的传输层
GATTGeneric Attribute Profile,通用属性规范,定义服务与特征
SMSecurity Manager,安全管理,负责配对与加密
DUTDirect Test Mode,直通测试模式,用于 BQB/FCC 认证
CCCClient Characteristic Configuration,客户端特征配置(通知使能)

Architecture

下图展示协议栈库在系统中的位置及其内部层次关系:

flowchart TD
    subgraph sg_App["应用层 (App)"]
        AppBLE["app_comm_ble.c<br/>生命周期回调 + 事件处理"]
        AppProfile["业务 Profile<br/>(RCSP / HOGP / 自定义 GATT)"]
    end

    subgraph sg_Stack["蓝牙协议栈库 (Host)"]
        BtstackTask["btstack_task<br/>协议栈任务"]
        BleApi["ble_api.h<br/>命令集 + ble_user_cmd_prepare"]
        Att["att.h<br/>属性协议"]
        Gatt["gatt.h<br/>GATT Server / Client"]
        Sm["sm.h<br/>安全管理/配对"]
        LeUser["le_user.h<br/>LE 用户接口"]
    end

    subgraph sg_Ctl["控制器层 (Controller)"]
        HCI["HCI 通道<br/>(命令/事件/ACL/ISO)"]
        BtctrlerTask["btctrler_task<br/>控制器任务"]
        RF["射频硬件"]
    end

    AppBLE -->|"BLE_CMD_* 命令"| BleApi
    AppProfile -->|"ATT/GATT 操作"| Gatt
    BleApi --> BtstackTask
    BtstackTask --> Att
    Att --> Gatt
    Gatt --> Sm
    LeUser --> BtstackTask
    BtstackTask -->|"HCI 命令/数据"| HCI
    HCI --> BtctrlerTask
    BtctrlerTask --> RF
    RF -.->|"HCI 事件上报"| BtstackTask
    BtstackTask -.->|"BT_STATUS_INIT_OK 等事件"| AppBLE

分层说明

  • 应用层:app_comm_ble.c 实现协议栈生命周期钩子(btstack_ble_start_before_init 等)与蓝牙状态/HCI 事件处理;业务 Profile 通过 GATT 服务注册与回调使用协议栈。
  • 协议栈 Host 层:ble_api.h 定义用户命令集,命令经 btstack_task 串行执行;ATT/GATT/SM 构成 BLE 逻辑链路控制的核心。bluetooth.h 作为统一入口聚合这些模块,并定义 HCI 包类型与 OGF/事件宏。
  • 控制器层:btctrler_task 运行在独立任务中,负责射频收发;与 Host 之间通过 HCI 命令/事件包交互。协议栈还定义了 ISO(LE Audio)相关常量,为后续同步通道扩展预留接口。

设计意图:将协议栈运行在独立任务(btstack_task)中,把命令与事件都收敛到该任务上下文处理,既保证了协议状态机的串行一致性,也让上层应用无需关心底层锁与中断上下文。

协议栈统一头文件 bluetooth.h

apps/include_lib/bt_include/bluetooth.h 是蓝牙协议栈库对外唯一的聚合头文件。应用只需 #include "bluetooth.h" 即可获得 LE 全部能力,无需逐个包含子模块:

//LE
#include "le/ble_data_types.h"
#include "le/ble_api.h"
#include "le/le_user.h"
#include "le/att.h"
#include "le/gatt.h"
#include "le/sm.h"

//Common
#include "btstack_event.h"

Source: bluetooth.h

该头文件还集中定义了与 HCI 传输相关的常量,它们是协议栈与控制器通信的基石:

  • HCI 数据包类型:HCI_COMMAND_DATA_PACKET(0x01)、HCI_ACL_DATA_PACKET(0x02)、HCI_SCO_DATA_PACKET(0x03)、HCI_EVENT_PACKET(0x04),以及 LE Audio 的 HCI_ISO_DATA_PACKET(0x05)。
  • OGF(Opcode Group Field):OGF_LINK_CONTROL(0x01)、OGF_LINK_POLICY(0x02)、OGF_CONTROLLER_BASEBAND(0x03)、OGF_INFORMATIONAL_PARAMETERS(0x04)、OGF_STATUS_PARAMETERS(0x05)、OGF_TESTING(0x06)、OGF_LE_CONTROLLER(0x08)、OGF_VENDOR_LE_CONTROLLER(0x3e)、OGF_VENDOR(0x3f)。
  • HCI 事件宏:从 HCI_EVENT_INQUIRY_COMPLETE(0x01) 到 HCI_EVENT_LINK_KEY_NOTIFICATION(0x18) 等一系列控制器→主机事件码,每个宏都带 @format/@param 注释说明参数字段布局,例如 HCI_EVENT_CONNECTION_COMPLETE 携带 status、connection_handle、bd_addr、link_type、encryption_enabled。
  • ISO 通道常量:ISO_SDU_DTAT_LENGTH(812 字节)、ISO_PDU_DTAT_LENGTH(251 字节)、ISO_PDU_INTERVAL_M_S/ISO_PDU_INTERVAL_S_M(20ms),为 LE Audio/同步流预留。
#define HCI_COMMAND_DATA_PACKET				0x01
#define HCI_ACL_DATA_PACKET	    			0x02
#define HCI_SCO_DATA_PACKET	    			0x03
#define HCI_EVENT_PACKET	    			0x04

// OGFs
#define OGF_LINK_CONTROL            0x01
#define OGF_LINK_POLICY             0x02
#define OGF_CONTROLLER_BASEBAND     0x03
#define OGF_INFORMATIONAL_PARAMETERS 0x04
#define OGF_LE_CONTROLLER           0x08
#define OGF_VENDOR                  0x3f

Source: bluetooth.h

BLE 用户命令集(ble_cmd_type_e)

apps/include_lib/bt_include/le/ble_api.h 定义了协议栈提供给用户的全部命令枚举。注意头文件中的警告:该枚举与库编译密切相关,用户不能自行在中间插入值,否则会造成命令编号错位:

typedef enum {
    BLE_CMD_ADV_ENABLE  = 1,
    BLE_CMD_ADV_PARAM,
    BLE_CMD_ADV_DATA,
    BLE_CMD_RSP_DATA,
    BLE_CMD_DISCONNECT,
    BLE_CMD_REGIEST_THREAD,
    BLE_CMD_ATT_SEND_INIT,
    BLE_CMD_ATT_MTU_SIZE,
    BLE_CMD_ATT_VAILD_LEN,
    BLE_CMD_ATT_SEND_DATA,
    BLE_CMD_REQ_CONN_PARAM_UPDATE,

    BLE_CMD_SCAN_ENABLE,
    BLE_CMD_SCAN_PARAM,
    BLE_CMD_STACK_EXIT,
    BLE_CMD_CREATE_CONN,
    BLE_CMD_CREATE_CONN_CANCEL,
    ...
} ble_cmd_type_e;

Source: ble_api.h

命令按功能域分组,编号区间如下:

命令区间功能域典型命令
1~0x3F基础 BLE 操作广播使能/参数/数据、扫描、连接、断开、ATT 收发、连接参数更新、地址配置、2M PHY、数据长度扩展、多机(MULTI)接口、SM 恢复
0x40~0x7FLE 5.x 扩展扩展广播(EXT_ADV)、周期广播(PERIODIC_ADV)、PHY 设置、扩展扫描/连接
0x80~0xFFGATT Client服务发现(SEARCH_PROFILE)、写 CCC、连接参数更新

命令统一通过可变参数接口下发:

ble_cmd_ret_e ble_user_cmd_prepare(ble_cmd_type_e cmd, int argc, ...);

Source: ble_api.h

命令返回码

ble_cmd_ret_e 定义了命令执行的返回值,用于区分成功与各类失败原因:

返回值值含义
BLE_CMD_RET_SUCESS0执行成功
BLE_CMD_RET_BUSY-100命令处理忙(协议栈任务正忙)
BLE_CMD_PARAM_OVERFLOW-101传数溢出
BLE_CMD_OPT_FAIL-102操作失败
BLE_BUFFER_FULL-103缓存满了
BLE_BUFFER_ERROR-104缓存出错
BLE_CMD_PARAM_ERROR-105传参出错
BLE_CMD_STACK_NOT_RUN-106协议栈没有运行
BLE_CMD_CCC_FAIL-107未使能通知,导致 NOTIFY/INDICATE 发送失败

Source: ble_api.h

常用操作宏

ble_api.h 针对高频操作提供了宏封装,将命令编号与参数封装到一行调用中,例如广播使能:

#define ble_op_adv_enable(enable)     \
	ble_user_cmd_prepare(BLE_CMD_ADV_ENABLE, 1, (int)enable)

Source: ble_api.h

协议栈生命周期管理

协议栈的生命周期由应用层的三个钩子函数驱动,在 apps/demo/transfer/modules/bt/app_comm_ble.c 中实现。这三个函数是协议栈库与应用的固定契约:

初始化前钩子:btstack_ble_start_before_init

在协议栈初始化之前调用,主要职责:DUT 测试模式的时钟调整、BLE 地址的确定与下发:

void btstack_ble_start_before_init(const ble_init_cfg_t *cfg, int param)
{
    u8 tmp_ble_addr[6];

    if (TCFG_NORMAL_SET_DUT_MODE || TCFG_NORMAL_SET_DUT_MODE_API || BT_MODE_IS(BT_BQB) || BT_MODE_IS(BT_FCC) || BT_MODE_IS(BT_FRE)) {
        //bt test mode, 提高sys\lsb\sfc时钟频率
        log_info("dut clock sys 128M, sfc 64M.");
        clk_set("sys", 128000000);
        clock_set_sfc_max_freq(64000000);
        clk_set("sfc", 64000000);
        ...
        return ;
    }

#if TCFG_USER_EDR_ENABLE
    if (!cfg) {
        cfg = &ble_default_config;
    }
    if (cfg->same_address) {
        //ble跟edr的地址一样
        memcpy(tmp_ble_addr, bt_get_mac_addr(), 6);
    } else {
        //生成edr对应唯一地址
        bt_make_ble_address(tmp_ble_addr, (void *)bt_get_mac_addr());
    }
#else
    log_info("ble use bif mac");
    memcpy(tmp_ble_addr, bt_get_mac_addr(), 6);
#endif

    le_controller_set_mac((void *)tmp_ble_addr);
    ...
}

Source: app_comm_ble.c

设计要点:

  • DUT/认证模式优先:BQB/FCC/FRE 测试需要更高的 sys/sfc 时钟(128M/64M),并在初始化前重新配置 bt_pll_para,保证射频时序在测试中的稳定性;
  • 地址策略:支持 BLE 与 EDR 共用地址(same_address=1,直接拷贝 MAC)或由 EDR MAC 派生唯一 BLE 地址(bt_make_ble_address);最终通过 le_controller_set_mac 写入控制器;
  • GATT 公共初始化:CONFIG_BT_GATT_COMMON_ENABLE 打开时调用 bt_ble_before_start_init() 做公共 GATT 服务预初始化。

初始化后钩子:btstack_ble_start_after_init

协议栈初始化完成(收到 BT_STATUS_INIT_OK 事件)后调用,负责 DUT 测试重配置与 BLE 应用层初始化:

void btstack_ble_start_after_init(int param)
{
    if (TCFG_NORMAL_SET_DUT_MODE || BT_MODE_IS(BT_BQB) || BT_MODE_IS(BT_FCC) || BT_MODE_IS(BT_FRE)) {
        log_info("ble2m_mdm_recfg_for_test\n");
        ble2m_mdm_recfg_for_test();
    }

    extern void bt_ble_init(void);
    bt_ble_init();
}

Source: app_comm_ble.c

退出钩子:btstack_ble_exit

协议栈退出时调用,先关闭 BLE 模块再执行协议栈清理:

void btstack_ble_exit(int param)
{
    extern void ble_module_enable(u8 en);
    extern void bt_ble_exit(void);
    ble_module_enable(0);
    bt_ble_exit();
}

Source: app_comm_ble.c

状态事件串联

BT_STATUS_INIT_OK 事件是生命周期从"初始化前"推进到"初始化后"的触发器,由协议栈在初始化完成后发给应用:

int bt_comm_ble_status_event_handler(struct bt_event *bt)
{
    switch (bt->event) {
    case BT_STATUS_INIT_OK:
        log_info("STATUS_INIT_OK\n");
        btstack_ble_start_after_init(0);
        break;
    default:
        break;
    }
    return 0;
}

Source: app_comm_ble.c

核心数据结构

ble_api.h 定义了连接、广播、扫描等核心参数结构,理解这些结构是正确调用协议栈 API 的前提:

连接参数

struct conn_update_param_t {
    u16 interval_min;  //连接周期范围最小值(unit:1.25ms)
    u16 interval_max;  //连接周期范围最大值(unit:1.25ms)
    u16 latency;       //忽略通信次数(unit: interval)
    u16 timeout;       //(unit:10ms)
};

struct create_conn_param_t {
    u16 conn_interval;        //连接周期(unit:1.25ms)
    u16 conn_latency;         //忽略通信次数(unit: interval)
    u16 supervision_timeout;  //(通信超时 unit:10ms)
    u8 peer_address_type;     //对方地址类型:0--public address,1--random address
    u8 peer_address[6];       //对方地址address
} _GNU_PACKED_;

Source: ble_api.h

广播报告

扫描结果由协议栈以 adv_report_t 上报,data[0] 为柔性数组,实际数据长度由 length 指定:

typedef struct {
    u8   event_type;    //对方广播包类型: 0--ADV_IND,1--ADV_DIRECT_IND,2--ADV_SCAN_IND,3--ADV_NONCONN_IND,4--SCAN_RSP
    u8   address_type;  //对方地址类型:0--public address,1--random address
    u8   address[6];    //peer_address
    s8   rssi;          //range:-127 ~128 dbm
    u8   length;        //广播包长度
    u8   data[0];       //广播包内容
} adv_report_t;

Source: ble_api.h

Core Flow:协议栈启动与广播使能的完整链路

下面用序列图展示从系统启动到 BLE 开始广播的完整调用链,涵盖协议栈初始化生命周期与命令下发路径:

sequenceDiagram
    participant App as 应用层 (app_comm_ble.c)
    participant Stack as 协议栈 (btstack_task)
    participant Api as ble_api.h
    participant Ctl as 控制器 (btctrler_task)

    App->>Stack: btstack_ble_start_before_init(cfg)
    Note over App,Stack: 配置时钟/地址,le_controller_set_mac()
    Stack->>Ctl: HCI 命令 (写地址等)
    Ctl-->>Stack: HCI 事件
    Stack-->>App: BT_STATUS_INIT_OK
    App->>App: btstack_ble_start_after_init(0)
    App->>App: bt_ble_init() 注册 GATT 服务
    App->>Api: ble_op_adv_enable(1)
    Api->>Stack: ble_user_cmd_prepare(BLE_CMD_ADV_ENABLE, 1, 1)
    Stack->>Ctl: HCI LE Set Advertising Enable
    Ctl-->>Stack: HCI Command Complete
    Stack-->>App: 命令执行完成回调

关键时序说明:

  1. 启动阶段:系统上电后,协议栈任务 btstack_task 启动,应用调用 btstack_ble_start_before_init 完成 BLE 地址配置与 DUT 时钟设置;
  2. 初始化完成事件:控制器初始化完成后,协议栈向应用上报 BT_STATUS_INIT_OK,应用在 bt_comm_ble_status_event_handler 中调用 btstack_ble_start_after_init 触发 bt_ble_init(注册 GATT 服务、启动 BLE 业务);
  3. 命令下发:应用通过宏/API 组装命令,ble_user_cmd_prepare 将命令投递到协议栈任务;协议栈任务串行解析参数、转换为 HCI 命令下发控制器,控制器回复 Command Complete 事件后协议栈回调通知应用。

Usage Examples

示例 1:BLE 与 EDR 地址策略配置

ble_default_config 是默认的 ble_init_cfg_t 配置,same_address=0 表示 BLE 使用由 EDR MAC 派生的独立地址:

//默认配置
static const ble_init_cfg_t ble_default_config = {
    .same_address = 0,
    .appearance = 0,
};

Source: app_comm_ble.c

示例 2:测试盒(Test Box)厂商事件处理

bt_comm_ble_hci_event_handler 展示了如何响应厂商自定义 HCI 事件:当测试盒通过 BLE 连接/断开时,根据 HCI_EVENT_VENDOR_REMOTE_TEST 事件的值决定是否复位系统以退出测试模式:

int bt_comm_ble_hci_event_handler(struct bt_event *bt)
{
    static u8 testbox_vendor_connect;
    if (bt->event == HCI_EVENT_VENDOR_REMOTE_TEST) {
        log_info("TEST_BOX:%d", bt->value);
        switch (bt->value) {
        case VENDOR_TEST_DISCONNECTED:
            if (testbox_vendor_connect) {
                testbox_vendor_connect = 0;
                log_info("clear_test_box_flag");
                system_reset(BT_FLAG);
                return 0;
            }
            break;

        case VENDOR_TEST_LEGACY_CONNECTED_BY_BLE:
            testbox_vendor_connect = 1;
            break;

        default:
            break;
        }
    }
    return 0;
}

Source: app_comm_ble.c

示例 3:GATT Client 初始化与事件回调注册

BLE 作为 GATT Client(中心设备)时,需要先初始化 Client 角色并注册 packet handler:

void gatt_client_init(void);

void gatt_client_register_packet_handler(btstack_packet_handler_t handler);

Source: ble_api.h

示例 4:设置 BLE 公开地址

le_controller_set_mac 在协议栈非工作状态(未扫描、未广播、未连接)下设置本地公开地址,返回值 0 表示成功:

int le_controller_set_mac(void *addr);

Source: ble_api.h

Configuration Options

协议栈库的配置分散在应用层配置宏与初始化结构体中:

配置项类型默认值说明
TCFG_USER_BLE_ENABLE宏由配置工具生成是否使能 BLE 功能,app_comm_ble.c 整体代码在其保护下编译
TCFG_USER_EDR_ENABLE宏由配置工具生成是否使能经典蓝牙(EDR),影响 BLE 地址生成策略
TCFG_NORMAL_SET_DUT_MODE宏0进入 DUT 直通测试模式
TCFG_NORMAL_SET_DUT_MODE_API宏0通过 API 进入 DUT 测试模式
BT_MODE_IS(BT_BQB/BT_FCC/BT_FRE)宏0认证测试模式(BQB/FCC/FRE),触发高频时钟与测试重配置
ble_init_cfg_t.same_addressu80BLE 地址是否与 EDR 相同;0=派生唯一地址
ble_init_cfg_t.appearanceu80GAP appearance 字段
CONFIG_BT_GATT_COMMON_ENABLE宏0使能公共 GATT 预初始化(bt_ble_before_start_init)

注:上述宏的实际值由 post_build 阶段 AW31N 配置工具生成的配置(如 bluetooth_v1.lua)决定,属于配置章节的范畴,此处仅说明它们对协议栈库行为的直接影响。

API Reference

ble_cmd_ret_e ble_user_cmd_prepare(ble_cmd_type_e cmd, int argc, ...)

协议栈命令的统一入口。所有 BLE 操作(广播、扫描、连接、ATT 收发等)最终都通过该函数下发。

参数:

  • cmd(ble_cmd_type_e):命令编号,见命令集枚举,不可自行插值;
  • argc(int):可变参数个数;
  • ...:命令参数,随命令不同而不同(如使能开关、参数结构体指针等)。

返回:

  • BLE_CMD_RET_SUCESS(0):命令成功提交;
  • 负值错误码:见 ble_cmd_ret_e(BUSY、PARAM_OVERFLOW、OPT_FAIL、BUFFER_FULL、BUFFER_ERROR、PARAM_ERROR、STACK_NOT_RUN、CCC_FAIL)。

说明: 命令在协议栈任务上下文中执行,返回成功仅代表命令被接受,不代表操作已完成;操作结果通过事件回调通知。

int le_controller_set_mac(void *addr)

设置 BLE 控制器的本地公开地址。

参数: addr(void *):6 字节 MAC 地址缓冲。

返回: 0 成功,非 0 失败。

说明: 必须在 BLE 非工作状态(无扫描、无广播、无连接)下调用才生效;可与 ble_op_set_ownaddress_type 配合选择地址类型。

void gatt_client_init(void)

初始化 GATT Client 角色,作为中心设备进行服务发现前必须先调用。

void gatt_client_register_packet_handler(btstack_packet_handler_t handler)

注册 GATT Client 的事件回调函数,用于接收服务发现、特征读写等结果事件。

void le_device_db_init(void)

初始化配对表(设备数据库),上电时调用一次。

void reset_PK_cb_register(void (*reset_pk)(u32 *))

注册 Passkey 输入复位回调。

Failure Modes, Edge Cases & Concurrency

命令执行失败

  • 协议栈未运行:在 btstack_task 尚未就绪时下发命令会返回 BLE_CMD_STACK_NOT_RUN,应用应等待 BT_STATUS_INIT_OK 事件后再启动 BLE 业务;
  • 发送缓冲区满:ATT 数据发送返回 BLE_BUFFER_FULL,需要等待上一包发送完成事件后重试;
  • 通知未使能:对端未写 CCC 使能通知时执行 NOTIFY/INDICATE 会返回 BLE_CMD_CCC_FAIL,这是 GATT 常见失败原因。

生命周期与状态边界

  • 地址修改必须在非工作状态进行(le_controller_set_mac 的注释明确约束),否则修改不生效;
  • 广播/扫描/连接三者不可任意并发,协议栈通过串行命令队列保证状态机一致性,但上层仍需按状态机顺序操作(如先停广播再改广播参数);
  • DUT 模式下协议栈行为被测试模式接管(高频时钟、测试重配置),业务功能不可用。

并发模型

协议栈采用单任务串行模型:所有命令与事件都收敛到 btstack_task 上下文处理。应用侧不同任务同时调用 ble_user_cmd_prepare 是安全的(命令入队串行执行),但回调中不应执行耗时操作,避免阻塞协议栈任务导致后续命令延迟或 HCI 超时。

测试盒/认证模式边界

app_comm_ble.c 的 HCI 事件处理显示:测试盒通过 BLE 连接后断开时系统直接 system_reset(BT_FLAG),这是产测场景的特殊行为——在正常产品代码中应移除或条件编译,防止意外复位。

Performance & Operational Notes

  • DUT 时钟策略:认证测试模式将 sys 时钟提升到 128M、sfc 到 64M,以保证射频时序;量产固件若非测试模式不应启用,以避免功耗增加;
  • ISO 通道预留:bluetooth.h 中 ISO 常量(812/251 字节 SDU/PDU、20ms 间隔)为 LE Audio 预留,启用同步流时需按此规划内存与调度;
  • 数据长度扩展:BLE_CMD_SET_DATA_LENGTH、BLE_CMD_SET_PHY(2M PHY)可用于提升吞吐,但需对端支持,且更长的 PDU 意味着更大的协议栈内存占用;
  • 事件日志:app_comm_ble.c 顶部通过 LOG_TAG/LOG_DEBUG_ENABLE 等宏控制日志等级,调试协议栈行为时可通过日志宏观察 BT_STATUS_INIT_OK、TEST_BOX 等关键事件。

Extension Points

  • 新 GATT 服务:在 bt_ble_init 中注册自定义服务(基于 gatt.h 服务表),可扩展私有 Profile;Jieli 的 RCSP 协议(apps/app/bsp/common/third_party_profile/jieli/JL_rcsp/rcsp_bluetooth.c)即是以此方式实现的标准范例;
  • HID over GATT:apps/demo/hid/modules/bt/ble_hogp.c 展示了在协议栈之上实现 HOGP 设备的完整路径,可作为开发新 Profile 的参考模板;
  • 命令集扩展:ble_cmd_type_e 的注释明确禁止用户插入值,扩展能力应通过新增命令宏或 Profile 层 API 实现,而不能修改库枚举;
  • 多机接口:BLE_CMD_MULTI_ATT_* 系列命令支持单栈多连接场景,多连接应用可直接复用该接口族。

Related Links

  • 蓝牙配置与调试(示例路径):post_build 配置工具 Lua 脚本(bluetooth_v1.lua、bluetooth_powerprofile.lua)决定协议栈编译期宏与功耗配置
  • BLE 应用开发(示例路径):app_comm_ble.c、ble_hogp.c 等应用层实现详解
  • RCSP 私有协议(示例路径):基于 GATT 的 Jieli 私有 Profile 实现
  • 核心源码:
    • bluetooth.h
    • ble_api.h
    • app_comm_ble.c
Next
设备驱动与文件系统库