当前文档版本为 NDK-v1.1.0,您可以访问当前页面的 开发中 版本以获取最近可能的更新。

BLE Dongle (产线测试)

重要

此例程仅存在于特殊版本的SDK中,如有需要请联系Panchip。

1 功能概述

此sample为pan107/pan101上演示BLE快连产线测试Dongle的功能,用于生产线快速测试BLE HID设备(鼠标、键盘等)。

核心特性:

  • 智能过滤: 支持多种过滤条件组合(设备名称前缀、UUID、RSSI、厂商数据等)

  • 自动识别: 通过解析Report Map自动识别设备类型(键盘/鼠标/复合设备)

  • 长度解析: 根据BLE通知数据包长度自动区分不同类型的HID报告

  • 快速连接: 连接完成后自动还原初始配置,准备下一次测试

  • 多接口USB: 支持3个USB HID接口(标准键盘+复合设备+自定义)

2 环境要求

  • board: pan107QFN32核心板/ pan101MSOP10核心板 + evb底板

  • uart0: 设置P16,P17作为默认的LOG输出端口,波特率921600

  • USB: 需要使用MPC版本之后USB修复后的芯片(早期版本USB不稳定)

  • BLE设备: 需要配对的BLE HID设备(鼠标/键盘/复合设备)

3 编译和烧录

例程位置:<home>\nimble\samples\solutions_hid\ble_dongle\keil_107x

  1. 打开Keil工程文件ble_dongle.uvprojx

  2. 选择目标芯片型号(PAN1070/PAN1010)

  3. 点击”Rebuild”编译工程

  4. 使用J-Link或其他调试器烧录固件

  5. 烧录完成后,Dongle自动进入扫描状态

注意:

  • 首次使用前建议全擦除芯片

  • 如需合并Bootloader,请参考Boot相关文档

  • FLM文件需根据实际芯片型号移植

4 演示说明

4.1 产线测试流程

典型应用场景:

产线工位 → BLE Dongle插入PC → BLE设备开机 → 自动配对 → 数据传输测试 → 断开重连

详细步骤:

  1. Dongle启动:

    • 上电后等待3秒(USB枚举稳定)

    • 初始化BLE协议栈和过滤器

    • 开始BLE扫描

  2. 设备发现与过滤:

    // 默认过滤配置(app_ble.c)
    #define APP_FILT_MATCH_MODE              BLE_DEV_FILT_MODE_ALL  // 所有条件必须满足
    #define APP_FILT_DEV_NAME_PREFIX_EN      1                      // 启用名称前缀过滤
    #define APP_FILT_DEV_NAME_PREFIX         "Pan"                  // 匹配"Pan"开头的设备
    #define APP_FILT_RSSI_THRESHOLD          -50                    // RSSI阈值:-50dBm
    

    Dongle只接收满足以下条件的设备:

    • 设备名称以”Pan”开头

    • RSSI信号强度 > -50dBm(近距离,减少干扰)

    • 所有条件必须同时满足(BLE_DEV_FILT_MODE_ALL)

  3. 自动连接:

    • 发现符合条件的设备后,立即发起连接

    • 连接成功后停止扫描

    • 启动SMP配对(加密连接)

  4. 服务发现(SDP):

    • 发现HID Service(0x1812)

    • 读取所有Characteristic

    • 订阅所有Report类型的Notify

  5. 设备类型识别:

    • 读取Report Map描述符(可选,默认关闭)

    • 解析Usage Page判断设备类型:

      • 0x01 + 0x02: Mouse

      • 0x070x06: Keyboard

      • 0x0C: Consumer Control

    • 日志输出识别结果

  6. 数据传输:

    • BLE设备发送HID报告(Notify)

    • Dongle接收后根据数据长度判断类型:

      • 8字节 → 标准键盘(EP1)

      • 2字节 → Consumer控制(EP2)

      • 7字节 → 鼠标数据(EP2)

      • 15字节 → NKRO键盘(EP2)

      • 1字节 → Power键(EP2)

    • 转发到对应的USB端点

  7. 断开重连:

    • 设备断开或测试完成后

    • Dongle立即重新开始扫描

    • 无需手动复位,可连续测试多个设备

4.2 过滤模式配置

两种过滤模式:

模式

宏定义

说明

适用场景

ALL(默认)

BLE_DEV_FILT_MODE_ALL

所有条件必须同时满足

产线精确匹配,避免误连

SINGLE

BLE_DEV_FILT_MODE_SINGLE

满足任一条件即可

宽松测试,兼容多种设备

修改方法:

// 在 app_ble.c 中修改
#define APP_FILT_MATCH_MODE    BLE_DEV_FILT_MODE_SINGLE  // 改为SINGLE模式

可用过滤条件:

条件

宏定义

默认值

说明

设备名称前缀

APP_FILT_DEV_NAME_PREFIX_EN

1 (启用)

匹配”Pan”开头

UUID16

APP_FILT_UUID16_EN

0 (禁用)

匹配HID Service(0x1812)

厂商数据

APP_FILT_MFG_DATA_EN

0 (禁用)

匹配特定Company ID

RSSI阈值

APP_FILT_RSSI_THRESHOLD

-50 dBm

信号强度下限

配置示例:

// 示例1: 只按名称过滤(产线常用)
#define APP_FILT_MATCH_MODE              BLE_DEV_FILT_MODE_ALL
#define APP_FILT_DEV_NAME_PREFIX_EN      1
#define APP_FILT_DEV_NAME_PREFIX         "TestMouse"
#define APP_FILT_RSSI_THRESHOLD          -60

// 示例2: 按UUID+RSSI过滤(通用测试)
#define APP_FILT_MATCH_MODE              BLE_DEV_FILT_MODE_ALL
#define APP_FILT_DEV_NAME_PREFIX_EN      0
#define APP_FILT_UUID16_EN               1
#define APP_FILT_UUID16                  0x1812
#define APP_FILT_RSSI_THRESHOLD          -70

// 示例3: 宽松模式(任一条件满足)
#define APP_FILT_MATCH_MODE              BLE_DEV_FILT_MODE_SINGLE
#define APP_FILT_DEV_NAME_PREFIX_EN      1
#define APP_FILT_DEV_NAME_PREFIX         "Pan"
#define APP_FILT_RSSI_THRESHOLD          -80

4.3 设备类型识别

Report Map解析(可选):

默认关闭(APP_ENABLE_REPORT_MAP_READ=0),开启后可自动识别设备类型。

识别逻辑:

// 解析Report Map中的Usage Page
for (uint16_t i = 0; i < len - 1; i++) {
    // Usage Page 0x01 + Usage 0x02 = Mouse
    if (buf[i] == 0x05 && buf[i+1] == 0x01 && 
        buf[i+2] == 0x09 && buf[i+3] == 0x02) {
        is_mouse = true;
    }
    // Usage Page 0x07 = Keyboard
    if (buf[i] == 0x05 && buf[i+1] == 0x07) {
        is_keyboard = true;
    }
    // Usage Page 0x0C = Consumer
    if (buf[i] == 0x05 && buf[i+1] == 0x0C) {
        is_consumer = true;
    }
}

识别结果示例:

Summary: Report IDs=5, Keyboard=2, Mouse=1, Consumer=1, Vendor=NO
>>> Device Type: COMBO (Keyboard + Mouse + Consumer) <<<

4.4 数据长度解析

核心机制: Dongle根据BLE Notify数据包长度自动判断数据类型并转发到对应USB端点。

长度映射表:

数据长度

设备类型

Report ID

USB端点

说明

8字节

标准键盘

无(隐含)

EP1 (0x81)

8字节键盘报告(Modifier+Reserved+Key1-6)

2字节

Consumer控制

0x03

EP2 (0x82)

2字节Consumer键值

7字节

鼠标

0x05

EP2 (0x82)

7字节鼠标报告(Buttons+X+Y+Wheel+AC Pan)

15字节

NKRO键盘

0x02

EP2 (0x82)

15字节N-Key Rollover键盘

1字节

Power键

0x04

EP2 (0x82)

1字节Power键状态

代码实现:

case BLE_GAP_EVENT_NOTIFY_RX:
{
    uint8_t data_len = OS_MBUF_PKTLEN(event->notify_rx.om);
    
    if (data_len == 8) {
        // 标准键盘数据 → EP1
        uint8_t trans_data[8];
        memcpy(&trans_data[0], event->notify_rx.om->om_data, 8);
        usbd_ep_start_write(0, STAND_KB_ENDPOINT, trans_data, 8);
        
    } else if (data_len == 7) {
        // 鼠标数据 → EP2
        uint8_t trans_data[8];
        trans_data[0] = 0x05;  // Mouse Report ID
        memcpy(&trans_data[1], event->notify_rx.om->om_data, 7);
        trans_data[7] = 0x00;  // AC Pan default
        usbd_ep_start_write(0, COMPOSITE_ENDPOINT, trans_data, 8);
        
    } else if (data_len == 2) {
        // Consumer控制 → EP2
        uint8_t trans_data[3];
        trans_data[0] = 0x03;  // Consumer Report ID
        memcpy(&trans_data[1], event->notify_rx.om->om_data, 2);
        usbd_ep_start_write(0, COMPOSITE_ENDPOINT, trans_data, 3);
        
    } else if (data_len == 15) {
        // NKRO键盘 → EP2
        uint8_t trans_data[17];
        trans_data[0] = 0x02;  // NKRO Report ID
        memcpy(&trans_data[1], event->notify_rx.om->om_data, 15);
        usbd_ep_start_write(0, COMPOSITE_ENDPOINT, trans_data, 16);
    }
}

优势:

  • 无需预先知道设备类型,自动适配

  • 支持混合设备(键鼠一体)

  • 简化产线测试流程

5 开发说明

5.1 Flash配置

Flash分区布局:

分区

起始地址

大小

用途

Bootloader

0x00000000

40 KB

引导程序(可选)

App

0x0000A000

220 KB

应用程序

Backup

0x00040800

220 KB

OTA备份(未使用)

KV Store

0x00077000

16 KB

键值存储(未使用)

User

0x0007B000

12 KB

用户数据(未使用)

注意:

  • CONFIG_ENABLE_BOOTLOADER=0(库上默认): 不使用Bootloader,直接运行App

  • 如需DFU升级,需使能Bootloader并配置相应分区

5.2 BLE配置

5.2.0 关键配置宏

过滤相关宏(app_ble.c):

// 过滤模式
#define APP_FILT_MATCH_MODE              BLE_DEV_FILT_MODE_ALL

// 设备名称前缀过滤
#define APP_FILT_DEV_NAME_PREFIX_EN      1
#define APP_FILT_DEV_NAME_PREFIX         "Pan"

// UUID过滤(禁用)
#define APP_FILT_UUID16_EN               0
#define APP_FILT_UUID16                  0x1812

// 厂商数据过滤(禁用)
#define APP_FILT_MFG_DATA_EN             0

// RSSI阈值
#define APP_FILT_RSSI_THRESHOLD          -50

// MTU交换(禁用)
#define APP_ENABLE_MTU_EXCHANGE          0

// Report Map读取(禁用)
#define APP_ENABLE_REPORT_MAP_READ       0

连接参数(sdk_config.h):

宏定义

默认值

说明

CONFIG_BT_MAX_NUM_OF_CENTRAL

1

最大中心设备数量(单连接)

CONFIG_SYSTEM_CLOCK

48 MHz

系统时钟频率

configTOTAL_HEAP_SIZE

10240 字节

FreeRTOS堆大小

重要说明:

  • 单连接模式: CONFIG_BT_MAX_NUM_OF_CENTRAL=1,每次只连接一个设备

  • 自动重扫: 断开后立即重新扫描,无需人工干预

  • RPA支持: 可使用Resolvable Private Address(APP_USE_RPA=1)

5.2.1 初始化流程

void setup(void)
{
    // 1. 初始化消息队列
    app_msg_queue_init();
    
    // 2. 初始化BLE设备过滤器
    ble_dev_filt_init();
    ble_dev_filt_set_match_mode(APP_FILT_MATCH_MODE);
    ble_dev_filt_set_rssi(APP_FILT_RSSI_THRESHOLD);
    
    // 3. 配置过滤条件
    #if APP_FILT_DEV_NAME_PREFIX_EN
        ble_dev_filt_set_device_name_prefix(APP_FILT_DEV_NAME_PREFIX,
                                           strlen(APP_FILT_DEV_NAME_PREFIX));
    #endif
    
    #if APP_FILT_UUID16_EN
        ble_dev_filt_set_uuid16(APP_FILT_UUID16);
    #endif
    
    #if APP_FILT_MFG_DATA_EN
        uint8_t mfg_data[] = { APP_FILT_MFG_DATA };
        ble_dev_filt_set_manu_data(mfg_data, APP_FILT_MFG_DATA_LEN);
    #endif
    
    // 4. 初始化BLE协议栈
    app_ble_init();
    
    // 5. 启动BLE任务
    app_ble_task_start();
    
    // 6. 开始扫描
    app_ble_scan_start();
}

5.2.2 连接流程

扫描 → 发现设备 → 过滤检查 → 发起连接 → SMP配对 → SDP → 订阅Notify → 数据传输
  ↑                                                                      |
  └──────────────────── 断开 ←──────────────────────────────────────────┘

关键事件处理:

  1. BLE_GAP_EVENT_DISC: 发现设备,调用ble_dev_filt_is_match()检查过滤条件

  2. BLE_GAP_EVENT_CONNECT: 连接建立,记录conn_handle

  3. BLE_GAP_EVENT_ENC_CHANGE: 加密状态改变,配对成功后进行SDP

  4. BLE_GAP_EVENT_DISCONNECT: 断开连接,立即重启扫描

  5. BLE_GAP_EVENT_NOTIFY_RX: 收到Notify,根据长度转发到USB

5.3 USB配置

USB HID描述符:

Dongle虚拟出3个USB HID接口:

接口

端点

类型

Report描述符大小

用途

Interface 0

EP1 (0x81)

Input

63字节

标准键盘(8字节)

Interface 1

EP2 (0x82) IN/OUT

Input/Output

214字节

复合设备(鼠标+Consumer+NKRO)

Interface 2

EP3 (0x83) IN/OUT

Input/Output

33字节

自定义设备

VID/PID配置:

#define USBD_VID           0x07D1
#define USBD_PID           0x0015
#define USBD_MAX_POWER     100
#define USBD_LANGID_STRING 1033

Ring Buffer:

#define RINGBUFFER_SIZE    1024  // 每个缓冲区1024字节

struct ring_buf ringbuf_raw;    // Interface 0 (标准键盘)
struct ring_buf ringbuf_raw2;   // Interface 1 (复合设备)

数据转发逻辑:

void usb_report(void)
{
    // 处理标准键盘报告(ringbuf_raw) → EP1
    if (!ring_buf_is_empty(&ringbuf_raw)) {
        ring_buf_get(&ringbuf_raw, cur_data, REPORT_SIZE);
        usbd_ep_start_write(0, STAND_KB_ENDPOINT, cur_data, 8);
    }
    
    // 处理复合设备报告(ringbuf_raw2) → EP2
    if (!ring_buf_is_empty(&ringbuf_raw2)) {
        ring_buf_get(&ringbuf_raw2, cur_data, REPORT_SIZE);
        usbd_ep_start_write(0, COMPOSITE_ENDPOINT, cur_data, size);
    }
}

5.4 日志与调试

日志级别:

// app_log.h 中配置
#define APP_LOG_LVL    2  // 0:None, 1:Error, 2:Warning, 3:Info, 4:Debug

关键日志输出:

// 设备发现
Device Found peer_addr_type:1 peer_addr: XX:XX:XX:XX:XX:XX

// 连接建立
Connection established - handle:0
-peer_ota_addr: XX:XX:XX:XX:XX:XX(at: 1)
-peer_id_addr: XX:XX:XX:XX:XX:XX(at: 1)
-conn_itvl: 37500 us
-latency: 0
-timeout: 500 ms

// 服务发现
Service discovery complete; status=0, conn_handle=0
Peer cached for LED control

// 设备类型识别(如果开启)
Summary: Report IDs=5, Keyboard=2, Mouse=1, Consumer=1, Vendor=NO
>>> Device Type: COMBO (Keyboard + Mouse + Consumer) <<<

// 数据传输
received notification; conn_handle=0,attr_handle=XX,attr_len=8

// 断开重连
disconnection complete; reason=19
Restarting scan immediately...

调试建议:

  • 产线环境建议APP_LOG_LVL=2(只显示Warning以上)

  • 开发调试时设置为APP_LOG_LVL=3(显示Info)

  • 可通过UART日志监控整个连接过程

6 RAM/Flash资源使用情况

PAN107x资源配置:

Flash Total: 508 KB (0x7F000)
SRAM Total:  48 KB (0xC000)

实际使用情况(当前配置):

Memory Region

Start Address

Used Size

Region Size

%age Used

FLASH_TEXT

0x00000000

168,430 B

480.00 KB

34.27%

SRAM_DATA_TEXT

0x20000000

42,744 B

48.00 KB

86.96%

说明:

  • Flash占用: 168,430字节 ≈ 164.5 KB (BLE协议栈 + USB驱动 + 应用代码)

  • RAM占用: 42,744字节 ≈ 41.7 KB (FreeRTOS堆 + BLE上下文 + Ring Buffer)

  • Flash充裕: 使用率仅34.27%,剩余约315KB可用于功能扩展

  • RAM紧张: SRAM使用率达86.96%,接近上限,需注意内存优化

资源占用分析:

  • Flash主要占用:

    • BLE协议栈(NimBLE): ~80KB

    • USB HID驱动: ~15KB

    • 设备过滤器: ~8KB

    • Peer管理(SDP): ~12KB

    • 应用层代码: ~49.5KB

  • RAM主要占用:

    • 2个Ring Buffer: 2 × 1024 = 2048字节

    • BLE连接上下文: ~4KB

    • Peer服务发现缓存: ~5KB

    • FreeRTOS堆(configTOTAL_HEAP_SIZE): 10240字节

    • 系统栈和任务栈: ~20KB

优化建议:

  1. 关闭日志: APP_LOG_LVL=0 可节省~3KB Flash

  2. 关闭Report Map读取: 已默认关闭,节省~2KB Flash

  3. 减小Ring Buffer: 如不需要大数据量,可改为512字节

  4. 减小FreeRTOS堆: configTOTAL_HEAP_SIZE=8192 可节省2KB RAM

  5. 关闭MTU交换: 已默认关闭,节省代码空间

资源对比:

配置项

Flash占用

RAM占用

说明

基础BLE Dongle

164.5 KB

41.7 KB

当前配置(实际编译)

+ Report Map读取

~167KB

~42KB

增加~2.5KB Flash

+ MTU交换

~170KB

~43KB

增加~5.5KB Flash, ~1KB RAM

最小配置

~155KB

~40KB

关闭所有可选功能

7 常见问题

7.1 无法发现设备

可能原因:

  1. 过滤条件过于严格

  2. RSSI阈值设置过高

  3. 设备名称不匹配

解决方法:

// 临时放宽过滤条件
#define APP_FILT_MATCH_MODE              BLE_DEV_FILT_MODE_SINGLE
#define APP_FILT_RSSI_THRESHOLD          -80
#define APP_FILT_DEV_NAME_PREFIX_EN      0

7.2 连接后立即断开

可能原因:

  1. SMP配对失败

  2. 设备不支持加密

  3. 连接参数不兼容

解决方法:

  • 查看日志中的encryption change event; status=XX

  • status=0表示成功,非0表示失败

  • 代码已处理配对失败情况,会继续尝试GATT操作

7.3 数据长度不符合预期

可能原因:

  1. 设备Report描述符与标准不符

  2. 数据被截断

  3. MTU太小

解决方法:

  • 检查设备的Report Map

  • 开启MTU交换:APP_ENABLE_MTU_EXCHANGE=1

  • 查看日志中的attr_len

7.4 产线测试速度慢

优化建议:

  1. 提高RSSI阈值,减少远距离设备干扰

  2. 使用精确的设备名称前缀

  3. 关闭不必要的过滤条件

  4. 缩短扫描间隔(需修改底层代码)

8 与prf_dongle的对比

特性

ble_dongle

prf_dongle

common_prf_dongle

射频协议

BLE 5.0

2.4G PRF

2.4G PRF

连接方式

广播扫描+配对

固定频点+地址

多Pipe并发

设备数量

1个(单连接)

1-2个

最多3个

配对方式

自动过滤+连接

强制配对按键

强制配对按键

设备识别

Report Map解析

配对包类型字段

配对包类型字段

数据转发

按长度解析

固定格式

Ring Buffer隔离

应用场景

产线快速测试

无线鼠标接收器

键鼠套件接收器

优势

自动化程度高

低延迟,高上报率

多设备并发

劣势

依赖BLE协议栈

需手动配对

代码复杂度高

选择建议:

  • 产线测试: 使用ble_dongle,自动化程度高,无需手动配对

  • 高性能鼠标: 使用prf_dongle,1000Hz上报率,低延迟

  • 键鼠套件: 使用common_prf_dongle,支持多设备并发