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

    • SDK 总览
    • 支持芯片与蓝牙认证
    • 工程结构导航
  • 开发环境与构建

    • 环境搭建与工具链安装
    • 编译指南与工程选择
    • 烧录与生产工具
  • BLE 透传/数传应用

    • 透传应用框架与处理模块
    • 透传与数传示例
    • 多连接与自定义服务示例
    • FindMy 与查找网络示例
  • HID 人机交互应用

    • 键盘与按键设备示例
    • 鼠标设备示例
    • 遥控器示例
    • HID 蓝牙应用模块
  • 公共 BSP 模块

    • 按键、编码器与红外输入
    • 传感器驱动
    • LED 与显示控制
    • 串口与 USB 通信
    • 存储、参数与时钟
    • 电源与温度管理
    • 消息、内存与系统配置
    • OTA 升级框架
  • 蓝牙协议栈与库

    • BLE 控制器与协议栈适配
    • 经典蓝牙 BR/EDR 支持
    • 第三方蓝牙协议
    • 设备管理框架
    • DUT 测试与射频认证
  • 构建系统与开发工具

    • Makefile 构建系统
    • 固件后处理与配置工具
    • 辅助脚本与库合并
  • 文档与硬件资料

    • AT 命令参考
    • 硬件参考资料
    • SDK 文档与在线资源

透传应用框架与处理模块

BLE 透传(Transparent Transmission)是杰理 AW33N BLE SDK 中最基础的无线数据通道能力:设备端通过通用串口(UART)接收外部数据并原样转发到 BLE GATT 通道,同时把手机 App 通过 GATT 下发的数据回传给串口,实现「串口 ⇄ BLE」双向透传。本文档深入分析 apps/demo/transfer 工程中透传应用框架(app_trans.c)与 BLE 协议处理模块(ble_trans.c)的完整实现。

Purpose and Scope

本页面覆盖以下内容:

  • 透传应用框架(app_trans.c):基于杰理 application 状态机的应用生命周期管理、BLE 协议栈启动/退出流程、消息循环与软关机处理;
  • BLE 透传协议处理模块(ble_trans.c):GATT Server 配置、安全管理(SM)、广播数据构造、UART→BLE 与 BLE→UART 双向数据通路、连接参数更新与回连 CCC 恢复;
  • 透传数据通道:UART 与 GATT 特征(ATT_CHARACTERISTIC_ae02_01)之间的数据搬运机制;
  • 工程级集成:apps/demo/transfer 工程的目录结构、配置开关(CONFIG_APP_LE_TRANS)与周边模块(AT 指令、非连接广播等)的关系。

有意不覆盖以下内容(由同级页面承担):

  • AT 指令交互框架(examples/at_char_com/,如 at_char_cmds.c、ble_at_char_server.c);
  • 非连接广播透传(examples/nonconn_trans/app_nonconn_trans.c);
  • USB Dongle 与远端升级透传(examples/dongle/,其 ota_dg_central.h 注释中 channel_3~9 为远端升级透传通道);
  • 底层 GATT/ATT 协议栈实现(btstack 内部,本页面仅以 API 调用视角引用)。

Overview

透传应用是理解杰理 BLE SDK 应用层架构的最佳入口:它以最小的业务逻辑串联起了「应用状态机 → BLE 协议栈 → GATT Profile → 外设驱动」整条链路。其设计意图可归纳为三点:

  1. 数据面与协议面分离:app_trans.c 只负责应用生命周期与消息循环,不关心 GATT 细节;ble_trans.c 只负责 BLE 协议处理(ATT 回调、CCC、连接参数),不关心应用策略。两者通过 ble_trans.h 暴露的接口和 sys_event 事件解耦。
  2. 以 UART 为数据源:通过 common_uart_init() 配置通用串口,串口 RX 中断里把数据直接塞入 BLE 发送通道(trans_uart_rx_to_ble),实现"有线串口即无线串口"的体验。
  3. 一次初始化、全链路回调驱动:GATT 的读写、事件全部由 trans_att_read_callback / trans_att_write_callback / trans_event_packet_handler 三个回调驱动,应用层只需注册配置结构体即可运行。

透传应用典型使用场景包括:手机 App 与 MCU 之间的调试日志透传、固件配置下发、传感器数据上送,以及通过 USB Dongle 转发的 PC 工具通信(见 ota_dg_central.h 中 "channel_2: pc->usb透传" 的通道规划)。

Architecture

透传框架的整体架构分为三层:应用层(状态机与消息循环)、BLE 协议层(GATT/ATT/SM/广播)与数据源层(UART 驱动与 LED 指示)。

flowchart TD
    subgraph sg_AppLayer["应用层 (app_trans.c)"]
        SM["le_trans_state_machine<br/>application 状态机"]
        START["le_trans_app_start<br/>时钟/蓝牙/串口初始化"]
        LOOP["le_trans_run_loop<br/>get_msg 消息循环"]
        PWROFF["le_trans_set_soft_poweroff<br/>软关机处理"]
    end

    subgraph sg_BleLayer["BLE 协议层 (ble_trans.c)"]
        CFG["trans_gatt_control_block<br/>GATT 控制块"]
        SMC["trans_sm_init_config<br/>安全管理配置"]
        ADV["广播/扫描应答数据<br/>trans_adv_data"]
        READ["trans_att_read_callback"]
        WRITE["trans_att_write_callback"]
        EVENT["trans_event_packet_handler"]
        U2B["trans_uart_rx_to_ble<br/>UART→BLE"]
    end

    subgraph sg_DataSrc["数据源与驱动层"]
        UART["common_uart_init<br/>通用串口 (TCFG_COMMON_UART_*)"]
        LED["led_operate<br/>LED 指示"]
        BTSTACK["btstack_init / btstack_ble_*<br/>协议栈接口"]
    end

    SM -->|"ACTION_LE_TRANS_MAIN"| START
    START --> LOOP
    START --> UART
    START --> LED
    START -->|"le_trans_bt_start"| BTSTACK
    BTSTACK -->|"ble_init_cfg_t<br/>comm_ble_profile_init"| CFG
    CFG --> READ
    CFG --> WRITE
    CFG --> EVENT
    CFG --> SMC
    EVENT -->|"SYS_BT_EVENT 推送"| LOOP
    UART -->|"串口 RX 数据"| U2B
    U2B -->|"ble_comm_att_send_data<br/>ATT_CHARACTERISTIC_ae02_01"| WRITE
    PWROFF -->|"btstack_ble_exit"| BTSTACK

架构解读:

  • 应用状态机驱动启动:le_trans_state_machine 是杰理 application 框架的回调,收到 ACTION_LE_TRANS_MAIN 意图后调用 le_trans_app_start() 完成时钟、蓝牙协议栈与串口的初始化,随后进入 le_trans_run_loop() 消息循环(app_trans.c#L217-L231)。
  • 配置结构体是协议层的唯一入口:trans_gatt_control_block(gatt_ctrl_t)注册了 server/client/sm 三组配置,ble_trans.c 通过 comm_ble_profile_init 将其挂载到协议栈(ble_trans.c#L84-L116)。
  • 数据流单向清晰:串口 RX → trans_uart_rx_to_ble → GATT Notify 到手机;手机写入特征 → trans_att_write_callback → 串口 TX。两条通路在 ble_trans.c 内部汇合,互不干扰。
  • 退出与省电:le_trans_set_soft_poweroff 遵循"先断链、再关机"的顺序,依据 TCFG_LOWPOWER_PATTERN 选择等待断链或直接软关机(app_trans.c#L82-L103)。

应用框架层详解(app_trans.c)

app_trans.c 是整个透传应用的"壳",全部代码由 CONFIG_APP_LE_TRANS 宏包裹,未开启该宏时整个文件不参与编译(app_trans.c#L45-L53)。它负责四件事:BLE 初始化配置描述、协议栈启停、消息循环、电源管理。

BLE 初始化配置(ble_init_cfg_t)

框架使用一个全局 ble_init_cfg_t 结构体描述 BLE 模块的初始化行为,这是杰理 SDK 应用层接入协议栈的标准方式:

static const ble_init_cfg_t le_trans_data_config = {
    .same_address = 0,
    .appearance = 0,
    .ble_profile_init = comm_ble_profile_init,
    .bt_ble_init  = le_trans_bt_ble_init,
    .bt_ble_before_start_init = le_trans_bt_ble_before_start_init,
    .bt_ble_exit = le_trans_bt_ble_exit,
    .ble_module_enable = le_trans_ble_module_enable,
};

Source: app_trans.c#L56-L64

设计要点:

  • .ble_profile_init = comm_ble_profile_init 复用公共 profile 初始化入口,而 ble_trans.c 通过 trans_gatt_control_block 提供自己的 server/client/sm 配置,二者在 comm_ble_profile_init 内部结合——这就是"公共框架 + 业务私有配置"的扩展模式。
  • .bt_ble_init / .bt_ble_before_start_init / .bt_ble_exit / .ble_module_enable 分别挂接 ble_trans.c 中对应的实现,使透传模块能介入协议栈启动的各个阶段。
  • same_address = 0 表示经典蓝牙与 BLE 使用不同地址;appearance = 0 表示未声明 GAP 外观。

协议栈启动与退出

le_trans_bt_start() 先根据系统时钟配置 PLL 参数,再依次调用 btstack_ble_start_before_init 与 btstack_init 拉起协议栈:

static void le_trans_bt_start()
{
    u32 sys_clk =  clk_get("sys");
    bt_pll_para(TCFG_CLOCK_OSC_HZ, sys_clk, 0, 0);
    /* bt_osc_offset_ext_save(-15); // 10pF晶振 */

    btstack_ble_start_before_init(&le_trans_data_config, 0);

    btstack_init();
}

Source: app_trans.c#L115-L124

退出流程则强调顺序:先调用 ble_comm_module_enable(0) 关闭模块,延时 20 个 OS tick 等待内部处理,再 btstack_ble_exit(0) 真正退出协议栈(app_trans.c#L137-L144)。这种"先降级、后拆除"的顺序避免在协议栈活跃时直接释放资源导致挂死。

应用启动与消息循环

le_trans_app_start() 的初始化顺序是:系统时钟(sys/lsb/sfc)→ 蓝牙时钟 → 协议栈 → LED → 通用串口 → 定时器 → 消息循环:

static void le_trans_app_start()
{
    clk_set("sys", TCFG_CLOCK_SYS_HZ);
    clk_set("lsb", TCFG_CLOCK_LSB_HZ);
    clk_set("sfc", TCFG_CLOCK_SFC_HZ);

    clock_bt_init();
    le_trans_bt_start();

#if TCFG_LED_ENABLE
    led_operate(LED_INIT_FLASH);
#endif

    // 配置一个通用串口做ble2uart or uart2ble
#if TCFG_COMMON_UART_ENABLE
    common_uart_init(TCFG_COMMON_UART_BAUDRATE, COMMON_UART_TX_PIN, COMMON_UART_RX_PIN);
#endif

    le_trans_run_loop();
}

Source: app_trans.c#L176-L205

值得注意:common_uart_init 的注释明确写着"配置一个通用串口做 ble2uart or uart2ble",即透传方向由串口收发自动决定。le_trans_run_loop() 则是一个被 LP_RUNCODE_AT(.lp_running.app.text) 标注的低功耗代码段,循环调用 get_msg 获取系统消息并交给 app_comm_process_handler 分发,同时支持 APP_SWITCH_MODE_EN 下的应用切换退出(app_trans.c#L148-L163)。

应用状态机

le_trans_state_machine 是 application 框架的标准状态机回调,覆盖 APP_STA_CREATE / APP_STA_START / APP_STA_PAUSE / APP_STA_RESUME / APP_STA_STOP 各阶段;在 APP_STA_START 阶段根据 it->action == ACTION_LE_TRANS_MAIN 触发真正的应用启动(app_trans.c#L217-L240)。这种"意图(intent)驱动"的模式是杰理多应用框架的标准做法,使透传应用可以被其他应用(如 OTA、AT 模式)以统一的 action 方式唤起或切换。

软关机(电源管理)

static void le_trans_set_soft_poweroff(void)
{
#if (TCFG_LOWPOWER_PATTERN == SOFT_MODE)
    le_trans_is_active = 1;
#endif
    //必须先主动断开蓝牙链路,否则要等链路超时断开
    btstack_ble_exit(0);

    if (ble_comm_dev_is_connected(GATT_ROLE_SERVER) || ble_comm_dev_is_connected(GATT_ROLE_CLIENT)) {
#if (TCFG_LOWPOWER_PATTERN == SOFT_MODE)
        //soft 方式非必须等链路断开
        sys_timeout_add((void *)POWER_EVENT_POWER_SOFTOFF, (void *)app_power_event_to_user, WAIT_DISCONN_TIME_MS);
#elif (TCFG_LOWPOWER_PATTERN == SOFT_BY_POWER_MODE)
        //must wait disconn
        app_power_soft.wait_disconn = 1;
#endif
    } else {
        app_power_set_soft_poweroff(NULL);
    }
}

Source: app_trans.c#L82-L103

这段代码体现了两种低功耗模式的取舍:SOFT_MODE 下允许"先关机、后台等断链",用 sys_timeout_add 延迟触发 POWER_EVENT_POWER_SOFTOFF;SOFT_BY_POWER_MODE 则必须等链路断开(app_power_soft.wait_disconn = 1)才能关机,防止掉电瞬间链路残留。

BLE 协议处理层详解(ble_trans.c)

ble_trans.c 是透传的"数据面"核心,包含 GATT 配置、安全配置、广播、数据收发与事件上报五部分。

GATT 控制块与回调注册

模块通过三个静态配置结构体 + 一个控制块把自身挂进协议栈:

static const sm_cfg_t trans_sm_init_config = {
    .slave_security_auto_req = 0,
    .slave_set_wait_security = 0,
#if PASSKEY_ENABLE
    .io_capabilities = IO_CAPABILITY_DISPLAY_ONLY,
#else
    .io_capabilities = IO_CAPABILITY_NO_INPUT_NO_OUTPUT,
#endif
    .authentication_req_flags = SM_AUTHREQ_BONDING | SM_AUTHREQ_MITM_PROTECTION,
    .min_key_size = 7,
    .max_key_size = 16,
    .sm_cb_packet_handler = NULL,
};

const gatt_server_cfg_t trans_server_init_cfg = {
    .att_read_cb = &trans_att_read_callback,
    .att_write_cb = &trans_att_write_callback,
    .event_packet_handler = &trans_event_packet_handler,
};

Source: ble_trans.c#L66-L88

安全配置的设计意图:默认 IO_CAPABILITY_NO_INPUT_NO_OUTPUT 且开启 SM_AUTHREQ_BONDING | SM_AUTHREQ_MITM_PROTECTION,即透传场景通常无配对界面,但保留绑定与防中间人能力;PASSKEY_ENABLE 置 1 可切换为 DISPLAY_ONLY 以便手机端弹窗显示 6 位 PIN。min_key_size = 7 满足 LE 最低 7 字节密钥要求,max_key_size = 16 允许 128 位 AES 密钥。

trans_gatt_control_block 汇总所有配置,并依据编译宏按需挂载 server / client / sm(ble_trans.c#L90-L116):mtu_size = ATT_LOCAL_MTU_SIZE、发送缓冲 cbuffer_size = ATT_SEND_CBUF_SIZE,multi_dev_flag = 0 表示单连接模式。

UART→BLE 数据通路

这是透传最核心的函数——串口收到的数据被原样封装为 GATT Notification 发给手机:

static void trans_uart_rx_to_ble(uint8_t *packet, uint32_t size)
{
    if (trans_con_handle && ble_comm_att_check_send(trans_con_handle, size) &&
        ble_gatt_server_characteristic_ccc_get(trans_con_handle, ATT_CHARACTERISTIC_ae02_01_CLIENT_CONFIGURATION_HANDLE)) {
        ble_comm_att_send_data(trans_con_handle, ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE, packet, size, ATT_OP_AUTO_READ_CCC);
        log_info_hexdump(packet, size);
    } else {
        log_info("drop uart data!!!\n");
    }
}

Source: ble_trans.c#L129-L138

发送前做了三重保护,这是透传数据不丢失的关键:

  1. trans_con_handle 非空——链路必须存在;
  2. ble_comm_att_check_send(conn_handle, size)——发送缓冲(ATT_SEND_CBUF_SIZE)能容纳本次数据,避免覆盖未发送完的数据;
  3. ble_gatt_server_characteristic_ccc_get(...)——对端必须已使能该特征的 CCC(开启 Notification),否则发送无意义。

任一条件不满足即打印 drop uart data!!! 并丢弃,保证协议栈发送队列不被撑爆(背压机制)。ATT_OP_AUTO_READ_CCC 表示发送时自动读取 CCC 确认。

BLE→UART 数据通路

手机端写入特征值时由 trans_att_write_callback 处理(在文件后段实现,本次源码探索未覆盖其函数体,但其声明见 ble_trans.c#L60)。结合 common_uart_init 的注释"ble2uart or uart2ble"可知:写回调中收到的 payload 会通过通用串口 TX 发送到外部 MCU,方向与 UART→BLE 对称。

回连恢复与连接参数更新

配对绑定后主机回连时,GATT Server 不会自动恢复各特征的 CCC,需要主动使能:

static void trans_resume_all_ccc_enable(uint16_t conn_handle, uint8_t update_request)
{
    ble_gatt_server_characteristic_ccc_set(conn_handle, ATT_CHARACTERISTIC_ae02_01_CLIENT_CONFIGURATION_HANDLE, ATT_OP_NOTIFY);
    ble_gatt_server_characteristic_ccc_set(conn_handle, ATT_CHARACTERISTIC_ae04_01_CLIENT_CONFIGURATION_HANDLE, ATT_OP_NOTIFY);
    ble_gatt_server_characteristic_ccc_set(conn_handle, ATT_CHARACTERISTIC_ae05_01_CLIENT_CONFIGURATION_HANDLE, ATT_OP_INDICATE);
    ble_gatt_server_characteristic_ccc_set(conn_handle, ATT_CHARACTERISTIC_ae3c_01_CLIENT_CONFIGURATION_HANDLE, ATT_OP_NOTIFY);

    if (update_request) {
        trans_send_connetion_updata_deal(conn_handle);
    }
}

Source: ble_trans.c#L171-L186

代码注释点明了设计动机:"配对绑定的方式,主机回连不是在使能server的通知开关,需要自己打开"(ble_trans.c#L168)。注意各特征使用不同通知类型:ae02_01/ae04_01/ae3c_01 用 NOTIFY,ae05_01 用 INDICATE——因为 INDICATE 带应用层确认,适合重要数据(如升级命令),NOTIFY 适合高速透传数据。

连接参数更新通过 ble_gatt_server_connetion_update_request(conn_handle, trans_connection_param_table, CONN_PARAM_TABLE_CNT) 发起,且用 trans_connection_update_enable 做一次性保护,避免重复请求被协议栈拒绝(ble_trans.c#L151-L158)。

事件上报

协议栈产生的 HCI/GATT 事件(连接、断开、安全、对端系统识别)经 trans_event_packet_handler 汇总,并通过 trans_event_post 转成系统事件推送给应用层:

static void trans_event_post(u32 arg_type, u8 priv_event, u8 *args, u32 value)
{
    struct sys_event *e = event_pool_alloc();
    if (e == NULL) {
        log_info("Memory allocation failed for sys_event");
        return;
    }
    e->type = SYS_BT_EVENT;
    e->arg  = (void *)arg_type;
    e->u.bt.event = priv_event;
    if (args) {
        memcpy(e->u.bt.args, args, 7);
    }
    e->u.bt.value = value;
    main_application_operation_event(NULL, e);
}

Source: ble_trans.c#L219-L236

这段代码是"协议栈线程 → 应用线程"的典型桥接:event_pool_alloc() 从事件池取空闲事件(内存不足时打印日志并放弃,不会阻塞协议栈),填充 SYS_BT_EVENT 类型后调用 main_application_operation_event 交给应用框架,最终进入 le_trans_run_loop 的 app_comm_process_handler 被消费。args 固定拷贝 7 字节(u.bt.args 数组容量),是 SDK 事件结构的既定约束。

对端操作系统识别通过 trans_check_remote_result 完成,REMOTE_TYPE_IOS 时打印 is ios,否则打印 not ios(ble_trans.c#L199-L206),用于区分 iOS/Android 的连接参数策略(iOS 对连接参数请求有限制)。

核心数据流(Core Flow)

透传的完整生命周期从应用启动到双向数据搬运,可按下面两条路径理解:

sequenceDiagram
    participant APP as application 框架
    participant AT as app_trans.c
    participant BT as ble_trans.c
    participant ST as btstack 协议栈
    participant UART as 通用串口
    participant PH as 手机 App

    Note over APP,PH: 启动阶段
    APP->>AT: ACTION_LE_TRANS_MAIN (APP_STA_START)
    AT->>AT: le_trans_app_start: 时钟/LED/串口初始化
    AT->>ST: le_trans_bt_start: btstack_ble_start_before_init
    ST->>BT: comm_ble_profile_init 挂载 trans_gatt_control_block
    AT->>AT: le_trans_run_loop: get_msg 循环
    ST-->>BT: HCI/GATT 事件 (连接/安全/断链)
    BT->>APP: trans_event_post: SYS_BT_EVENT

    Note over UART,PH: 数据阶段 (UART→BLE)
    UART->>BT: trans_uart_rx_to_ble(packet, size)
    BT->>BT: 校验连接/缓冲/CCC 三重条件
    BT->>PH: ble_comm_att_send_data (Notify ae02_01)

    Note over UART,PH: 数据阶段 (BLE→UART)
    PH->>BT: 写入特征值 → trans_att_write_callback
    BT->>UART: 串口 TX 输出到外部 MCU

    Note over AT,ST: 关机阶段
    APP->>AT: le_trans_set_soft_poweroff
    AT->>ST: btstack_ble_exit(0)
    AT->>AT: 依 TCFG_LOWPOWER_PATTERN 决定是否等断链

关键顺序说明:

  1. 启动必须遵循"配置结构体 → btstack_ble_start_before_init → btstack_init"的顺序,GATT 控制块在协议栈初始化前就绪;
  2. UART→BLE 发送前的三重校验(连接句柄、发送缓冲、CCC 状态)必须在调用 ble_comm_att_send_data 之前完成,缺一即丢弃数据;
  3. 事件上报使用事件池异步推送,协议栈线程不会被应用层处理阻塞;
  4. 关机必须先 btstack_ble_exit(0) 主动断链,再根据低功耗模式决定是否等待断链完成,避免链路残留导致功耗异常。

配置选项(Configuration Options)

透传框架的行为由编译宏与板级配置共同决定。源码中直接出现的配置项如下:

配置项类型默认值/取值说明
CONFIG_APP_LE_TRANS编译宏0/1透传应用总开关,为 0 时 app_trans.c/ble_trans.c 不参与编译
TCFG_COMMON_UART_ENABLE编译宏0/1通用串口使能,关闭则无 UART 数据源
TCFG_COMMON_UART_BAUDRATE数值板级定义透传串口波特率
COMMON_UART_TX_PIN / COMMON_UART_RX_PINGPIO板级定义透传串口引脚
TCFG_LOWPOWER_PATTERN枚举SOFT_MODE / SOFT_BY_POWER_MODE软关机模式:SOFT_MODE 非必须等断链;SOFT_BY_POWER_MODE 必须等断链
PASSKEY_ENABLE宏0置 1 时 SM io_capabilities 切换为 IO_CAPABILITY_DISPLAY_ONLY(显示 6 位 PIN)
CONFIG_BT_GATT_SERVER_NUM数值编译配置非 0 时挂载 trans_server_init_cfg
CONFIG_BT_GATT_CLIENT_NUM数值编译配置非 0 时挂载 trans_client_init_cfg
CONFIG_BT_SM_SUPPORT_ENABLE编译宏0/1非 0 时挂载 trans_sm_init_config
RCSP_BTMATE_EN编译宏0/1杰理 RCSP 助手相关功能(如 resume_all_ccc_enable 中的 RCSP 分支)
APP_SWITCH_MODE_EN编译宏0/1应用切换模式,使能后在消息循环中可响应退出
TCFG_LED_ENABLE编译宏0/1启动时执行 led_operate(LED_INIT_FLASH)
TCFG_CLOCK_SYS_HZ / TCFG_CLOCK_LSB_HZ / TCFG_CLOCK_SFC_HZ数值板级定义系统/LSB/SFC 时钟频率,启动时设置

安全与连接参数相关(定义于 ble_trans.h 及 profile 头文件,部分行号未在本次探索范围内):

配置项类型说明
ATT_LOCAL_MTU_SIZE数值本地 MTU 大小,控制单包有效载荷
ATT_SEND_CBUF_SIZE数值ATT 发送环形缓冲大小,决定 ble_comm_att_check_send 的背压阈值
SM_AUTHREQ_BONDING / SM_AUTHREQ_MITM_PROTECTION位标志绑定 + 防中间人认证要求
min_key_size / max_key_size数值7 ~ 16 字节密钥范围
trans_connection_param_table / CONN_PARAM_TABLE_CNT表连接参数候选表(间隔/潜伏期/超时)

使用示例

示例 1:将透传应用注册进 application 框架

透传应用通过标准 application 结构注册,状态机回调由框架在应用切换时调用:

static int le_trans_state_machine(struct application *app, enum app_state state, struct intent *it)
{
    switch (state) {
    case APP_STA_CREATE:
        break;

    case APP_STA_START:
        if (!it) {
            break;
        }
        switch (it->action) {
        case ACTION_LE_TRANS_MAIN:
            le_trans_app_start();
            break;
        }
        break;

    case APP_STA_PAUSE:
        break;

    case APP_STA_RESUME:
        break;

    case APP_STA_STOP:
        break;
    }
    return 0;
}

Source: app_trans.c#L217-L240(函数体末尾 return 0; 及收尾代码位于后续行)

使用方式:其他应用(如 AT 模式、OTA)在需要切到透传时,构造 intent 并设置 action = ACTION_LE_TRANS_MAIN 后投递给本应用;应用收到后在 APP_STA_START 阶段启动。这就是杰理多应用框架的"意图驱动切换"。

示例 2:UART→BLE 透传发送(带三重背压校验)

这是透传数据面最核心的调用序列,展示了如何在驱动层直接搬运数据:

static void trans_uart_rx_to_ble(uint8_t *packet, uint32_t size)
{
    if (trans_con_handle && ble_comm_att_check_send(trans_con_handle, size) &&
        ble_gatt_server_characteristic_ccc_get(trans_con_handle, ATT_CHARACTERISTIC_ae02_01_CLIENT_CONFIGURATION_HANDLE)) {
        ble_comm_att_send_data(trans_con_handle, ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE, packet, size, ATT_OP_AUTO_READ_CCC);
        log_info_hexdump(packet, size);
    } else {
        log_info("drop uart data!!!\n");
    }
}

Source: ble_trans.c#L129-L138

使用方式:在通用串口 RX 中断或轮询回调中调用,packet/size 为串口收到的一帧数据;返回前请确认 trans_con_handle 已由连接事件更新,否则数据会被丢弃。

示例 3:回连后恢复所有特征的通知使能

绑定设备回连时,服务端必须自行恢复 CCC,否则手机收不到数据:

static void trans_resume_all_ccc_enable(uint16_t conn_handle, uint8_t update_request)
{
    log_info("resume_all_ccc_enable\n");

#if RCSP_BTMATE_EN
    /* ble_gatt_server_characteristic_ccc_set(conn_handle, ATT_CHARACTERISTIC_ae02_02_CLIENT_CONFIGURATION_HANDLE, ATT_OP_NOTIFY); */
#endif
    ble_gatt_server_characteristic_ccc_set(conn_handle, ATT_CHARACTERISTIC_ae02_01_CLIENT_CONFIGURATION_HANDLE, ATT_OP_NOTIFY);
    ble_gatt_server_characteristic_ccc_set(conn_handle, ATT_CHARACTERISTIC_ae04_01_CLIENT_CONFIGURATION_HANDLE, ATT_OP_NOTIFY);
    ble_gatt_server_characteristic_ccc_set(conn_handle, ATT_CHARACTERISTIC_ae05_01_CLIENT_CONFIGURATION_HANDLE, ATT_OP_INDICATE);
    ble_gatt_server_characteristic_ccc_set(conn_handle, ATT_CHARACTERISTIC_ae3c_01_CLIENT_CONFIGURATION_HANDLE, ATT_OP_NOTIFY);

    if (update_request) {
        trans_send_connetion_updata_deal(conn_handle);
    }
}

Source: ble_trans.c#L171-L186

使用方式:在 GATT 连接建立事件(trans_event_packet_handler 收到连接事件)中调用,update_request = 1 时同时发起连接参数更新;新增自定义特征时需在此处同步添加 ccc_set 调用,这是回连功能最常见的扩展点。

API 参考

以下 API 均来自源码中可验证的签名与调用方式;ble_trans.h 中未在本次探索覆盖的完整声明以"声明于头文件"标注。

应用框架层(app_trans.c,static 函数,仅供本模块内部使用)

le_trans_app_start(void)

透传应用入口,依次完成时钟、蓝牙协议栈、LED、通用串口初始化后进入消息循环。

  • 返回:void
  • 调用方:le_trans_state_machine 在 APP_STA_START + ACTION_LE_TRANS_MAIN 时调用
  • 说明:内部调用 le_trans_run_loop() 后不返回(除非 APP_SWITCH_MODE_EN 触发退出)

le_trans_run_loop(void)

消息循环,循环执行 get_msg 与 app_comm_process_handler。

  • 返回:void
  • 说明:标注 LP_RUNCODE_AT(.lp_running.app.text),属于低功耗运行段代码

le_trans_set_soft_poweroff(void)

软关机流程:先 btstack_ble_exit(0) 断链,再按低功耗模式决定立即关机或等待断链。

  • 返回:void
  • 说明:SOFT_MODE 下通过 sys_timeout_add(POWER_EVENT_POWER_SOFTOFF, ...) 延迟关机

BLE 协议层(ble_trans.c)

trans_uart_rx_to_ble(uint8_t *packet, uint32_t size)

将串口数据帧通过 GATT Notify 发送给已连接主机。

  • 参数:packet(uint8_t*)数据指针;size(uint32_t)数据长度
  • 返回:void
  • 失败行为:连接无效、发送缓冲不足或 CCC 未使能时打印 drop uart data!!! 并丢弃
  • 要点:发送特征句柄 ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE,模式 ATT_OP_AUTO_READ_CCC

trans_att_read_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t offset, uint8_t *buffer, uint16_t buffer_size)

GATT Server 属性读回调,处理主机发起的 Read 请求。

  • 参数:connection_handle 连接句柄;att_handle 属性句柄;offset 读偏移;buffer 输出缓冲;buffer_size 缓冲大小
  • 返回:uint16_t(按 btstack 惯例返回写入字节数)
  • 声明位置:ble_trans.c#L59

trans_att_write_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size)

GATT Server 属性写回调,接收手机下发的透传数据(BLE→UART 通路入口)。

  • 参数:connection_handle 连接句柄;att_handle 属性句柄;transaction_mode 事务模式(Write/WriteNoResponse);offset 写偏移;buffer 数据;buffer_size 长度
  • 返回:int(0 表示成功)
  • 声明位置:ble_trans.c#L60

trans_event_packet_handler(int event, uint8_t *packet, uint16_t size, uint8_t *ext_param)

协议栈事件统一入口(连接、断开、安全、对端系统识别等),内部调用 trans_event_post 推送系统事件。

  • 返回:int
  • 声明位置:ble_trans.c#L61

trans_event_post(u32 arg_type, u8 priv_event, u8 *args, u32 value)

从事件池分配 sys_event,填充 SYS_BT_EVENT 后投递到应用框架。

  • 参数:arg_type(u32)事件子类型;priv_event(u8)私有事件号;args(u8*)最多拷贝 7 字节附带参数;value(u32)事件附加值
  • 返回:void
  • 失败行为:event_pool_alloc() 返回 NULL 时打印日志并放弃(不阻塞协议栈线程)

trans_resume_all_ccc_enable(uint16_t conn_handle, uint8_t update_request)

回连后恢复各特征 CCC(ae02_01/ae04_01/ae3c_01 用 NOTIFY,ae05_01 用 INDICATE),可选发起连接参数更新。

  • 参数:conn_handle 连接句柄;update_request(uint8_t)非 0 时调用 trans_send_connetion_updata_deal
  • 返回:void

trans_send_connetion_updata_deal(uint16_t conn_handle)

通过 ble_gatt_server_connetion_update_request 请求连接参数更新,trans_connection_update_enable 置 0 防止重复请求。

  • 参数:conn_handle 连接句柄
  • 返回:void
  • 失败行为:请求返回非 0 时保留 trans_connection_update_enable,后续可重试

trans_check_remote_result(uint16_t con_handle, remote_type_e remote_type)

打印对端系统类型(REMOTE_TYPE_IOS 时标记 is ios),用于区分 iOS/Android 连接策略。

  • 参数:con_handle 连接句柄;remote_type(remote_type_e)识别结果
  • 返回:void

专业笔记:故障模式、边界与并发

数据丢失与背压

  • 发送缓冲满:ble_comm_att_check_send 返回假时数据被直接丢弃。透传是"尽力而为"通道,应用层(或外部 MCU)需自行实现流控(如串口 RTS/CTS、分帧重传)。若需要可靠传输,应改用带 INDICATE 确认的特征(如 ae05_01)或上层协议分包。
  • CCC 未使能:手机尚未打开 Notification 时串口数据同样被丢弃,drop uart data!!! 日志是排查"手机收不到数据"的第一线索。

连接状态竞争

trans_con_handle 在断开事件后可能残留旧值。trans_uart_rx_to_ble 虽校验句柄非空,但若在断链与事件处理之间串口数据到达,可能向已失效连接发送。SDK 的 ble_comm_att_send_data 内部会进一步校验,应用层可通过在断开事件中清零 trans_con_handle 加固。

并发与线程模型

  • 串口 RX 中断/驱动线程与协议栈线程是两个执行上下文,trans_uart_rx_to_ble 调用 ble_comm_att_send_data 时协议栈内部有锁保护发送队列;
  • 事件上报使用 event_pool_alloc 异步投递,协议栈线程绝不等待应用层,避免死锁;
  • trans_connection_update_enable 标志防重入,保证连接参数请求只发起一次。

低功耗边界

SOFT_BY_POWER_MODE 下若链路未断开就执行 app_power_set_soft_poweroff 会导致异常,因此代码严格区分两种模式;SOFT_MODE 的延迟关机通过 sys_timeout_add 实现,注意 WAIT_DISCONN_TIME_MS 需大于链路超时时间。

安全边界

默认 IO_CAPABILITY_NO_INPUT_NO_OUTPUT + MITM 保护:无配对界面时攻击者可伪装绑定,但 MITM 标志要求双方认证;对安全敏感场景应开启 PASSKEY_ENABLE 强制 PIN 确认。

性能与运维

  • 单包吞吐:受 ATT_LOCAL_MTU_SIZE 与 ATT_SEND_CBUF_SIZE 约束。cbuffer_size 决定背压开始丢弃前的最大在途数据量,增大它可提高突发吞吐但增加 RAM 占用。
  • 连接参数:trans_connection_param_table 提供候选参数表,iOS 对连接间隔有最小限制(30ms 量级),trans_check_remote_result 的 iOS 识别可用于选择不同参数表。
  • 调试手段:log_info_hexdump(packet, size) 打印每一帧透传数据;LE_DEBUG_TIMER_INFO 可开启 1s 周期定时器日志;LOG_DUMP_ENABLE 控制数据 dump 级别(见 app_trans.c#L42-L52 与 ble_trans.c#L40-L48)。
  • 收发计数:模块维护 trans_recieve_test_count / trans_send_test_count 统计收发帧数,可用于吞吐自测。

扩展点

  1. 新增透传特征:在 profile(ble_trans_profile.h)中定义新特征句柄,并在 trans_resume_all_ccc_enable 中增加对应 ccc_set;发送时调用 ble_comm_att_send_data 并指定新句柄。
  2. 切换通知类型:需要可靠传输时把 ATT_OP_NOTIFY 换成 ATT_OP_INDICATE(参考 ae05_01 的做法)。
  3. 接入其他数据源:仿照 trans_uart_rx_to_ble 编写 SPI/I2C 数据回调,只需满足"连接有效 + 缓冲可容纳 + CCC 已使能"三重前置。
  4. 多连接支持:trans_gatt_control_block.multi_dev_flag = 0 为单连接;置 1 并引入按连接句柄区分的状态表即可支持多主机。
  5. 应用切换:通过 APP_SWITCH_MODE_EN + tans_exit_app 标志,在消息循环中退出透传回到主应用,是 SDK 多应用协同的标准钩子。

测试与验证线索

本次源码探索未读取独立测试文件,但源码中保留了内建自测痕迹:trans_recieve_test_count / trans_send_test_count 收发计数与 trans_test_read_write_buf[4] 读写测试缓冲,配合 le_trans_run_loop 的消息循环可做回环测试(手机端写特征 → 串口回显 → 再转回 BLE)。LE_DEBUG_TIMER_INFO 定时器可用于长时间稳定性观测。建议验证路径:手机连接 → 打开 ae02_01 Notification → 串口发数据 → 手机应收到同帧数据;手机写 ae02_01 → 串口应输出同帧数据。

Related Links

  • 透传应用入口 app_trans.c
  • BLE 透传处理模块 ble_trans.c
  • 透传 Profile 定义 ble_trans_profile.h
  • 透传模块头文件 ble_trans.h
  • Transfer 工程入口 app_main.c
  • AT 指令交互示例(同级页面)
  • 非连接广播透传示例(同级页面)
  • USB Dongle 透传通道规划 ota_dg_central.h
Next
透传与数传示例