杰理 SDK 文档中心
首页
首页
  • 项目概览

    • SDK 简介与核心特性
    • 芯片平台与硬件资料
    • SDK 版本与发布信息
  • 快速开始

    • 环境搭建与工具链
    • 编译工程
    • 烧录与量产工具
  • 工程结构与构建系统

    • 工程目录布局
    • 构建与链接配置
  • 应用层开发

    • mbox_flash 应用框架
    • 板级支持包 (BSP)
    • 公共应用模块
    • UI 显示子系统
  • 蓝牙子系统

    • BLE 控制器、链路层与 HCI 传输
    • GATT 服务框架
    • BLE 应用示例:遥控器 / Dongle / 对讲机
    • 经典蓝牙支持
  • 音频子系统

    • 音频编解码器
    • 音频设备接口 (DAC / ADC / APA)
    • 音效处理与 EQ
    • 播放、录音与 MIO 工作流
  • 设备与文件系统

    • 存储设备驱动 (NorFlash / SDMMC / USB)
    • 文件系统 (FAT / nor_fs / SYDF)
    • 设备管理框架 (dev_mg)
  • 系统服务与电源管理

    • 消息机制 (msg / hot_msg)
    • 配置与参数存储 (app_config / VM)
    • 电源管理 (SOFT OFF / POWER DOWN)
  • 固件升级

    • 升级框架总览 (code_v1 / code_v2)
    • 双 Bank 升级机制
    • 升级通道:UART / 测试盒 / BLE OTA / USB / SD
  • 补丁包与版本维护

    • 版本升级补丁链 (v1.1.0 → v1.4.0)
    • 问题修复补丁
    • 固件裁剪与资源优化
  • 开发工具与支持

    • 辅助工具与脚本
    • 文档、配置说明与常见问题

经典蓝牙支持

AW30N BLE SDK 中经典蓝牙(BR/EDR)能力的完整说明:包括双模(经典 + BLE)协议栈架构、SPP 串口协议、EDR HID 设备协议、EDR 主机(Emitter)模式,以及相关配置宏与代码入口。

Purpose and Scope

本文档介绍 AW30N SDK 中**经典蓝牙(Classic Bluetooth / BR/EDR)**子系统的支持方式与使用方法。内容涵盖:

  • 经典蓝牙与 BLE 共存的双模架构(bt_common 目录下的 spp_and_le、hid 等 profile 工程结构);
  • 经典蓝牙协议栈分层(btstack 主机协议栈 + btctrler 控制器)及配置入口;
  • 经典蓝牙支持的协议:SPP(Serial Port Profile) 与 EDR HID;
  • 经典蓝牙 EDR 主机模式(EDR_EMITTER_EN,inquiry + page 流程);
  • 与经典蓝牙相关的配置宏、日志开关、OTA 升级回调等代码入口。

与经典蓝牙相关的、但属于其他能力范畴的主题不在本文档展开,请参见对应页面:

  • 纯 BLE(GATT/SM/广播)的详细机制属于 BLE 协议栈相关页面;
  • 各具体应用示例(Dongle、SPP+LE、HID 等)的完整工程级说明属于各自示例页面;
  • 板级外设配置(board_config.h、app_config.c 中非蓝牙部分)属于板级适配页面。

Overview

AW30N 是一颗支持双模蓝牙的 SoC:既能运行 BLE(低功耗蓝牙),也支持经典蓝牙 BR/EDR(用于 SPP 透传、EDR HID 键鼠、经典音频等场景)。SDK 中经典蓝牙的使能由一组编译期宏控制,核心入口集中在:

  • sdk/apps/app/bsp/common/bt_common/bt_profile_cfg.h —— 全局 profile 选择与 SPP 开关;
  • sdk/apps/app/bsp/common/bt_common/spp_and_le/include/spple_app_config.h —— SPP + LE 双模应用选择(SPP_LE / MULTI / DONGLE / CENTRAL / LL_SYNC 等),其中 DONGLE 工程支持 EDR 主机模式;
  • sdk/apps/app/bsp/common/bt_common/hid/include/ —— EDR HID 设备协议头文件(edr_hid_user.h、standard_hid.h、app_comm_bt.h);
  • sdk/apps/app/bsp/common/bt_common/spp_and_le/config/ 与 hid/config/ —— 每个 profile 各自的 lib_btstack_config.c(主机协议栈配置)与 lib_btctrler_config.c(控制器配置)。

经典蓝牙的能力默认未全量开启,而是通过条件编译按应用裁剪。例如 USER_SUPPORT_PROFILE_SPP 只有在 BT_FOR_APP_EN(或 APP_ONLINE_DEBUG、AI_APP_PROTOCOL)为真时才被定义;而 BT_FOR_APP_EN 又由 TRANS_DATA_EN、RCSP_BTMATE_EN、RCSP_ADV_EN、SMART_BOX_EN、ANCS_CLIENT_EN、LL_SYNC_EN、TUYA_DEMO_EN 任一使能时自动打开。这种"按需使能、自动推导"的设计意图是:在 256KB Flash 级别的资源受限产品中,避免未使用的协议栈代码和 SDP 服务记录占用的 ROM/RAM。

Architecture

经典蓝牙支持在 AW30N SDK 中按"控制器 — 主机协议栈 — Profile — 应用"四层组织,BLE 与经典蓝牙共享控制器与射频,但各自拥有独立的主机协议栈实例配置:

flowchart TD
    subgraph sg_App["应用层 (app)"]
        APP["app / app_config.c<br/>SPP_USER_LOG 日志开关"]
        UPDATE["testbox_update.c<br/>testbox_bt_classic_update_* 回调"]
    end

    subgraph sg_Profile["Profile 层 (bt_common)"]
        SPPLE["spp_and_le<br/>SPP + LE 双模示例"]
        HID["hid<br/>EDR HID 示例"]
        SPP["USER_SUPPORT_PROFILE_SPP<br/>SPP 串口协议"]
        EDRHOST["EDR_EMITTER_EN<br/>EDR 主机 (inquiry + page)"]
    end

    subgraph sg_Host["主机协议栈层 (btstack)"]
        BTSTACK["lib_btstack_config.c<br/>GAP/SDP/SPP/HID 服务记录"]
        CTRLER["lib_btctrler_config.c<br/>控制器配置"]
    end

    subgraph sg_HW["硬件层"]
        RF["2.4G 射频<br/>BR/EDR + BLE 双模"]
    end

    APP --> SPPLE
    APP --> HID
    SPPLE --> SPP
    SPPLE --> EDRHOST
    SPPLE --> BTSTACK
    HID --> BTSTACK
    BTSTACK --> CTRLER
    CTRLER --> RF
    UPDATE --> APP

各层职责说明:

  • 应用层:app 目录承载具体产品逻辑,例如通过 app_config.c 中的 app_info_debug_enable 位图(SPP_USER_LOG = BIT(3))打开 SPP 用户日志;OTA 升级代码(testbox_update.c)中提供了 testbox_bt_classic_update_* 系列回调,用于在经典蓝牙连接状态下执行升级前的私有参数填充、跳转前处理和状态通知。
  • Profile 层:bt_common 下按应用形态拆分工程:spp_and_le(SPP 与 LE 组合场景)、hid(经典蓝牙 HID 键鼠场景)。bt_profile_cfg.h 统一决定是否使能 SPP 服务记录(SDP)。
  • 主机协议栈层:每个 profile 目录下都有一份独立的 lib_btstack_config.c 与 lib_btctrler_config.c,用于裁剪协议栈特性(如经典蓝牙的 SDP 服务记录、SPP 通道、HID 报告等)与控制器参数(如经典蓝牙的 EDR 速率、sniff 模式)。
  • 硬件层:射频同时承载 BR/EDR 与 BLE,双模同地址/同名字由 DOUBLE_BT_SAME_NAME、DOUBLE_BT_SAME_MAC 宏控制。

设计意图:将协议栈配置与 Profile 代码放在同一工程目录下,是为了让每个示例工程可独立编译、独立裁剪,互不干扰 —— 这也是 spple_app_config.h 中 CONFIG_APP_* 只能选 1 个("apps example 选择,只能选1个")的原因。

经典蓝牙使能机制(bt_profile_cfg.h)

经典蓝牙能力的总开关位于 bt_profile_cfg.h。其核心逻辑是:根据应用宏自动推导 BT_FOR_APP_EN,再由 BT_FOR_APP_EN 决定 SPP 是否使能。

#if (TRANS_DATA_EN || RCSP_BTMATE_EN || RCSP_ADV_EN || SMART_BOX_EN || ANCS_CLIENT_EN || LL_SYNC_EN || TUYA_DEMO_EN)
#ifndef BT_FOR_APP_EN
#define    BT_FOR_APP_EN             1
#endif
#else
#ifndef BT_FOR_APP_EN
#define    BT_FOR_APP_EN             0
#endif
#ifndef AI_APP_PROTOCOL
#define    AI_APP_PROTOCOL             0
#endif
#endif


///---sdp service record profile- 用户选择支持协议--///
#if (BT_FOR_APP_EN || APP_ONLINE_DEBUG || AI_APP_PROTOCOL)
#if (LL_SYNC_EN || TUYA_DEMO_EN)
#undef USER_SUPPORT_PROFILE_SPP
#define USER_SUPPORT_PROFILE_SPP    0
#else
#undef USER_SUPPORT_PROFILE_SPP
#define USER_SUPPORT_PROFILE_SPP    1
#endif
#endif

Source: bt_profile_cfg.h

逐段解读:

  1. 只要打开了 TRANS_DATA_EN(数据传输)、RCSP_BTMATE_EN(RCSP App)、RCSP_ADV_EN、SMART_BOX_EN、ANCS_CLIENT_EN、LL_SYNC_EN(腾讯连连)或 TUYA_DEMO_EN(涂鸦)中的任何一个,就认为该工程"需要蓝牙与 App 交互",强制置 BT_FOR_APP_EN = 1。这些宏来自上层 app_config.c 的应用选择。
  2. 若上述宏全为 0,则 BT_FOR_APP_EN = 0 且同时关闭 AI_APP_PROTOCOL,此时整棵蓝牙协议栈都不会被链接 —— 这是纯非蓝牙应用的裁剪路径。
  3. USER_SUPPORT_PROFILE_SPP 是 SDP 服务记录层面的 SPP 开关:在需要蓝牙与 App 交互(BT_FOR_APP_EN || APP_ONLINE_DEBUG || AI_APP_PROTOCOL)的前提下,若使用 LL_SYNC_EN 或 TUYA_DEMO_EN(这两类场景走私有协议而非标准 SPP),则关闭 SPP 服务记录;其余场景默认开启 SPP。

设计意图:SPP 是经典蓝牙设备被手机/App 连接的最通用"数据管道",但 LL_SYNC(腾讯连连)与涂鸦使用各自的私有协议,注册标准 SPP 的 SDP 记录只会白白占用 Flash,因此这两类工程被显式排除。

BLE Demo 选择与经典蓝牙的关系

同一个文件中通过 TCFG_BLE_DEMO_SELECT 选择 BLE 侧运行的 demo(bt_profile_cfg.h):

#define DEF_BLE_DEMO_NULL                 0 //ble 没有使能
#define DEF_BLE_DEMO_ADV                  1 //only adv,can't connect
#define DEF_BLE_DEMO_TRANS_DATA           2 //
#define DEF_BLE_DEMO_RCSP_DEMO            4 //
#define DEF_BLE_DEMO_ADV_RCSP             5
#define DEF_BLE_DEMO_CLIENT               7 //
#define DEF_BLE_ANCS_ADV                  9
#define DEF_BLE_DEMO_MULTI                11 //
#define DEF_BLE_DEMO_LL_SYNC              13 //

Source: bt_profile_cfg.h

TCFG_BLE_DEMO_SELECT 由 TCFG_USER_BLE_ENABLE 与各应用宏按优先级推导(RCSP > TRANS_DATA > LL_SYNC > TUYA > ...),这与经典蓝牙的使能互相独立:经典蓝牙与 BLE demo 可以同时打开,形成双模(例如 TRANS_DATA_EN 同时打开 SPP 与 DEF_BLE_DEMO_TRANS_DATA)。

SPP + LE 双模应用配置(spple_app_config.h)

经典蓝牙最典型的载体是 spp_and_le 工程(SPP + LE 双模),其应用选择入口在 spple_app_config.h:

#if (TRANS_DATA_SPPLE_EN)

#define TCFG_MEDIA_LIB_USE_MALLOC		    1
//apps example 选择,只能选1个,要配置对应的board_config.h
#define CONFIG_APP_SPP_LE                 0 //SPP + LE or LE's client
#define CONFIG_APP_MULTI                  0 //蓝牙LE多连 + spp
#define CONFIG_APP_DONGLE                 1 //usb + 蓝牙(ble 主机),PC hid设备
#define CONFIG_APP_CENTRAL                0 //ble client,中心设备
#define CONFIG_APP_LL_SYNC                0 //腾讯连连
#define CONFIG_APP_BEACON                 0 //蓝牙BLE ibeacon
#define CONFIG_APP_NONCONN_24G            0 //2.4G 非连接收发, 不支持rcsp,需要关闭
#define CONFIG_APP_TUYA                   0 //涂鸦协议
#define CONFIG_APP_AT_COM                 0 //AT com HEX格式命令
#define CONFIG_APP_AT_CHAR_COM            0 //AT com 字符串格式命令
#define CONFIG_APP_IDLE                   0 //空闲任务
#define CONFIG_APP_CONN_24G               0 //基于BLE的2.4g,板级只需要开BLE
#define CONFIG_APP_HILINK                 0 //华为协议
#define CONFIG_APP_ELECTROCAR             0 //电车项目,注意将板级处ADKEY以及别的IO占用失能, 关闭低功耗:TCFG_LOWPOWER_LOWPOWER_SEL设置为0
#define CONFIG_APP_REDUCE_RAM             0 //省ram的应用, 不支持rcsp,需要关闭

Source: spple_app_config.h

要点:

  • 整个文件被 TRANS_DATA_SPPLE_EN 包裹,只有打开该宏才编译双模示例代码;
  • 应用示例互斥(只能选 1 个),且需要与 board_config.h 的板级配置对应;
  • CONFIG_APP_SPP_LE(SPP + LE)、CONFIG_APP_MULTI(LE 多连 + SPP)是经典蓝牙 SPP 的典型应用;CONFIG_APP_DONGLE 则组合了 USB、BLE 主机与可选的 EDR 主机能力。

双模共存的命名/地址策略

在 CONFIG_APP_SPP_LE 分支中(spple_app_config.h),SDK 提供了经典蓝牙与 BLE 的共存策略开关:

#if CONFIG_APP_SPP_LE
//配置双模同名字,同地址
#define DOUBLE_BT_SAME_NAME                0 //同名字
#define DOUBLE_BT_SAME_MAC                 0 //同地址
#define CONFIG_APP_SPP_LE_TO_IDLE          0 //SPP_AND_LE To IDLE Use
#define CONFIG_BLE_HIGH_SPEED              0 //BLE提速模式: 使能DLE+2M, payload要匹配pdu的包长

Source: spple_app_config.h

  • DOUBLE_BT_SAME_NAME = 1 时经典蓝牙与 BLE 广播使用同一个设备名,手机端看到的是一个设备而非两个;
  • DOUBLE_BT_SAME_MAC = 1 时两者共享同一 MAC 地址,避免因地址不同导致手机配对记录混乱;
  • 这两个开关默认关闭,原因是部分手机对"同名同址的双模设备"处理存在兼容性问题,产品可根据目标手机兼容性测试结果打开。

EDR 主机模式(经典蓝牙 Emitter)

CONFIG_APP_DONGLE 分支中定义了经典蓝牙主机(EDR Emitter)能力(spple_app_config.h):

#elif CONFIG_APP_DONGLE
/*默认做搜索设备匹配名字再发起连接 inquery + page*/
#define EDR_EMITTER_EN                     0 //蓝牙(edr主机)

#if EDR_EMITTER_EN
/*不做搜索匹配 + 连接,只开放可连接,等待对方连接*/
#define EDR_EMITTER_PAGESCAN_ONLY          0 /**/
#endif

#define CONFIG_BT_GATT_COMMON_ENABLE       1
#define CONFIG_BT_SM_SUPPORT_ENABLE        1 //配置是否支持加密
#define CONFIG_BT_GATT_CLIENT_NUM          1 //设置主机个数1~2,(dongle可连接蓝牙BLE设备的个数,=2时会多注册1个usb设备)
#define CONFIG_BT_COMPOSITE_EQUIPMENT      0
#define CONFIG_BT_GATT_SERVER_NUM          0 //
#define CONFIG_BT_GATT_CONNECTION_NUM      (CONFIG_BT_GATT_SERVER_NUM + CONFIG_BT_GATT_CLIENT_NUM) //
#define CONFIG_BLE_CONNECT_SLOT            0 //BLE高回报率设置, 支持私有协议
#define CONFIG_BLE_HIGH_SPEED              1 //BLE提速模式: 使能DLE+2M, payload要匹配pdu的包长

Source: spple_app_config.h

关键语义:

  • EDR_EMITTER_EN = 1 表示 AW30N 作为经典蓝牙主机,默认流程是"搜索设备(inquiry)→ 匹配名字 → 发起连接(page)";
  • EDR_EMITTER_PAGESCAN_ONLY = 1 时跳过搜索与主动连接,设备只开放可连接/可发现(page scan),等待对端(从机)来连 —— 典型于与手机 App 配对前由手机发起连接;
  • 该分支同时把 CONFIG_BT_GATT_CLIENT_NUM 设为 1,即 Dongle 同时可作为 BLE 主机连接 1~2 个 BLE 外设,形成"经典蓝牙主机 + BLE 主机"的复合桥接形态;
  • CONFIG_BLE_HIGH_SPEED = 1 打开 BLE 提速模式(DLE + 2M),保证 BLE 侧吞吐不被经典蓝牙活动拖累。

设计意图:Dongle(USB 蓝牙适配器)场景下,经典蓝牙用于连接经典外设(如旧式鼠标、串口透传设备),BLE 用于连接新式低功耗外设,USB 把两者数据回传 PC。EDR_EMITTER_EN 与 EDR_EMITTER_PAGESCAN_ONLY 分别对应"主动扫描连接"与"被动等待连接"两种产品形态,避免把两种模式耦合在同一个运行路径里。

EDR HID 设备协议

经典蓝牙 HID(键鼠/遥控器)位于 sdk/apps/app/bsp/common/bt_common/hid/ 目录:

  • hid/include/edr_hid_user.h —— EDR HID 用户层接口(报告发送、连接管理回调);
  • hid/include/standard_hid.h —— 标准 HID 描述符与报告格式定义;
  • hid/include/app_comm_bt.h —— HID 工程下蓝牙公共接口;
  • hid/include/lib_profile_cfg.h —— HID 工程的 profile 裁剪(HOGP/EDR HID 选择);
  • hid/config/lib_btstack_config.c 与 hid/config/lib_btctrler_config.c —— HID 工程的主机协议栈与控制器配置。

HID 工程与 spp_and_le 工程互斥编译(均由 app_config.c 的应用宏选择,如 CONFIG_HID_CASE_ENABLE / CONFIG_SPP_AND_LE_CASE_ENABLE,见升级代码中的条件编译)。EDR HID 与 BLE HOGP 的差异在于传输层:EDR HID 走经典蓝牙的 L2CAP PSM 0x11(HID Control)与 0x13(HID Interrupt),BLE HOGP 走 GATT 服务,SDK 通过 lib_profile_cfg.h 分别裁剪。

经典蓝牙日志与调试

经典蓝牙 SPP 的用户态调试日志通过 app_config.c 中的日志位图控制(app_config.c):

#define SPP_USER_LOG		3	// 用于打印spp_user.c中的打印,app使用spp交互时需要用到
#define RCSP_PROTOCOL_LOG	2	// 用于JL_rcsp_protocol.c中的调试打印
int app_info_debug_enable = 0 \
                            /*	| BIT(SPP_USER_LOG) \ */
                            ;

Source: app_config.c

  • SPP_USER_LOG = 3 是对应 spp_user.c 中打印的位号(BIT(3));
  • 默认 app_info_debug_enable = 0,所有蓝牙调试打印关闭;产品调试期把 BIT(SPP_USER_LOG) 加入即可观察 SPP 收发的用户态日志,量产时保持关闭以省功耗与吞吐。

Core Flow:经典蓝牙连接流程

经典蓝牙的典型连接流程分为**从机模式(等待连接)与主机模式(主动连接)**两种。下图以 EDR_EMITTER_EN = 1(主机)且 EDR_EMITTER_PAGESCAN_ONLY = 0 的默认流程为例,展示从搜索到数据传输的完整链路:

sequenceDiagram
    participant APP as 应用层 (app)
    participant BTSTACK as btstack 主机协议栈
    participant CTRLER as btctrler 控制器
    participant PEER as 对端经典蓝牙设备

    APP->>BTSTACK: 初始化双模 (spp_and_le / hid 工程)
    BTSTACK->>CTRLER: 下发控制器配置 (lib_btctrler_config.c)
    CTRLER-->>BTSTACK: 控制器就绪

    APP->>BTSTACK: EDR Emitter 启动 (inquiry)
    BTSTACK->>CTRLER: 发起 Inquiry 扫描
    CTRLER-->>BTSTACK: 发现设备列表 (含名字/地址)
    BTSTACK->>BTSTACK: 按名字匹配目标设备
    BTSTACK->>CTRLER: 发起 Page 连接
    CTRLER-->>BTSTACK: 基带连接建立
    BTSTACK->>PEER: SDP 查询 SPP/HID 服务记录
    PEER-->>BTSTACK: SDP 响应 (USER_SUPPORT_PROFILE_SPP)
    BTSTACK->>PEER: L2CAP 通道建立 (SPP: RFCOMM / HID: PSM 0x11/0x13)
    PEER-->>BTSTACK: 连接成功回调
    BTSTACK-->>APP: 上报连接事件
    APP->>APP: testbox_bt_classic_update_* 回调挂接 (OTA 等)
    APP<->>PEER: SPP 数据收发 / HID 报告上报

步骤说明:

  1. 初始化:应用层(spp_and_le 或 hid 工程)拉起 btstack 主机协议栈,加载各自的 lib_btstack_config.c 与 lib_btctrler_config.c 配置(SDP 服务记录、控制器参数、sniff 等);
  2. Inquiry:主机模式先扫描周围经典蓝牙设备,收集地址与名字;
  3. 名字匹配:在协议栈或应用层按预设名字过滤目标(spple_app_config.h 注释"默认做搜索设备匹配名字再发起连接");
  4. Page:对匹配到的目标发起基带寻呼,建立 ACL 链路;
  5. SDP 服务发现:查询对端是否支持 SPP(或 HID)服务 —— 本端 SDP 服务记录是否注册由 USER_SUPPORT_PROFILE_SPP 决定;
  6. L2CAP/RFCOMM:SPP 走 RFCOMM 串口仿真通道,EDR HID 走 L2CAP PSM 0x11/0x13;
  7. 应用回调:连接事件上报应用层,应用可挂接 OTA 升级等业务(如 testbox_bt_classic_update_state_cbk);
  8. 数据传输:SPP 透传用户数据,HID 上报键鼠报告。

经典蓝牙 OTA 升级接入点

经典蓝牙连接状态下的 OTA 升级由 testbox_update.c 提供钩子(升级流程属于"升级"页面范畴,这里只说明经典蓝牙相关的接入点):

#if defined(CONFIG_SPP_AND_LE_CASE_ENABLE) || defined(CONFIG_HID_CASE_ENABLE)
#include "lib_profile_cfg.h"
...
static void testbox_bt_classic_update_private_param_fill(UPDATA_PARM *p)
static void testbox_bt_classic_update_before_jump_handle(int type)
static void testbox_bt_classic_update_state_cbk(int type, u32 state, void *priv)

Source: testbox_update.c

三个回调分别承担:升级前填充私有参数(如当前经典蓝牙连接信息)、跳转前处理(断开经典蓝牙链路、保存上下文)、升级状态通知(进度/结果回调给应用)。它们只在 CONFIG_SPP_AND_LE_CASE_ENABLE 或 CONFIG_HID_CASE_ENABLE(即双模/经典蓝牙工程)下编译,说明经典蓝牙产品的升级通道需要额外处理经典链路的断开与恢复 —— 这是与纯 BLE 产品升级的关键差异。

Usage Examples

示例 1:开启经典蓝牙 SPP(双模透传工程)

在 app_config.c 中使能数据传输类应用宏(如 TRANS_DATA_EN),bt_profile_cfg.h 会自动推导 BT_FOR_APP_EN = 1 并默认打开 USER_SUPPORT_PROFILE_SPP = 1,从而在 SDP 中注册 SPP 服务记录:

#if (TRANS_DATA_EN || RCSP_BTMATE_EN || RCSP_ADV_EN || SMART_BOX_EN || ANCS_CLIENT_EN || LL_SYNC_EN || TUYA_DEMO_EN)
#ifndef BT_FOR_APP_EN
#define    BT_FOR_APP_EN             1
#endif
#else
#ifndef BT_FOR_APP_EN
#define    BT_FOR_APP_EN             0
#endif
#ifndef AI_APP_PROTOCOL
#define    AI_APP_PROTOCOL             0
#endif
#endif

Source: bt_profile_cfg.h

效果:手机可通过标准蓝牙串口(SPP)连接设备进行透传,BLE 侧同时保持 GATT 服务;两个链路互不干扰。

示例 2:配置经典蓝牙主机模式(EDR Emitter)

在 spple_app_config.h 中把 CONFIG_APP_DONGLE 置 1,再打开 EDR_EMITTER_EN:

#elif CONFIG_APP_DONGLE
/*默认做搜索设备匹配名字再发起连接 inquery + page*/
#define EDR_EMITTER_EN                     0 //蓝牙(edr主机)

#if EDR_EMITTER_EN
/*不做搜索匹配 + 连接,只开放可连接,等待对方连接*/
#define EDR_EMITTER_PAGESCAN_ONLY          0 /**/
#endif

Source: spple_app_config.h

效果:设备作为经典蓝牙主机执行 inquiry + page 主动连接;如需"等待对端连接"形态,将 EDR_EMITTER_PAGESCAN_ONLY 置 1。

示例 3:双模同名字/同地址

在 SPP+LE 工程中开启 DOUBLE_BT_SAME_NAME / DOUBLE_BT_SAME_MAC,让手机只看到一个设备:

#if CONFIG_APP_SPP_LE
//配置双模同名字,同地址
#define DOUBLE_BT_SAME_NAME                0 //同名字
#define DOUBLE_BT_SAME_MAC                 0 //同地址
#define CONFIG_APP_SPP_LE_TO_IDLE          0 //SPP_AND_LE To IDLE Use
#define CONFIG_BLE_HIGH_SPEED              0 //BLE提速模式: 使能DLE+2M, payload要匹配pdu的包长

Source: spple_app_config.h

示例 4:打开 SPP 用户日志调试

调试 SPP 透传时,将 BIT(SPP_USER_LOG) 加入 app_info_debug_enable:

#define SPP_USER_LOG		3	// 用于打印spp_user.c中的打印,app使用spp交互时需要用到
#define RCSP_PROTOCOL_LOG	2	// 用于JL_rcsp_protocol.c中的调试打印
int app_info_debug_enable = 0 \
                            /*	| BIT(SPP_USER_LOG) \ */
                            ;

Source: app_config.c

Configuration Options

以下为经典蓝牙支持相关的关键配置宏(均在编译期生效):

配置宏类型默认值说明
BT_FOR_APP_EN宏自动推导蓝牙与 App 交互总开关;任一应用宏打开时自动置 1
USER_SUPPORT_PROFILE_SPP宏1是否在 SDP 中注册 SPP 服务记录;LL_SYNC_EN/TUYA_DEMO_EN 时强制为 0
TRANS_DATA_EN宏由工程决定数据传输应用宏,同时打开 SPP 与 DEF_BLE_DEMO_TRANS_DATA
AI_APP_PROTOCOL宏0AI 语音 App 协议开关,可独立打开经典蓝牙
APP_ONLINE_DEBUG宏0在线调试开关,可独立触发 SPP 使能
CONFIG_APP_SPP_LE宏0SPP + LE 双模示例(互斥选择)
CONFIG_APP_MULTI宏0LE 多连 + SPP 示例(互斥选择)
CONFIG_APP_DONGLE宏0USB + 蓝牙 Dongle 示例(互斥选择)
EDR_EMITTER_EN宏0经典蓝牙主机模式使能(inquiry + page)
EDR_EMITTER_PAGESCAN_ONLY宏0仅开放可连接,等待对端连接
DOUBLE_BT_SAME_NAME宏0双模使用同一设备名
DOUBLE_BT_SAME_MAC宏0双模使用同一 MAC 地址
SNIFF_MODE_RESET_ANCHOR宏0EDR sniff 模式锚点重置配置
CONFIG_BLE_HIGH_SPEED宏0/1BLE 提速(DLE + 2M),Dongle 分支默认 1
SPP_USER_LOG位号BIT(3)spp_user.c 用户日志位,配合 app_info_debug_enable

API Reference

经典蓝牙相关的对外接口主要分布在三个层面:

Profile 使能(编译期 API)

bt_profile_cfg.h 提供的宏即"接口":BT_FOR_APP_EN、USER_SUPPORT_PROFILE_SPP 控制 SDP 服务记录注册;spple_app_config.h 的 CONFIG_APP_* 系列选择具体工程形态。这些宏在编译期决定哪些协议栈代码被链接,运行期不可更改 —— 因此产品形态必须在构建前确定。

OTA 升级回调(testbox_update.c)

函数作用触发时机
testbox_bt_classic_update_private_param_fill(UPDATA_PARM *p)填充升级私有参数(如经典链路信息)升级启动前
testbox_bt_classic_update_before_jump_handle(int type)跳转升级前的经典蓝牙链路处理跳转升级程序前
testbox_bt_classic_update_state_cbk(int type, u32 state, void *priv)升级状态通知回调升级过程中/结束

Source: testbox_update.c

Profile 用户接口(头文件层)

  • spp_and_le 工程:spp_user.c 提供 SPP 数据收发/连接回调(日志位 SPP_USER_LOG 指向该文件);
  • hid 工程:edr_hid_user.h 提供 EDR HID 连接管理与报告发送接口,standard_hid.h 定义标准 HID 报告格式;
  • 双模公共头文件:bt_common/bt_ble.h 统一定义 BLE/EDR 共用的数据类型与枚举,app_comm_bt.h(HID 工程)提供蓝牙公共 API。

注:上述 Profile 层接口的完整函数签名位于对应 spp_user.c / edr_hid_user.c 实现中,本文档未逐行读取(受源材料预算限制),实际使用时请以源码为准。

Failure Modes, Edge Cases & Concurrency

编译期冲突与互斥

  • 应用示例互斥:CONFIG_APP_SPP_LE、CONFIG_APP_MULTI、CONFIG_APP_DONGLE 等只能选 1 个("apps example 选择,只能选1个")。若同时置多个为 1,编译期会产生宏冲突或链接重复定义 —— 这是经典蓝牙工程最常见的配置错误。
  • SPP 与私有协议互斥:LL_SYNC_EN / TUYA_DEMO_EN 强制 USER_SUPPORT_PROFILE_SPP = 0。若强行打开 SPP,两类协议都会尝试占用 RFCOMM/串口通道,运行期会互相抢占连接,因此 SDK 在宏层面直接禁止。

双模并发与射频共享

  • AW30N 的射频在 BR/EDR 与 BLE 之间时分复用。经典蓝牙处于 inquiry/page/sniff 状态时,BLE 的连接间隔、广播间隔可能被拉长,导致 BLE 侧吞吐下降。Dongle 分支默认 CONFIG_BLE_HIGH_SPEED = 1(DLE + 2M)即是对此的补偿。
  • CONFIG_BT_GATT_CONNECTION_NUM 必须等于 CONFIG_BT_GATT_SERVER_NUM + CONFIG_BT_GATT_CLIENT_NUM;Dongle 分支主机数为 1~2,超过后需要额外注册 USB 设备(注释明示 "=2时会多注册1个usb设备")。

连接建立失败场景

  • 主机模式(EDR_EMITTER_EN=1)下 inquiry 超时或按名字匹配不到目标:SDK 不会自动重试无限次,需要应用层依据回调状态决定重扫间隔与次数;
  • EDR_EMITTER_PAGESCAN_ONLY=1 时设备不主动连接,若对端从不发起 page,设备将一直处于等待态 —— 产品需设计超时退出机制;
  • 经典蓝牙链路在 OTA 升级跳转前必须显式断开(testbox_bt_classic_update_before_jump_handle),否则升级程序无法重新初始化控制器。

地址/名字冲突

  • DOUBLE_BT_SAME_MAC 打开后,经典蓝牙与 BLE 共享地址,部分手机在双模绑定/回连时可能出现地址解析异常;关闭(默认)则手机看到两个设备。该参数需依据目标手机兼容性实测结果调整,属于已知的产品权衡点。

Performance & Operational Considerations

  • 资源裁剪:经典蓝牙协议栈(SDP、RFCOMM、HID 等)占用可观 ROM/RAM。SDK 提供 256KB 裁剪补丁包(补丁包/AW30N_v1.2.0_SDK裁剪到256KB以内的补丁包_20240815/),其中 testbox_update.c 的经典蓝牙升级回调同样被保留,说明裁剪后经典蓝牙 + OTA 的最小形态仍然成立。
  • 日志开销:默认 app_info_debug_enable = 0,所有蓝牙日志关闭;仅在调试期打开 BIT(SPP_USER_LOG)。量产保持关闭可降低 UART 打印占用与功耗。
  • 低功耗:spple_app_config.h 中 SNIFF_MODE_RESET_ANCHOR 控制 EDR sniff 模式锚点行为;CONFIG_APP_ELECTROCAR 等分支注释提示需将 TCFG_LOWPOWER_LOWPOWER_SEL 置 0 关闭低功耗才能正常使用外设 —— 经典蓝牙连接态下的低功耗配置需与板级电源策略联动。
  • BLE 高回报率:CONFIG_BLE_CONNECT_SLOT(BLE 高回报率私有协议)与经典蓝牙共存时需实测互扰;Dongle 分支默认关闭以优先保证经典蓝牙主机链路稳定。

Extension Points

  1. 新增经典蓝牙 Profile 工程:参照 spp_and_le 与 hid 的目录结构(include/ + modules/bt/ + config/),在 bt_common 下新建工程目录,提供独立的 lib_btstack_config.c / lib_btctrler_config.c,并在 app_config.c 增加互斥的应用宏。
  2. 自定义 SPP 应用:修改/替换 spp_user.c 中的数据收发与连接回调(日志位 SPP_USER_LOG 已预留),即可接入自定义透传协议(如 AT 命令,见 CONFIG_APP_AT_COM / CONFIG_APP_AT_CHAR_COM)。
  3. EDR HID 定制:通过 standard_hid.h 的 HID 描述符定义自定义报告格式,通过 edr_hid_user.h 挂接报告发送与连接事件。
  4. OTA 流程定制:实现/替换 testbox_bt_classic_update_private_param_fill、testbox_bt_classic_update_before_jump_handle、testbox_bt_classic_update_state_cbk 三个回调,适配不同升级协议(私有参数格式由产品定义)。

Tests

SDK 中经典蓝牙相关的测试与验证手段主要体现为:

  • 示例工程自测:spp_and_le(SPP_LE / MULTI / DONGLE)与 hid 各示例即最小可测固件,配合 board_config.h 板级配置可直接烧录验证经典蓝牙连接与透传;
  • OTA 升级路径测试:testbox_update.c 中的经典蓝牙升级回调链是升级链路的核心测试点,覆盖"连接态升级 → 断开经典链路 → 跳转 → 状态回调"全流程;
  • 双模共存测试:需验证 DOUBLE_BT_SAME_NAME/MAC 开关下手机端的发现、配对、回连行为,以及经典蓝牙活动对 BLE 连接间隔的影响。

说明:受源材料读取预算限制,本页未逐文件核对 spp_user.c、edr_hid_user.c 的测试用例细节;涉及具体用例时请以对应工程目录下的源码为准。

Related Links

  • bt_profile_cfg.h — 经典蓝牙 SPP 使能与 BLE demo 选择
  • spple_app_config.h — SPP+LE / MULTI / DONGLE 双模应用与 EDR 主机配置
  • bt_ble.h — 蓝牙公共头文件(BLE/EDR 共用定义)
  • app_config.c — 应用宏与蓝牙日志开关
  • testbox_update.c — 经典蓝牙 OTA 升级回调
  • 相关页面:BLE 协议栈(GATT/SM)、SPP+LE 示例工程、HID 示例工程、OTA 升级
Prev
BLE 应用示例:遥控器 / Dongle / 对讲机