【LMP】规范精讲[11]: 暗房里的协议——产线射频测试是怎么指挥芯片的

一颗蓝牙芯片出厂前要在测试仪上过五关:发射功率、调制谱、初始 载波 、 跳频 特性、 接收灵敏度。测试仪凭什么能让一块毫无用户界面的芯片乖乖按指定图案、指定频率、指定包型发射?答案就藏在链路管理层的最后一块拼图里------测试模式。它像一间暗房:平时门锁得死死的,产线或认证实验室先用本地手段开锁,然后测试仪通过空口下达指令,芯片终止一切正常业务,变成一台听话的信号发生器或回声机。这一篇把暗房的开门、门禁、内部三间房(发射、回环、暂停)讲清楚,最后用抓包日志看看与它同源的功率控制在正常模式下的样子。


目录

一、设计哲学:给测试仪开的后门,给黑客关的大门

二、激活与退出:两道门与两条退路

三、暗房里的生存法则:控制命令与白名单

[四、控制 PDU 的解剖:场景、跳频、频率、功率、轮询、包型、长度](#四、控制 PDU 的解剖:场景、跳频、频率、功率、轮询、包型、长度)

五、暗房里的三个房间

[5.1 房间一:发射测试](#5.1 房间一:发射测试)

[5.2 房间二:回环测试](#5.2 房间二:回环测试)

[5.3 房间三:暂停测试](#5.3 房间三:暂停测试)

六、抓包:白名单命令在正常世界的样子

七、收个尾

八、测验


一、设计哲学:给测试仪开的后门,给黑客关的大门

规范开宗明义:链路管理协议提供一组 PDU 用于测试蓝牙射频和基带。测试模式有两种激活途径------本地激活(硬件或软件接口)和空口激活。空口激活有一条铁律,规范值得整段读:

For activation over the air interface, entering the test mode shall be locally enabled for security and type approval reasons. The implementation of this local enabling is not subject to standardization.

出于安全和型号核准的原因,空口进入测试模式必须先在本地使能,而本地使能的实现方式不做标准化。这句话背后是深刻的安全考量。测试模式下的设备会停用一切正常功能,只按测试仪的指令发射------如果攻击者能通过空口随意把你的耳机、手机、手表拽进测试模式,等于随时能让设备瘫痪,甚至指挥它在不合规的功率和频率上发射,规避监管。所以规范把钥匙留在本地:产线上通过治具触点或产测软件开锁,这把锁长什么样每个厂商自己定,规范不管,但锁必须存在。

测试支持篇里还有一句更狠的补充:处于测试模式的设备不应支持正常操作,出于安全原因,测试模式的设计原则是对用户毫无益处------不允许任何硬件或软件接口的数据输出或输入。暗房就是暗房,进去之后跟外界的数据通道全部切断,只能被测试仪指挥。

二、激活与退出:两道门与两条退路

整个激活流程只有一对消息。测试仪(永远扮演中央)向被测设备(永远扮演外设,规范称 IUT)发送 LMP_TEST_ACTIVATE,链路管理器必须能在任何时刻接收这条消息。设备的回应取决于那把本地锁:

本地已使能------回 LMP_ACCEPTED,进入测试模式;本地未使能------回 LMP_NOT_ACCEPTED,继续正常工作,错误码固定为 LMP PDU Not Allowed(0x24)。

进入之前有一条前置义务:被测设备应终止所有正常操作再进入测试模式。而在与测试仪建立连接之前,设备要执行寻呼扫描和查询扫描(推荐扩展扫描活动),让自己能被测试仪找到------毕竟芯片还没跟测试仪配过对,得先处于可被寻呼的状态。本地激活的路径同理,也要先终止一切正常操作。

退出有两条路,语义不同。第一条:测试仪发 LMP_TEST_CONTROL 并把测试场景设为 exit test mode,被测设备退出测试模式、回到正常工作,但连接还在,可以继续做别的;第二条:直接发 LMP_DETACH,测试模式和连接一起结束,设备掉电或回到待机。测试支持篇补了一个细节:离开测试模式后设备进入待机态,断电后也必须回到待机态------保证下次开机是干净状态,不会把暗房状态带到用户手里。

三、暗房里的生存法则:控制命令与白名单

进入测试模式后,规范给设备立了三条规矩。

第一条,控制命令只认测试模式。LMP_TEST_CONTROL 用于启动具体测试,测试模式下收到回 LMP_ACCEPTED;不在测试模式收到则回 LMP_NOT_ACCEPTED,错误码同样是 0x24。

第二条,屏蔽一切无关命令。规范是:

A Bluetooth device in test mode shall ignore all LMP commands not related to control of the test mode.

处于测试模式的蓝牙设备应忽略所有与测试控制无关的链路管理命令。暗房里不谈正常业务,免得普通流程干扰测量。

第三条是例外白名单,这句最有信息量:

LMP commands dealing with power control and the request for LMP features (LMP_FEATURES_REQ), and adaptive frequency hopping (LMP_SET_AFH, LMP_CHANNEL_CLASSIFICATION_REQ and LMP_CHANNEL_CLASSIFICATION) are allowed in test mode; the normal procedures are also used to test the adaptive power control.

功率控制、特性请求、自适应跳频三类命令在测试模式照常有效,而且测试自适应功率控制本身就沿用正常流程。为什么留这三个活口?因为发射功率和跳频恰恰是射频测试的核心被测对象------测试仪要指挥设备升降功率、要设置信道图才能完成功率控制和跳频特性的测量,把这两类命令禁了,暗房里的仪器就没法干活了。特性请求则用于确认设备身份和能力。这个白名单设计是理解测试模式与正常模式关系的钥匙,后面抓包部分还会回到它。

四、控制 PDU 的解剖:场景、跳频、频率、功率、 轮询 、包型、长度

LMP_TEST_CONTROL 的参数表是整个测试模式最核心的数据结构,一共八个字段。

Test_Scenario 一字节定义测试场景:0 暂停测试、1 到 4 是发射测试的四种图案(全 0、全 1、1010 交替、伪随机序列)、5 和 6 是 ACL 与同步包回环、7 和 8 是无白化版本的回环、9 是 1111 0000 交替图案、255 退出测试模式、10 到 254 保留。Hopping_Mode 只有两种取值:0 单频收发、1 正常跳频。Tx_Frequency 和 Rx_Frequency 直接以信道号 k 编码,频率等于 2402 加 k 兆赫兹。Power_Mode 区分固定发射功率(0)和自适应功率控制(1)。Poll_Period 以 1.25 毫秒为单位。Packet_Type 最讲究:低四位沿用包头里的类型编号(同一套编号体系),高四位区分大类------0 表示 ACL 或 SCO、1 表示 eSCO、2 表示 EDR 版 ACL、3 表示 EDR 版 eSCO。Test_Data_Length 两字节,等于用户数据长度,不含载荷头和 CRC。

表尾还有一行极容易被略过但极其精彩的注释,规范:

To ensure that the contents of the LMP_TEST_CONTROL PDU are suitably whitened (important when sent in transmitter mode), all parameters listed in Table 4.37 are XORed with 0x55 before being sent.

为确保控制 PDU 的内容得到适当白化(在发射模式下发送时尤为重要),所有参数发送前与 0x55 异或。这句话为什么重要?回忆发射测试的设定:设备要以恒定比特图案反复发射,且白化功能是关闭的(后面详述)。可 LMP_TEST_CONTROL 本身是一个要在空口传输的正常包,如果它的参数原样发送,全 0 场景号的载荷就是一串零------数据全零在射频上意味着直流、意味着测量仪器看到的是畸变的调制谱。把参数全部异或 0x55 后,哪怕逻辑值是全 0,线上也是 0x55 的翻转图案,0 与 1 各占一半,白化器(哪怕关着)等效地获得了均衡的比特分布。一个字节的异或,解决了恒定图案下控制信道自身的可传输性问题,这是协议设计里以简驭繁的典范。Test_Data_Length 是双字节,所以异或 0x5555。

参数取值还有一张限制表:发射测试时 Tx 与 Rx 频率必须相同且 0 到 78;回环测试收发频率各自独立取 0 到 78;回环时 Poll_Period 不适用置 0;ACL 和 SCO 包的回环测试长度字段同样置 0,eSCO 包则按基带规范的包长表取值。包长上限由附录的包型总表约束------ACL 家族从 DM1 的 17 字节一路到 3-DH5 的 1021 字节,同步家族从 HV3 的 30 字节到 3-EV5 的 540 字节,测试长度必须在对应包型的合法范围内选。

用代码把参数编码和白化解码串起来会更直观:

复制代码
def encode_test_control(scenario, hop_mode, tx_freq, rx_freq,
                        power_mode, poll_period, pkt_type, data_len):
    # 发送方向:所有字段与 0x55 异或(双字节字段与 0x5555)
    payload = bytes([
        scenario   ^ 0x55,
        hop_mode   ^ 0x55,
        tx_freq    ^ 0x55,
        rx_freq    ^ 0x55,
        power_mode ^ 0x55,
        poll_period ^ 0x55,
        pkt_type   ^ 0x55,
    ])
    payload += (data_len ^ 0x5555).to_bytes(2, "little")
    return payload

def decode(pkt):
    # 解码即再异或一次,异或自逆
    s = pkt[0] ^ 0x55
    return {"scenario": s, "hopping": pkt[1] ^ 0x55,
            "tx_freq_mhz": 2402 + (pkt[2] ^ 0x55)}

# 例:发射测试·1010图案·单频·信道0·固定功率·DH1包
p = encode_test_control(scenario=3, hop_mode=0, tx_freq=0, rx_freq=0,
                        power_mode=0, poll_period=1, pkt_type=0x02, data_len=27)
print(p.hex(" "))   # 线上载荷:56 55 55 55 55 50 57 22 55

注意解码输出的十六进制串里大量 55------逻辑上的零参数在线上全部变成了 55,这正是白化的效果。

五、暗房里的三个房间

链路管理规范对测试模式只写了激活与控制的骨架,血肉全在测试支持篇里。逐一过一遍。

5.1 房间一:发射测试

测试架构本身很直白:测试仪与被测设备组成一个微微网,测试仪当中央、掌控全部流程,控制指令走空口链路管理命令,测量设备(频谱仪、功率计)作为可选角色挂在旁边。被测设备与测试仪之间的数据通道只有空气,本地接口全部封死。

发射测试的运作是严格的问答制。测试仪在中央发槽发 POLL 包,被测设备在紧随其后的外设发槽发射测试包------恒定图案、同一测试包无限重复、与微微网外设发射时序对齐。测试仪的轮询间隔由控制 PDU 的 Poll_Period 字段决定。有个宽限:就算没收到测试仪的包,被测设备也可以按正常时序发自己的突发,只是 ARQN 位必须设为 NAK 表明没收到东西。突发长度可以超过单槽包,此时测试仪就用下一个空闲的中央发槽继续轮询。

测试包就是正常蓝牙包,载荷换成测试图案,并且只应使用无前向纠错的包型------HV3、EV3、EV5、DH1、DH3、DH5 及其 EDR 版本再加 AUX1。道理很简单:FEC 会改变原始比特图案,测出来的调制谱就不纯了。

伪随机图案用 PRBS9 序列:九级线性反馈移位寄存器,第五级和第九级的输出异或后反馈到第一级输入,移位寄存器初始化为九个一,序列周期 2 的 9 次方减 1 即 511 比特,最长连零 8 个。生成器代码不到十行:

复制代码
def prbs9(nbits):
    # 9级LFSR,第5、9级异或反馈,初值全1
    reg = 0b111111111
    out = []
    for _ in range(nbits):
        fb = ((reg >> 4) ^ (reg >> 8)) & 1   # 第5级 与 第9级 异或
        out.append(reg & 1)
        reg = (reg >> 1) | (fb << 8)
    return out

seq = prbs9(511)
print("周期:", 511, "最长连零:", max(len(s) for s in "".join(map(str, seq)).split("1")))

白化的开关时序图是这个房间里最值得细看的部分:测试仪下发进入发射测试的控制命令(此时白化还开着),被测设备回 LMP_ACCEPTED 后白化关闭,此后所有测试包都是不白化的裸图案;退出时反向再来一遍。规范还专门叮嘱实现者:LMP_ACCEPTED 的重传必须沿用与首次发送相同的白化状态------确认包自己不能在白化语义上跳变。

频率切换的生效时机藏着一套双保险防失步协议。测试仪收到 LMP_ACCEPTED 后,必须继续发至少 8 个时槽(4 次传输)携带 ACK 的 POLL 包,然后才切换到新的跳频和白化设置;被测设备发完 ACCEPTED 后要等链路控制层对 ACCEPTED 的确认,收到后才切换。也就是说双方各自确认对方已经收到自己的确认后才动频率------任何一方贸然先跳,另一方还在旧频率上等待,链路立刻失锁,而且规范直言这种失步无法恢复(丢掉 ACCEPTED 最终必然导致跳频同步丢失),只能重来。改频率是射频测试里最频繁的操作,这一小段握手规则是整个测试流程稳定性的基石。

跳频自适应的测试衔接也写得很细:只有跳频模式设为正常跳频(79 信道)时才允许 AFH,进入测试模式前已启用的 AFH 沿用原参数,信道分类上报状态在进出测试模式时保持,测试模式下仍可被测试仪的信道分类命令和主机侧的评估模式命令改变。

5.2 房间二:回环测试

回环模式让被测设备变成一面镜子:接收测试仪发来的正常基带包,解码后用同样的包型把载荷原样发回去。发送时机有两种:紧跟在测试仪发包之后的那个外设发槽立即回环,或者延迟一轮、在测试仪下一次发射之后的外设发槽再回。没有信令协商用哪种,设备行为固定或由其他手段调整,不许随机变。

回环的包处理规则一张流程图说尽,几条关键分支值得逐条看。同步字都没检测到------不回,装死。包头 HEC 校验失败------回一个 ARQN 为 NAK 的空包,或者干脆不回。收到测试控制相关的链路管理命令------执行命令、按正常流程回 ACK 或 NAK,但包本身不回环;其他链路管理命令一律忽略、不回包。载荷里的 FEC 解码后要重新编码再发------这恰好测了前向纠错的编解码通路;如果测试仪想测纯粹误码率,就选无 FEC 的包型。CRC 校验失败要回 NAK,但载荷照样原样回环,且回包的 CRC 一律重新计算------不管收到时对错,发回去的必须是自洽的包。还有一条防错设计:如果带 CRC 和载荷头的包 CRC 失败,就按(可能出错的)载荷头指示的字节数回环------错了也按错的数据长度回,测试仪那边自然能对出问题。

5.3 房间三:暂停测试

暂停测试是房间之间的中转站:从发射或回环状态收到场景号为 0 的控制命令,被测设备停止当前测试进入暂停。发射测试下暂停意味着不再发任何包,但对 POLL 包要正常回应(回空包),对允许的链路管理命令也正常应答。还有两条贴心的细则:暂停时控制 PDU 的其他字段全部忽略,跳频方案和白化状态不因暂停而改变。暂停的意义在于测试流程的编排------测完发射功率想接着测灵敏度,先暂停、换参数、再启动,不用退出测试模式重新激活。

六、抓包:白名单命令在正常世界的样子

翻遍手里两份正常的连接日志,LMP_TEST_ACTIVATE 和 LMP_TEST_CONTROL 一条都没有------这正是安全设计的自证:本地使能那道门不开,空口的激活指令永远只会收到 0x24 拒绝,正常产品的日志里根本不该出现这对 PDU。反过来,白名单里的三类命令在正常模式下天天上班,抓包里样样齐全,而且工作方式与测试模式的规定同源。

先看功率控制。在音乐播放日志里,链路建立六秒后外设先发了一条加到最大功率的请求,随后中央根据链路质量开始精细调价:连续两条降一步的指令、再连续两条升一步的指令,每条指令的结果都如实回报------降两步用了两条 PDU,升两步也用了两条 PDU,一步不多一步不少。

对照测试支持篇对功率控制测试的规定:被测设备从最大功率起步,每收到一条功率请求 PDU 就升降一步。正常模式和测试模式执行的是同一套步进机制,测试模式只是把正常流程拿来当被测对象------这就是白名单设计里那句 normal procedures are also used to test 的含义。抓包里那条从设备请求中央加到最大功率的消息也很讲究:链路刚建立、远端信号质量未知,先把对端拉满功率保证建链稳定,再逐步下调省电,这是真实产品里功率控制最常见的开场动作。

再看跳频自适应。通话日志里,建链时外设先收到信道分类请求(上报本端信道评估能力),中央随即下发信道图。此后通话的二十多秒里,信道图持续更新:可用信道数从 32 一路放宽到 76------环境干扰退去,信道逐批归还。

测试支持篇规定测 AFH 时沿用正常 LMP 流程、信道分类状态跨测试模式保持。这份日志展示的正是那套正常流程的全部要素:分类上报、信道图下发、周期性更新。也就是说,暗房里测跳频特性时,测试仪和被测设备之间跑的就是图里这些消息,一模一样。

七、收个尾

测试模式在整个链路管理协议里是个特殊的存在:前面十篇讲的所有流程------加密、配对、嗅探、语音专线------都是为了用户业务服务,唯独它是为测试仪服务的。设计上三件套环环相扣:本地使能的门禁挡住未授权激活;白名单保留功率控制与跳频这两类与射频测量直接相关的命令;发射、回环、暂停三个房间覆盖了射频一致性测试的全部场景。对做芯片和产测的工程师,这套机制是每天打交道的工具;对做应用和协议的工程师,理解它的意义在于反方向------知道正常日志里不该出现什么,出现就是异常,而白名单命令的正常样貌又长什么样,不会误判。协议读到这里,链路管理层的正篇就完整了。

八、测验

问题一:蓝牙设备通过空口激活测试模式有什么安全前提?被测设备拒绝时的错误码是什么?测试模式下哪些常规链路管理命令仍然有效?

参考答案:

空口激活前必须在本地(硬件或软件接口)使能测试模式,且本地使能的实现不受标准化约束------这是规范出于安全和型号核准原因的强制要求,防止攻击者远程把设备拖入停服状态或指挥其违规发射。设备未使能时对 LMP_TEST_ACTIVATE 回 LMP_NOT_ACCEPTED,错误码为 LMP PDU Not Allowed(0x24);对不在测试模式时收到的 LMP_TEST_CONTROL 同样回 0x24。测试模式下设备忽略所有与测试控制无关的链路管理命令,但有三类例外:功率控制类(LMP_INCR_POWER_REQ、LMP_DECR_POWER_REQ 等)、特性请求(LMP_FEATURES_REQ)、自适应跳频类(LMP_SET_AFH、LMP_CHANNEL_CLASSIFICATION_REQ、LMP_CHANNEL_CLASSIFICATION)。保留它们的原因是功率和跳频正是射频测试的被测对象,且测试规范明确自适应功率控制的测试沿用正常流程。

问题二:LMP_TEST_CONTROL 的所有参数为什么发送前要与 0x55 异或?这个设计解决了什么问题?

参考答案:

发射测试模式下设备的白化功能是关闭的,测试载荷是恒定比特图案。如果控制 PDU 的参数原样发送,逻辑值为零的字段(比如单频测试的频率 0、场景参数的低位)在线上就是一串全零比特,全零数据在射频上表现为直流分量,破坏调制的随机性要求,也会干扰测量。将所有参数与 0x55 异或后,逻辑零在线上呈现为 0x55(0 与 1 各半)的均衡图案,等效实现了对控制内容的白化,保证控制 PDU 自身在关闭白化的发射测试环境下仍能可靠传输且不影响测量。双字节字段 Test_Data_Length 与 0x5555 异或同理。接收端再异或一次即可恢复(异或自逆)。这个设计的精妙在于用一字节的固定开销解决了恒定图案环境的自传输问题,无需引入独立的白化开关状态。

问题三:发射测试中从单频切换到跳频(或反向)时,测试仪和被测设备各自如何确认切换时机?为什么说贸然切换会导致不可恢复的失步?

参考答案:

切换生效遵循双重确认规则。测试仪一侧:收到被测设备的 LMP_ACCEPTED 后,必须继续以原设置发送至少 8 个时槽(4 次传输)携带 ACK 的 POLL 包,确认对方已收到自己的确认后才切换到新的跳频和白化设置。被测设备一侧:发送 ACCEPTED 后等待链路控制层对该 ACCEPTED 的 ACK,收到后才切换。双方各自确认对方收到确认才动频率,本质上是把切换点锚定在一个双方都观测到的空口事件上。如果任何一方提前切换:比如测试仪已跳到新跳频序列而设备还在旧频率上等 POLL,或设备已切而测试仪还在旧频率发 POLL,双方从此在不同跳频序列上互相等待,蓝牙跳频序列由时钟和地址决定,双方失去对当前频率的共识后无法自行恢复重同步,规范明确指出这种频率同步丢失不可恢复,只能断链重来。这也是正常操作中跳频图案变更(如 AFH 信道图更新)要走完整 LMP 确认流程的同一逻辑。


相关推荐
芯片人0072 小时前
GEK100系列芯片进入上市公司上海移远通信供应链
人工智能·单片机·嵌入式硬件·物联网·芯片
热文新讯16 小时前
迎进博·话疗愈:2026酒店“疗愈睡眠”闭门研讨会在沪举行
大数据·人工智能·物联网
数字新视界18 小时前
机房动环监控系统助力数据中心高效能管理与安全保障
物联网·数据可视化·数据中心基础设施管理·dcim管理系统·数据中心dcim
数字新视界1 天前
数字孪生技术赋能智能化转型与创新实践
嵌入式硬件·物联网·系统架构·机房管理·动力与环境监控系统
注塑机数据采集联网1 天前
数据采集网关入门:ZK-D1/D3从零开始构建你的数据运用
大数据·数据仓库·人工智能·物联网·数据库架构·注塑机网关
硅基手札1 天前
CAN 技术系列 08 · CAN 控制器寄存器与 IP 架构
驱动开发·架构·嵌入式开发·通信协议·can总线
硅基手札1 天前
CAN 技术系列 09 · CAN 传输模式:轮询 / 中断 / DMA
驱动开发·bsp·嵌入式开发·通信协议·can总线
智购科技智能售货柜1 天前
顾客已经关门,视觉售货柜还在处理旧画面:延迟积压怎么查?~YH
python·单片机·嵌入式硬件·物联网·eclipse
microrain1 天前
跟着一条属性报文走一遍 SagooIoT 的接入链路
物联网·架构·golang·sagooiot