蓝牙 LE PAST 技术详解:让第三台设备免扫描直接接收广播

PAST (Periodic Advertising Sync Transfer) 是蓝牙 5.0 引入的核心特性之一,也是 LE Audio 广播音频的关键使能技术。本文从协议原理、HCI 命令、LL 层 PDU 到代码路径,完整解析 PAST 如何让第三台设备跳过扫描直接接收广播数据。



视频链接: https://item.taobao.com/item.htm?id=1001969040805&mi_id=000032T4qZX9WZoRwX6YbxlNUaZOfOI6XoxDx0jxsfnwlEc&spm=a21xtw.29178619.0.0

Le Audio文章目录:

还在为蓝牙BLE Audio的学习苦恼吗?安排下,让你一文彻底了解Le Audio蓝牙低功耗音频的技术-CSDN博客


一、什么是 PAST

PAST 全称 Periodic Advertising Sync Transfer(周期广播同步转移),定义在 Bluetooth Core Spec Vol 6, Part B, Section 4.4.5。

一句话概括:设备 B 把自己已经建立的 Periodic Advertising 同步信息,通过 ACL 连接转移给设备 C,使 C 无需扫描就能直接接收设备 A 的周期广播。

PAST 解决的核心矛盾是:

|--------|------------------------------------------------|--------------------------|
| 问题 | 传统方式 | PAST 方式 |
| 发现周期广播 | 必须扫描 ADV_EXT_IND → 跟随 AuxPtr → 接收 AUX_SYNC_IND | 由已同步设备直接转移 SyncInfo |
| 功耗 | 扫描占空比高,耳机类设备无法承受 | 零扫描,Controller 直接在目标时刻唤醒 |
| 发现时间 | 需要数个广播周期 | 即时(一次 ACL PDU 传输即完成) |
| 可靠性 | 扫描可能错过 AUX_SYNC_IND | 通过 ACL 可靠传输 |


二、背景:Periodic Advertising 的工作方式

理解 PAST 之前,必须先理解 Periodic Advertising(周期广播)的常规同步过程。

2.1 周期广播的三层结构

复制代码
Device A (Advertiser)
    │
    ├─ Primary ADV: ADV_EXT_IND (PDU on ch 37/38/39)
    │     └─ AuxPtr: 指向 Secondary 信道
    │
    ├─ Secondary ADV: AUX_SYNC_IND (PDU on secondary ch)
    │     └─ SyncInfo: 周期广播的同步参数
    │     └─ TXPower, AdvDataInfo 等
    │
    └─ Periodic ADV: ADV_PERIODIC (在 SyncInfo 指定的信道/时间发送)
          └─ 携带 BIGInfo (如果存在 BIG)
          └─ 携带周期性广播数据

2.2 常规同步流程(无 PAST)

  1. Scanner 在主信道(37/38/39)扫描,收到 ADV_EXT_IND
  2. ADV_EXT_IND 中的 AuxPtr 字段指向 Secondary 信道
  3. Scanner 跳转到 Secondary 信道,接收 AUX_SYNC_IND
  4. AUX_SYNC_IND 中的 SyncInfo 包含周期广播的完整调度信息
  5. Scanner 用 SyncInfo 计算下一次 Periodic ADV 的时间和信道
  6. Scanner 在正确时间唤醒,接收 ADV_PERIODIC PDU

问题:步骤 1-4 需要持续扫描,功耗极高。对于 TWS 耳机这种电池容量极小的设备,几乎不可行。


三、三设备广播接收原理(核心)

这是本文的核心问题:怎样让第三台设备(C)收到广播者(A)的广播数据?

3.1 三种设备角色

|-----------------------|----------|---------------------------------------|
| 角色 | 设备 | 说明 |
| Broadcaster | Device A | 发送 Periodic Advertising 的广播者(如 TV、手机) |
| Scanner / PAST Sender | Device B | 已扫描并同步 A 的周期广播,负责转移同步信息(如手机) |
| PAST Receiver | Device C | 接收 B 转移的 SyncInfo,免扫描直接接收 A 的广播(如耳机) |

3.2 完整流程(7 步)

阶段一:B 同步 A(步骤 ①②)

  • ① B 扫描发现 A 的 ADV_EXT_IND → AUX_SYNC_IND,从中提取 SyncInfo
  • ② B 的 Controller 建立同步,生成 HCI_LE_Periodic Advertising Sync Established 事件,Host 获得 sync_handle

阶段二:B-C 建立 ACL 连接(步骤 ③)

  • ③ B 与 C 之间必须先有 BLE ACL 连接。PAST 转移的 LL_PERIODIC_SYNC_IND PDU 就走在这个连接上

阶段三:PAST 转移(步骤 ④⑤)

  • ④ B 的 Host 发送 HCI_LE_Periodic_Advertising_Sync_Transfer 命令 → B 的 Controller 在 ACL 连接上发送 LL_PERIODIC_SYNC_IND PDU → C 的 Controller 接收
  • ⑤ C 的 Controller 自动解析 PDU 中的 SyncInfo,建立与 A 的周期广播同步,生成 Sync Established 事件上报 Host

阶段四:C 直接接收 A 的广播(步骤 ⑥⑦)

  • ⑥ C 的 Controller 根据 SyncInfo,在正确的时间、正确的信道唤醒,直接接收 A 的 ADV_PERIODIC PDU------完全无需扫描
  • ⑦ C 从 Periodic Advertising 数据中读取 BIGInfo ,同步 BIG(Broadcast Isochronous Group),接收 BIS(Broadcast Isochronous Stream)音频/数据流

3.3 为什么 C 能直接接收?------原理拆解

这是理解 PAST 的关键。Periodic Advertising 本质上是一个确定性调度系统

复制代码
SyncInfo 提供的信息:
├── Offset     → "多久之后开始下一次广播"  → 解决 WHEN
├── Interval   → "每隔多久广播一次"        → 解决 PERIODICITY
├── Channel Map→ "用哪些 RF 信道"          → 解决 WHERE
├── Access Addr→ "广播的接入地址"          → 解决 FILTER
├── CRC Init   → "CRC 初始值"              → 解决 DECODE
└── Event Counter → "当前事件序号"         → 解决 CHANNEL HOPPING

有了这 6 个参数,C 的 Controller 能:

  1. 计算下一次广播的绝对时间:参考 ACL 连接的锚点 + Offset
  2. 计算跳频序列:用 Event Counter 和 Channel Map 推导下一次使用哪个信道
  3. 在目标时刻唤醒:Radio 直接调谐到目标信道
  4. 过滤和解码:用 Access Address 过滤,用 CRC Init 校验

类比:传统扫描像「不知道电视节目表,逐个频道翻找」;PAST 像「朋友直接把节目表和频道号给你,你到点打开就行」。

3.4 关键细节:PAST 只转移 SyncInfo,不转移 BIGInfo

一个常见误区:PAST 转移的是 Periodic Advertising 的同步信息,不是 BIGInfo。

  • PAST 转移后,C 可以直接接收 Periodic Advertising
  • 但 BIGInfo 在 Periodic Advertising 的数据载荷中
  • C 仍需接收至少一个 Periodic ADV PDU 才能获取 BIGInfo
  • 获取 BIGInfo 后,C 才能同步 BIG 并接收 BIS 数据

四、SyncInfo 结构详解

SyncInfo 是 PAST 的核心载荷,定义在 Core Spec Vol 6, Part B, Section 2.3.4.3:

|--------------------|---------|---------------------------------------|
| 字段 | 大小 | 说明 |
| Sync Packet Offset | 13 bits | 距参考点的时间偏移(30us 或 300us 单位) |
| Offset Units | 1 bit | 0 = 30us,1 = 300us |
| Offset Adjust | 1 bit | 若为 1,偏移量额外增加 2^13 × 30us |
| Interval | 12 bits | 广播间隔,单位 1.25ms(范围 7.5ms ~ 81.91875s) |
| Channel Map | 37 bits | bit n = 1 表示信道 n 被使用 |
| SCA | 3 bits | Sleep Clock Accuracy(发送方时钟精度等级) |
| Access Address | 32 bits | Periodic Advertising train 的接入地址 |
| CRC Init | 24 bits | CRC 初始值 |
| Event Counter | 16 bits | 当前周期广播事件计数器 |

Channel Hopping 计算

C 的 Controller 收到 SyncInfo 后,用以下公式计算下一个事件的信道:

复制代码
channelIndex = (EventCounter + 1) mod 37
// 如果 channelIndex 在 Channel Map 中被使用 → 使用该信道
// 否则 → 使用 Channel Map 中 >= channelIndex 的下一个可用信道

每次收到一个 ADV_PERIODIC,Event Counter 递增,C 据此计算下一次的信道。


五、PAST 协议详解

5.1 涉及的 HCI 命令

发送方(Device B):

|------------------------------------------------------------|-----------------------------------------------------|
| 命令 | 作用 |
| HCI_LE_Set_Periodic_Advertising_Sync_Transfer_Parameters | 配置 PAST 参数:skip(允许跳过的事件数)、sync_timeout(同步超时)、CTE 类型 |
| HCI_LE_Periodic_Advertising_Sync_Transfer | 执行转移:指定 conn_handle(到 C 的 ACL)和 sync_handle(要转移的同步) |

接收方(Device C):

|----------------------------------------------------------------|------------------------------------------------------------------|
| 命令 | 作用 |
| HCI_LE_Set_Periodic_Advertising_Sync_Transfer_Receive_Enable | 使能 PAST 接收:mode=1 使能,指定 conn_handle(到 B 的 ACL)、skip、sync_timeout |

生成的 HCI 事件:

|------------------------------------------------------|-------------------------------------------------|
| 事件 | 触发条件 |
| HCI_LE_Periodic_Advertising_Sync_Transfer_Received | C 的 Controller 收到 LL_PERIODIC_SYNC_IND 后上报 Host |
| HCI_LE_Periodic Advertising Sync Established | C 成功建立同步后上报,附带新的 sync_handle |

5.2 LL_PERIODIC_SYNC_IND PDU

这是 PAST 在 LL 层的实际传输载体,定义在 Core Spec Vol 6, Part B, Section 2.4.2.12。

复制代码
LL_PERIODIC_SYNC_IND PDU 结构:
┌──────────────────────┬──────────┬────────────────┬──────────────┬─────┬──────────────────┬─────────────┬───────────────┐
│ ID (1 byte)          │ Reserved │ SyncInfo       │ Channel Map  │ PHY │ Access Address   │ CRC Init    │ Event Counter │
│ (0x00 = Sync Transfer)│          │ (17 bytes)     │ (5 bytes)    │(1B) │ (4 bytes)        │ (3 bytes)   │ (2 bytes)     │
└──────────────────────┴──────────┴────────────────┴──────────────┴─────┴──────────────────┴─────────────┴───────────────┘

关键点

  • 这个 PDU 在 B-C 的 ACL 连接上以 LL Control PDU 形式发送
  • B 的 Controller 负责 PDU 构造和发送,Host 不需要参与 LL 层细节
  • C 的 Controller 负责解析 PDU 并自动建立同步

5.3 PAST 两种模式

|-------------------|-----------------------|---------------------------|
| 模式 | 说明 | 使用场景 |
| Sync Transfer | B 转移自己已有的 sync_handle | B 是扫描者,帮助 C 同步到 A |
| Set Info Transfer | B 转移自己的广播 Set 信息 | B 本身是广播者,直接告诉 C 自己的周期广播参数 |

Set Info Transfer 用 HCI_LE_Periodic_Advertising_Set_Info_Transfer 命令,适用于「手机既是广播者又想把广播转给耳机」的场景。


六、代码路径

6.1 BlueZ (Linux)

复制代码
内核态:
  net/bluetooth/hci_core.c     → HCI 命令发送框架
  net/bluetooth/hci_event.c    → LE Periodic Advertising Sync Established 事件处理
                                 LE Periodic Advertising Sync Transfer Received 事件处理
  net/bluetooth/hci_sync.c     → HCI 命令同步执行框架

用户态:
  src/shared/ad.c              → 广播数据解析
  src/shared/hci-cmd.c         → HCI 命令封装
  src/android/hal-hci.c        → HAL 层接口
  monitor/btmon.c              → HCI 日志监控工具

mgmt 接口:
  MGMT_OP_ADD_EXT_ADV_PARAMS   → 配置扩展广播
  // PAST 相关通过 mgmt 命令触发

关键调试 :用 btmon 抓 HCI log,搜索 LE Periodic Advertising Sync TransferLL_PERIODIC_SYNC_IND

6.2 Bluedroid (Android)

复制代码
system/bt/stack/hcic/
  hciblecmds.c                 → HCI_LE_Set_Periodic_Advertising_Sync_Transfer_Parameters
                                 HCI_LE_Periodic_Advertising_Sync_Transfer
                                 HCI_LE_Set_Periodic_Advertising_Sync_Transfer_Receive_Enable
  hcicmd.c                     → HCI 命令发送

system/bt/stack/btm/
  btm_ble_5_gap.c              → BLE 5.x GAP 接口
  btm_ble_api.c                → BTM_BlePeriodicAdvSyncTransfer 等应用层 API

system/bt/stack/btu/
  hcitask.c                    → HCI 任务调度,事件分发

system/bt/main/
  stack_config.c               → 协议栈配置

应用层:
  frameworks/base/core/java/android/bluetooth/
    BluetoothAdapter.java       → 公共 API 入口
    BluetoothLeBroadcastAssistant.java → LE Audio Broadcast Assistant(PAST 调用方)

七、实际应用场景

7.1 LE Audio 广播音频(最核心场景)

这是 PAST 存在的根本原因。

复制代码
场景:机场候机厅广播音频

Device A = 机场广播发射器(发送 Periodic ADV + BIG + BIS 音频流)
Device B = 乘客手机(Broadcast Assistant,扫描发现 A)
Device C = 乘客 TWS 耳机(Broadcast Sink,接收音频)

流程:
1. 手机扫描发现机场广播的 Periodic ADV
2. 手机同步 Periodic ADV,读取 BIGInfo
3. 手机通过 BASS(Broadcast Audio Scan Service)写入耳机的 BASS Characteristic
4. 手机通过 PAST 将 SyncInfo 转移给左耳
5. 手机通过 PAST 将 SyncInfo 转移给右耳
6. 左右耳直接接收 A 的 BIS 音频流,无需扫描

为什么耳机不能自己扫描?

  • TWS 耳机电池通常 40-60mAh,持续扫描会耗尽电量
  • 扫描占空比可能需要 10-30%,PAST 方式仅需在 Periodic ADV 时刻唤醒(<0.1%)
  • 耳机的天线和 Radio 性能通常弱于手机

7.2 电子货架标签(ESL)

复制代码
Device A = ESL 网关(广播价格更新数据)
Device B = 手机 App(管理标签,扫描发现 A)
Device C = 电子货架标签(通过 PAST 接收更新数据)

优势:标签平时深度睡眠,仅在 PAST 转移后唤醒接收,电池寿命可达数年

7.3 传感器数据广播

复制代码
Device A = 环境传感器(周期广播温湿度数据)
Device B = 网关(已同步 A)
Device C = 新加入的显示设备(通过 PAST 快速同步)

优势:新设备无需扫描即可加入数据接收,部署灵活

八、调试技巧

8.1 用 btmon 抓 PAST 流程

复制代码
# 抓取 HCI 日志
sudo btmon -w past_debug.log

# 过滤 PAST 相关命令和事件
btmon -r past_debug.log | grep -E "Periodic|Sync Transfer|PERIODIC_SYNC"

关键日志标识:

  • > HCI_LE_Periodic_Advertising_Sync_Transfer → B 发起转移
  • < HCI_LE_Periodic Advertising Sync Established → C 成功同步
  • LL_PERIODIC_SYNC_IND → LL 层 PDU 传输

8.2 常见问题排查

|---------------------------|-----------------|-----------------------------------------------------------------|
| 问题 | 可能原因 | 排查方法 |
| C 收不到 PAST | B-C 之间没有 ACL 连接 | 检查连接状态,hcitool leacl 确认 |
| C 同步建立后立即丢失 | sync_timeout 太短 | 检查 Set_Periodic_ADV_Sync_Transfer_Receive_Enable 的 timeout 参数 |
| C 同步成功但收不到 ADV_PERIODIC | A 已停止广播 | 确认 A 仍在发送 Periodic ADV |
| SyncInfo Offset 计算错误 | ACL 锚点参考不正确 | 检查 LL_PERIODIC_SYNC_IND 的发送时间点 |
| C 的 Event Counter 与 A 不同步 | PAST 转移时延迟过大 | 检查 ACL 连接的 latency 和 timeout |

8.3 PTS 测试

PAST 相关的 PTS 测试用例:

  • PAST/SR/BI-01-C:Sync Transfer 基本流程
  • PAST/SR/BI-02-C:Set Info Transfer 流程
  • PAST/SR/BI-03-C:PAST 参数配置
  • PAST/CG/BI-01-C:Controller 在 ACL 上发送 LL_PERIODIC_SYNC_IND

九、自研协议栈实现要点

对于你团队自研蓝牙协议栈 Host,PAST 实现需要关注:

9.1 Host 层职责

复制代码
Host 需要实现的:
├── HCI 命令封装和发送
│   ├── LE_Set_Periodic_ADV_Sync_Transfer_Parameters
│   ├── LE_Periodic_ADV_Sync_Transfer
│   ├── LE_Set_Periodic_ADV_Sync_Transfer_Receive_Enable
│   └── LE_Periodic_ADV_Set_Info_Transfer
├── HCI 事件处理
│   ├── Periodic_Advertising_Sync_Transfer_Received
│   └── Periodic_Advertising_Sync_Established
├── sync_handle 管理
│   ├── 维护 sync_handle → 广播源映射表
│   └── PAST 转移后 C 侧生成新 sync_handle
└── 上层接口(GATT BASS / 应用层 API)

Host 不需要实现的 (Controller 负责):
├── LL_PERIODIC_SYNC_IND PDU 构造和解析
├── SyncInfo 中 Offset 的精确时间计算
├── Channel Hopping 算法
└── Radio 调度(何时唤醒、调谐到哪个信道)

9.2 关键实现细节

  1. sync_handle 生命周期管理:PAST 转移后,B 侧的 sync_handle 仍然有效(B 继续同步),C 侧生成一个新的 sync_handle。两者独立,互不影响。
  2. skip 和 timeout 参数
    • skip:允许 C 连续错过多少个 Periodic ADV 事件而不丢失同步
    • sync_timeout:超过此时间未收到任何 ADV_PERIODIC 则同步丢失(范围 10ms~163.84s)
    • 建议初始值:skip = 0,sync_timeout = 1000ms(根据实际广播间隔调整)
  1. Service Data 字段HCI_LE_Periodic_Advertising_Sync_Transfer 中的 16-bit Service Data 由 B 的 Host 设置,C 的 Host 通过 Sync_Transfer_Received 事件接收。可携带应用层元数据(如广播源 ID)。
  2. 与 BASS 的联动:在 LE Audio 场景中,PAST 通常由 BASS(Broadcast Audio Scan Service)触发。B 的 Host 写入 C 的 BASS Add Source Characteristic 后,自动触发 PAST 流程。

十、总结

|--------|------------|----------------|
| 维度 | 传统扫描同步 | PAST 转移同步 |
| 功耗 | 高(持续扫描) | 极低(仅目标时刻唤醒) |
| 发现时间 | 数百ms~数秒 | 即时(一次 ACL PDU) |
| 可靠性 | 依赖无线扫描 | ACL 可靠传输 |
| 适用设备 | 手机、网关 | 耳机、标签、传感器 |
| 蓝牙版本 | 5.0+ | 5.0+ |
| 依赖条件 | 无 | B-C 间有 ACL 连接 |

PAST 的本质是:把「发现」和「接收」解耦。B 负责「发现」(扫描),C 负责「接收」(直接听)。中间通过 ACL 连接把同步信息可靠地传递过去。

对于你团队的三个工作板块:

  • 产测陪测:PAST 测试用例是产线必测项(LE Audio 模组)
  • Bringup:BlueZ/Bluedroid 的 PAST 流程调试是客户常见问题
  • 自研协议栈:PAST 的 Host 层实现相对简单(HCI 命令+事件管理),但 Controller 侧的 SyncInfo 时间计算是难点

参考文档:Bluetooth Core Specification v5.4, Vol 6, Part B, Section 4.4.5 (PAST), Section 2.4.2.12 (LL_PERIODIC_SYNC_IND)