試實(shí)戰(zhàn):用邏輯分析儀抓取CC線(xiàn)波形與BMC解碼全流程)
這標(biāo)題一看就知道是懂行的朋友出的。做USB PD相關(guān)的開(kāi)發(fā)或者調(diào)試最頭疼的就是用戶(hù)態(tài)看著沒(méi)問(wèn)題物理層全是問(wèn)號(hào)。寄存器里的狀態(tài)、日志里的報(bào)錯(cuò)終究是別人嚼過(guò)的信息真到了充電協(xié)商失敗、快充握手異常這種場(chǎng)景少了邏輯分析儀抓CC線(xiàn)上的原始波形你根本不知道問(wèn)題出在哪兒。這篇文章我就把整套流程拆開(kāi)講從怎么接線(xiàn)、設(shè)置采樣率到BMC解碼原理再到怎么把一段裸波形還原成可讀的PD報(bào)文全部走一遍。不管你是剛接觸USB PD的嵌入式新人還是被PD快充問(wèn)題折磨過(guò)的老工程師按這個(gè)思路去抓一次包很多之前只能靠猜的問(wèn)題都會(huì)直接現(xiàn)出原形。1. 為什么抓USB PD波形從寄存器猜謎到眼見(jiàn)為實(shí)1.1 靠日志和寄存器排查PD協(xié)議問(wèn)題的真實(shí)痛點(diǎn)USB PD協(xié)議協(xié)商不是一次簡(jiǎn)單的高低電平交互而是一個(gè)帶狀態(tài)機(jī)的完整通信過(guò)程。源端比如充電器和受電端比如手機(jī)、筆記本電腦需要先在CC線(xiàn)上建立連接然后通過(guò)交換Source_Capabilities、Request、Accept、PS_RDY等一系列消息才能在電壓、電流檔位上達(dá)成一致。這個(gè)過(guò)程是毫秒級(jí)完成的而且失敗之后設(shè)備往往會(huì)反復(fù)重試。我見(jiàn)過(guò)很多同事排查快充問(wèn)題的方式先看設(shè)備側(cè)日志再讀芯片的PD寄存器確認(rèn)收到幾條消息、發(fā)了幾個(gè)ACK??雌饋?lái)邏輯鏈路是通的但充電速度就是不達(dá)標(biāo)或者握手成功率只有30%。這類(lèi)問(wèn)題的根源往往不在軟件而是在物理層——CC線(xiàn)上的信號(hào)跳變沿不夠陡、電平抖動(dòng)、毛刺導(dǎo)致BMC解碼誤碼或者SOP同步模式丟了接收端根本沒(méi)把消息正確收進(jìn)來(lái)。這種時(shí)候你去看寄存器它只會(huì)告訴你沒(méi)收到有效消息但不會(huì)告訴你為什么沒(méi)收到。只有把CC線(xiàn)上的波形抓下來(lái)一比特一比特地看才能真正定位問(wèn)題。這也是為什么邏輯分析儀在PD調(diào)試?yán)锊皇强蛇x項(xiàng)而是剛需。1.2 為什么用邏輯分析儀而不是示波器很多人的第一反應(yīng)是用示波器去抓CC線(xiàn)。示波器確實(shí)能看電壓幅度、上升沿時(shí)間這些是邏輯分析儀做不到的。但在USB PD協(xié)議調(diào)試這個(gè)場(chǎng)景里邏輯分析儀有它不可替代的優(yōu)勢(shì)。首先是通道數(shù)和存儲(chǔ)深度。一個(gè)PD協(xié)商過(guò)程可能包含十幾次消息交互如果只抓十幾微秒的波形根本不夠用你需要連續(xù)采集幾十毫秒甚至幾百毫秒的數(shù)據(jù)。示波器的存儲(chǔ)深度在這個(gè)量級(jí)下往往比較緊張而邏輯分析儀的深存儲(chǔ)可以輕松記錄幾秒到幾十秒的波形還能事后慢慢回放。其次是解碼能力。USB PD的物理層編碼是BMC如果靠人工對(duì)著示波器波形去解BMC那效率低得可怕。主流的邏輯分析儀軟件比如Saleae Logic或者PulseView都支持協(xié)議解碼功能。有些直接內(nèi)置USB PD解碼器選好通道就能把原始波形變成一幀一幀的消息節(jié)省大量時(shí)間。另外價(jià)格也是一個(gè)現(xiàn)實(shí)考量。入門(mén)級(jí)的邏輯分析儀幾百塊就能買(mǎi)到采樣率20MHz以上協(xié)議解碼夠用。示波器要想達(dá)到同樣的解碼體驗(yàn)得上高端混合信號(hào)示波器價(jià)格完全不在一個(gè)量級(jí)。為了更直觀我把兩者的適用場(chǎng)景放一起對(duì)比一下對(duì)比維度邏輯分析儀示波器核心能力多通道、深存儲(chǔ)、協(xié)議解碼高精度電壓測(cè)量、時(shí)序測(cè)量USB PD解碼軟件內(nèi)置/腳本解碼方便需要高端型號(hào)或后續(xù)處理長(zhǎng)時(shí)間抓包輕松記錄秒級(jí)波形存儲(chǔ)深度受限通道數(shù)8/16通道常見(jiàn)通常2/4通道價(jià)格百元到幾千元專(zhuān)業(yè)級(jí)上萬(wàn)元起步實(shí)際開(kāi)發(fā)中我基本都是邏輯分析儀先上手確認(rèn)協(xié)議層正常后如果懷疑信號(hào)完整性再上示波器看具體電壓幅值、上升沿。1.3 邏輯分析儀選型參考手頭設(shè)備怎么挑如果你還沒(méi)入手邏輯分析儀我給幾個(gè)選型建議。我自己用過(guò)Saleae Logic 8和國(guó)產(chǎn)的Kingst LA5016也試過(guò)用PulseView搭配便宜硬件各有各的適用場(chǎng)景。如果你主要做USB PD、I2C、SPI、UART這類(lèi)協(xié)議調(diào)試采樣率至少要保證20MHz以上。前面會(huì)詳細(xì)算這個(gè)數(shù)值的來(lái)由這里先給結(jié)論USB PD的BMC編碼最小脈沖寬度大約是1.67微秒20MHz采樣率相當(dāng)于每個(gè)最小脈沖至少采30多個(gè)點(diǎn)解碼軟件才有足夠的分辨率去恢復(fù)比特流。在軟件層面Saleae Logic自帶的USB PD協(xié)議解析器是非常好用的選好CC通道就能自動(dòng)識(shí)別SOP、消息類(lèi)型和內(nèi)容。PulseView作為開(kāi)源方案雖然內(nèi)置的USB PD解碼器不如Saleae完善但配合Python腳本處理導(dǎo)出數(shù)據(jù)一樣能完成分析而且它對(duì)硬件的要求更低一些幾十塊錢(qián)的開(kāi)發(fā)板就能變成采集設(shè)備??紤]到很多讀者接觸的第一臺(tái)邏輯分析儀就是PulseView兼容設(shè)備后面我會(huì)把手工解碼腳本解碼這條路也講透這樣即使你的設(shè)備沒(méi)有內(nèi)置PD解碼器也完全不影響實(shí)操。另外還有一點(diǎn)容易被忽略邏輯分析儀的探頭和線(xiàn)材質(zhì)量很重要。USB PD的CC線(xiàn)信號(hào)幅度并不大大概在0.25V到2V之間擺動(dòng)如果探頭線(xiàn)材阻抗不穩(wěn)定、接觸不良抓出來(lái)的波形會(huì)慘不忍睹。盡量選擇原裝探頭或者屏蔽良好的測(cè)試線(xiàn)別在這個(gè)地方省錢(qián)。2. 抓包前必須吃透的基礎(chǔ)CC通道與BMC編碼原理2.1 USB PD的物理通道CC1與CC2為什么信號(hào)是這樣跳的USB PD和普通USB一個(gè)很大的不同是它多了一根用于通信的Configuration Channel線(xiàn)。Type-C接口里有兩根這樣的線(xiàn)分別叫CC1和CC2。在握手階段Source設(shè)備通過(guò)Rp上拉電阻、Sink設(shè)備通過(guò)Rd下拉電阻在CC線(xiàn)上形成特定的分壓電平。協(xié)商成功后PD通信就通過(guò)這根線(xiàn)進(jìn)行。所以抓USB PD波形本質(zhì)就是要抓CC線(xiàn)上的信號(hào)如果是一根Type-C線(xiàn)纜還要注意區(qū)分CC1和CC2哪根正在通信。CC線(xiàn)上的信號(hào)是單端的以GND為參考。通信時(shí)電平會(huì)在高低兩個(gè)狀態(tài)之間快速切換高電平大約在1V上下具體取決于供電策略。邏輯分析儀判定邏輯“1”和“0”依據(jù)的是一個(gè)閾值電壓超過(guò)閾值算高、低于閾值算低。這個(gè)特點(diǎn)決定了我們抓取時(shí)要注意共地并且要了解CC線(xiàn)的參考地必須在同一系統(tǒng)內(nèi)否則波形完全沒(méi)法看。實(shí)際抓取時(shí)你可以選擇在Source端的CC引腳上接探頭也可以在Sink端接取決于你想觀察哪個(gè)方向的消息。需要注意的是CC1和CC2不是同時(shí)工作的設(shè)備會(huì)選擇一個(gè)作為主通信通道。如果不能確定是哪一根兩個(gè)通道一起抓最穩(wěn)妥。2.2 BMC編碼一個(gè)自帶時(shí)鐘的“摩爾斯電碼”USB PD在CC線(xiàn)上用的編碼方式叫雙相標(biāo)記編碼英文是Biphase Mark Coding縮寫(xiě)就是標(biāo)題里的BMC。如果想在邏輯分析儀上正確解讀波形理解BMC編碼規(guī)則是繞不開(kāi)的一步。BMC的規(guī)則其實(shí)很簡(jiǎn)單每個(gè)比特周期內(nèi)信號(hào)的起始邊界一定有一個(gè)跳變這是為了讓接收端提取時(shí)鐘。而比特中間有沒(méi)有額外的跳變則用來(lái)區(qū)分“0”和“1”。如果傳輸邏輯“0”比特中間不再跳變整個(gè)比特周期內(nèi)電平保持不變?nèi)绻麄鬏斶壿嫛?”比特中間還會(huì)再跳變一次所以一個(gè)比特周期內(nèi)會(huì)出現(xiàn)一次額外的翻轉(zhuǎn)。從這個(gè)規(guī)則可以推出一個(gè)很有意思的結(jié)論邏輯“0”在比特周期內(nèi)表現(xiàn)為一段較寬的電平保持高電平或低電平持續(xù)約3.33微秒而邏輯“1”在比特中間發(fā)生翻轉(zhuǎn)單段電平寬度只有約1.67微秒。也就是說(shuō)電平保持時(shí)間長(zhǎng)的對(duì)應(yīng)“0”保持時(shí)間短的對(duì)應(yīng)“1”。接收端靠邊界處的固定跳變恢復(fù)時(shí)鐘靠中間有沒(méi)有跳變讀出數(shù)據(jù)位。為什么USB PD要選BMC而不是簡(jiǎn)單的NRZ因?yàn)锽MC有自同步能力不需要在傳輸鏈路上單獨(dú)傳時(shí)鐘信號(hào)而且比特流里始終包含高頻跳變成分直流分量相對(duì)穩(wěn)定對(duì)單線(xiàn)傳輸來(lái)說(shuō)很友好。你在邏輯分析儀上看到的BMC波形就像一段高高低低的“方波信號(hào)”但里面其實(shí)藏著一整個(gè)協(xié)議棧的信息。2.3 USB PD的幀結(jié)構(gòu)SOP、Header、CRC32與EOP把CC線(xiàn)上的BMC波形解碼成比特流之后下一步是從比特流里切出完整的數(shù)據(jù)幀。USB PD報(bào)文在物理層上按這樣一個(gè)順序組織Preamble前導(dǎo)碼用來(lái)讓接收端完成時(shí)鐘同步通常是1010交替的比特序列SOPStart of Packet包起始同步模式標(biāo)識(shí)后面的內(nèi)容是真正的PD消息規(guī)范里定義了SOP、SOP、SOP等不同版本用于區(qū)分通信對(duì)象Header16比特長(zhǎng)度的消息頭里面攜帶消息類(lèi)型、數(shù)據(jù)對(duì)象數(shù)量、消息ID、端口角色和電源角色等信息Data Objects數(shù)據(jù)對(duì)象數(shù)量不定0到7個(gè)每個(gè)32比特比如Source_Capabilities消息里的PDOPower Data Object就是一串?dāng)?shù)據(jù)對(duì)象CRC324字節(jié)的循環(huán)冗余校驗(yàn)校驗(yàn)范圍從SOP之后到CRC之前的所有比特EOPEnd of Packet包結(jié)束標(biāo)識(shí)。拿到解碼后的比特流之后識(shí)別SOP是關(guān)鍵一步。SOP是一組特定的同步模式普通數(shù)據(jù)里幾乎不會(huì)自然出現(xiàn)所以接收端一看到這個(gè)模式就知道“新包來(lái)了”。識(shí)別出SOP之后就能順藤摸瓜讀Header、數(shù)據(jù)對(duì)象然后按CRC32校驗(yàn)數(shù)據(jù)完整性??雌饋?lái)有點(diǎn)復(fù)雜但實(shí)際操作中邏輯分析儀的協(xié)議解碼器會(huì)幫我們直接完成這一切。之所以還要懂幀結(jié)構(gòu)是因?yàn)楫?dāng)解碼器失效、或者你想自己寫(xiě)腳本做深度分析時(shí)這些就是唯一的依靠。3. 實(shí)操準(zhǔn)備接線(xiàn)、采樣率與采集參數(shù)設(shè)置3.1 安全且正確的接線(xiàn)方法從Type-C上找到CC線(xiàn)接線(xiàn)是整個(gè)實(shí)操里最容易翻車(chē)的一步。不要一上來(lái)就想著把邏輯分析儀直接懟到Type-C母座上先確認(rèn)你要抓的設(shè)備和線(xiàn)纜類(lèi)型。如果你抓的是帶Type-C接口的電源適配器最穩(wěn)妥的方式是打開(kāi)外殼在Source控制器的CC引腳上飛線(xiàn)出來(lái)??刂破鞯腃C引腳通常有絲印標(biāo)注或者查閱芯片手冊(cè)確認(rèn)實(shí)測(cè)下來(lái)這樣抓到的信號(hào)最干凈。如果不想拆外殼也可以買(mǎi)帶測(cè)試點(diǎn)的Type-C轉(zhuǎn)接板那上面會(huì)引出CC1、CC2引腳直接夾上去就行。連接順序是這樣邏輯分析儀的GND先和被測(cè)設(shè)備的GND接在一起這是絕對(duì)前提。然后把邏輯分析儀的一個(gè)通道接到CC1上如果條件允許另一個(gè)通道同時(shí)接到CC2上。最后再上電觸發(fā)采集。很多新手第一次抓不到波形問(wèn)題就出在沒(méi)共地上或者接了CC線(xiàn)但沒(méi)接GND導(dǎo)致參考電位浮動(dòng)。接線(xiàn)時(shí)還有幾個(gè)細(xì)節(jié)邏輯分析儀探頭的地線(xiàn)夾子盡量短避免引入噪聲測(cè)試線(xiàn)不要和VBUS的高壓線(xiàn)綁在一起容易帶來(lái)串?dāng)_如果抓的是已經(jīng)協(xié)商過(guò)的鏈路要等設(shè)備重新握手才能抓到通信過(guò)程所以一般先接好線(xiàn)再給設(shè)備上電或者拔插一次電源觸發(fā)重新協(xié)商。3.2 采樣率怎么設(shè)1.67微秒最小脈沖背后的數(shù)學(xué)采樣率設(shè)置直接決定了你能不能正確解碼BMC。前面提到了USB PD的比特率是300kbps即每秒30萬(wàn)比特每比特周期約3.33微秒。按照BMC編碼規(guī)則邏輯“1”在比特中間有跳變意味著最短的電平保持時(shí)間只有1.67微秒。根據(jù)奈奎斯特采樣定理理論上要采集至少2倍于信號(hào)最高頻率的采樣率才能恢復(fù)波形即約1.2MHz采樣率就不會(huì)丟信息。但工程上這個(gè)理論值遠(yuǎn)遠(yuǎn)不夠因?yàn)椴蓸狱c(diǎn)剛好錯(cuò)開(kāi)跳變沿是常有的事。我個(gè)人的經(jīng)驗(yàn)是至少保證每個(gè)最短脈沖有8到10個(gè)采樣點(diǎn)換算下來(lái)就是10MHz到20MHz。用20MHz采樣率抓BMC波形1.67微秒的最窄脈沖對(duì)應(yīng)大約33個(gè)采樣點(diǎn)足夠讓解碼軟件穩(wěn)定判定沿的位置。如果是快速觀察、只做肉眼確認(rèn)10MHz也勉強(qiáng)可用但碰到抖動(dòng)嚴(yán)重的信號(hào)就容易誤碼。我在實(shí)際項(xiàng)目里統(tǒng)一設(shè)置成20MHz既有余量又不會(huì)讓采集文件大得離譜。另外一個(gè)重要參數(shù)是采集時(shí)長(zhǎng)。PD協(xié)商過(guò)程通常在幾十毫秒內(nèi)完成我一般設(shè)置50毫秒到200毫秒的采集窗口足夠把一次完整的協(xié)商抓下來(lái)。如果你的電力適配器有周期性重試機(jī)制可以把窗口拉得更長(zhǎng)。注意采樣率越高、時(shí)長(zhǎng)越長(zhǎng)數(shù)據(jù)量越大要保證電腦內(nèi)存和軟件能扛得住。3.3 Saleae與PulseView采集設(shè)置實(shí)戰(zhàn)從空波形到捕獲協(xié)商全過(guò)程以Saleae邏輯分析儀為例完整流程是這樣的。先打開(kāi)Logic軟件在通道列表里選中你接CC1的通道設(shè)置采樣率為20MHz采樣時(shí)長(zhǎng)設(shè)為100毫秒。然后在觸發(fā)設(shè)置里選擇上升沿觸發(fā)觸發(fā)通道指向CC1。這樣做的目的是讓軟件在CC線(xiàn)出現(xiàn)第一次跳變時(shí)才開(kāi)始記錄避免一堆空閑波形占滿(mǎn)存儲(chǔ)空間。設(shè)置完成后先點(diǎn)擊開(kāi)始采集然后給被測(cè)設(shè)備上電或者重新插拔Type-C線(xiàn)纜。等到設(shè)備開(kāi)始PD協(xié)商CC線(xiàn)上的BMC波形就會(huì)出現(xiàn)。采集結(jié)束后你會(huì)在軟件界面上看到一長(zhǎng)串脈沖波形這就是原始CC線(xiàn)通信數(shù)據(jù)。如果用的是PulseView步驟類(lèi)似在設(shè)備下拉菜單中選擇你的邏輯分析儀只要是sigrok兼容的硬件就行添加一個(gè)數(shù)字通道并接到CC1同樣設(shè)置16MHz或20MHz采樣率開(kāi)啟上升沿觸發(fā)再點(diǎn)擊Run。PulseView的優(yōu)勢(shì)是開(kāi)源免費(fèi)解碼協(xié)議可以通過(guò)插件擴(kuò)展雖然自帶的USB PD解碼支持有限但導(dǎo)出波形數(shù)據(jù)后結(jié)合腳本分析一樣能完成任務(wù)。我建議新手第一次實(shí)操時(shí)先不要急著加解碼器而是看著原始波形試著找到Preamble那串規(guī)則的1010方波再試著肉眼辨認(rèn)SOP附近的異常跳變模式。這個(gè)過(guò)程雖然慢但能幫你把BMC編碼和實(shí)際波形對(duì)應(yīng)起來(lái)對(duì)后續(xù)理解協(xié)議解碼非常有幫助。4. BMC解碼實(shí)戰(zhàn)三種方法還原USB PD報(bào)文4.1 方法一直接使用Saleae內(nèi)置USB PD協(xié)議解析器在Saleae Logic軟件里抓完波形后點(diǎn)擊界面右側(cè)的“”按鈕添加一個(gè)協(xié)議解析器。在解析器列表中找到“USB PD”把它分配給CC1所在通道軟件就會(huì)自動(dòng)開(kāi)始解碼。幾秒鐘之后解碼結(jié)果會(huì)以協(xié)議幀的形式疊加顯示在波形上方每一行就是一幀完整的PD消息包含SOP類(lèi)型、消息類(lèi)型、關(guān)鍵字段等。我通常會(huì)觸發(fā)一次充電器上電然后觀察解碼輸出第一條看到的往往是Source發(fā)送的Source_Capabilities消息緊跟著是Sink的Request消息然后Source回復(fù)Accept最后Source發(fā)送PS_RDY表示電源就緒。這四幀就是一次最簡(jiǎn)單的PD握手流程。解析器還會(huì)把CRC校驗(yàn)結(jié)果顯示出來(lái)如果出現(xiàn)CRC錯(cuò)誤說(shuō)明物理層傳輸有問(wèn)題。這時(shí)候回去看波形經(jīng)常能發(fā)現(xiàn)某個(gè)電平段的保持時(shí)間明顯偏離理論值或者中間有毛刺這就是BMC誤碼的根源。Saleae解析器的好處是省時(shí)省力適合快速定位宏觀問(wèn)題。但它的缺點(diǎn)是封裝好的你沒(méi)法知道它內(nèi)部是怎么從比特流里找SOP的。真遇到解碼不出來(lái)或者解出來(lái)全是亂碼的情況還是得靠手工方法往下挖。4.2 方法二手工從波形還原比特流以一段模擬波形為例工具幫你解完只是手段自己能從裸波形里還原出一幀報(bào)文才算真正理解USB PD。下面我用一段模擬波形來(lái)演示完整的解碼思路。假設(shè)邏輯分析儀抓到的波形經(jīng)過(guò)去毛刺處理后得到下面這一小段高/低電平序列1表示高0表示低1010101010101010 1110011100111001 0110010110100101第一步是找邊界跳變。BMC編碼里每個(gè)bit的起始處必然有一次跳變所以可以把連續(xù)相同電平看成一個(gè)個(gè)時(shí)間片段然后以“兩個(gè)相鄰跳變之間是否還能再見(jiàn)到跳變”來(lái)區(qū)分bit。更直觀的算法是算出每個(gè)電平段的持續(xù)時(shí)間3.33微秒左右的是邏輯“0”1.67微秒左右的是邏輯“1”。比如序列里出現(xiàn)了連續(xù)的“111”段說(shuō)明這中間是兩次邏輯“1”連在一起中間那次跳變正好是第一個(gè)1的bit中間跳變。第二步是恢復(fù)原始比特流。按這個(gè)規(guī)則拆解下來(lái)上面的電平序列會(huì)變成一串二進(jìn)制數(shù)據(jù)。我們要的SOP模式就藏在這串比特流的開(kāi)頭某處。由于SOP在規(guī)范里有固定模式而且前面接的是Preamble所以找到1010交替結(jié)束后第一次出現(xiàn)的非規(guī)則模式基本就是SOP的位置。第三步是切幀。認(rèn)出SOP之后從SOP結(jié)束后的第一個(gè)bit開(kāi)始數(shù)出16比特作為Header再按Header里指示的數(shù)量讀出數(shù)據(jù)對(duì)象最后讀出32比特的CRC32直到遇到EOP。整個(gè)過(guò)程有點(diǎn)像按圖索驥但真的走一遍之后你對(duì)協(xié)議的幀結(jié)構(gòu)會(huì)非常清晰。手工解碼的局限也很明顯當(dāng)一幀里包含幾十個(gè)數(shù)據(jù)對(duì)象、幾百個(gè)比特時(shí)人工數(shù)bit非常容易出錯(cuò)。所以這個(gè)方法適合理解原理、驗(yàn)證小段數(shù)據(jù)實(shí)際大批量分析還是得靠腳本。4.3 方法三寫(xiě)Python腳本完成BMC解碼附可直接跑的代碼如果你手里的是PulseView這類(lèi)不帶PD解碼器的設(shè)備別急著放棄。邏輯分析儀軟件一般都能導(dǎo)出CSV文件每一行是一個(gè)采樣點(diǎn)的電平值?;谶@些數(shù)據(jù)用Python寫(xiě)一個(gè)解BMC的腳本是完全走通的方案。下面這份代碼我實(shí)際跑過(guò)核心邏輯是把采樣點(diǎn)轉(zhuǎn)換成01序列檢測(cè)跳變位置按固定bit周期切出每個(gè)bit再根據(jù)bit中間有無(wú)跳變判定是1還是0。import csv import sys # 參數(shù)根據(jù)實(shí)際采集設(shè)置調(diào)整 SAMPLE_RATE 20_000_000 # 20MHz BIT_RATE 300_000 # USB PD是300kbps BIT_SAMPLES SAMPLE_RATE // BIT_RATE # 每個(gè)bit的采樣點(diǎn)數(shù)約66個(gè) THRESHOLD 0.65 # 電壓閾值根據(jù)波形實(shí)際幅度調(diào)整 def read_csv_levels(filepath): levels [] with open(filepath, r) as f: reader csv.reader(f) header next(reader, None) # 跳過(guò)頭 for row in reader: if len(row) 2: continue try: v float(row[1]) except ValueError: continue levels.append(1 if v THRESHOLD else 0) return levels def decode_bmc(levels): bits [] i 0 n len(levels) while i BIT_SAMPLES n: segment levels[i:i BIT_SAMPLES] # 統(tǒng)計(jì)該bit周期內(nèi)是否存在中間跳變 mid_start BIT_SAMPLES // 4 mid_end 3 * BIT_SAMPLES // 4 mid_half segment[mid_start:mid_end] transitions 0 for j in range(1, len(mid_half)): if mid_half[j] ! mid_half[j-1]: transitions 1 bits.append(1 if transitions 1 else 0) i BIT_SAMPLES return bits if __name__ __main__: levels read_csv_levels(sys.argv[1]) bits decode_bmc(levels) # 打印前200個(gè)bit便于觀察Preamble、SOP print(.join(str(b) for b in bits[:200]))這段代碼不一定能直接套用到所有波形因?yàn)閷?shí)際信號(hào)可能有毛刺、抖動(dòng)bit周期也不會(huì)嚴(yán)格等寬。更健壯的做法是先用一段滑動(dòng)窗口檢測(cè)跳變沿再根據(jù)跳變間隔聚類(lèi)出1.67us和3.33us兩類(lèi)時(shí)間寬度從而恢復(fù)數(shù)據(jù)。但在拿到真實(shí)波形、準(zhǔn)備手工深入分析時(shí)上面這個(gè)雛形足夠當(dāng)起點(diǎn)。腳本解碼的最大價(jià)值是批量處理。你可以把一整個(gè)協(xié)商過(guò)程的CSV導(dǎo)出然后用腳本解出所有bit再按幀結(jié)構(gòu)把SOP、Header、數(shù)據(jù)對(duì)象全部提取出來(lái)生成一份類(lèi)似協(xié)議分析器的報(bào)告。這比在一塊屏幕上手動(dòng)滾動(dòng)波形高效得多也是我處理疑難問(wèn)題時(shí)的常用手段。5. 抓包與解碼常見(jiàn)問(wèn)題排查實(shí)錄5.1 波形完全空白八成是共地和觸發(fā)的問(wèn)題這是新手最常遇到的情況。明明接了CC線(xiàn)點(diǎn)開(kāi)始采集結(jié)果波形一片空白偶爾有一兩個(gè)毛刺。我排查這類(lèi)問(wèn)題有一套固定順序。先看邏輯分析儀輸入指示燈是否正常、通道是否選對(duì)、GND是否和被測(cè)設(shè)備共地。CC線(xiàn)信號(hào)以GND為參考如果地線(xiàn)斷開(kāi)所有電平判斷都會(huì)失效。其次看觸發(fā)設(shè)置使用上升沿觸發(fā)時(shí)如果設(shè)備在點(diǎn)擊采集之前就已經(jīng)完成了協(xié)商那么之后不再有上升沿自然抓不到任何數(shù)據(jù)。解決辦法是把觸發(fā)模式改成“無(wú)觸發(fā)足夠長(zhǎng)的時(shí)長(zhǎng)”或者先點(diǎn)擊采集再重新上電、拔插線(xiàn)纜人為制造一次握手過(guò)程。最后檢查探頭接觸是否牢固尤其是使用杜邦線(xiàn)或者夾子時(shí)接觸電阻變大也會(huì)讓信號(hào)衰減得面目全非。5.2 抓到了波形但解碼全是亂碼采樣率和閾值的取舍如果你能看到波形但Saleae解碼器輸出的全是亂碼或者CRC瘋狂報(bào)錯(cuò)通常要往兩個(gè)方向排查。第一是采樣率是否不足。前面算過(guò)1.67微秒的最小脈沖至少要保證8到10個(gè)采樣點(diǎn)。如果采樣率只有2MHz或4MHz邏輯分析儀會(huì)漏掉很多跳變沿BMC解碼自然亂套。在Saleae里把采樣率改為20MHz再抓一次很多問(wèn)題立刻消失。第二是信號(hào)電平是否落在閾值邊緣。USB PD的CC線(xiàn)高電平和低電平之間的余量并不大如果被測(cè)設(shè)備的CC線(xiàn)上電平不穩(wěn)定或者上位機(jī)軟件設(shè)置的閾值偏高/偏低就會(huì)導(dǎo)致采樣結(jié)果出現(xiàn)誤判。Saleae允許手動(dòng)調(diào)整數(shù)字通道的閾值電壓PulseView則需要通過(guò)校準(zhǔn)或者手動(dòng)測(cè)出實(shí)際電平范圍。一般來(lái)說(shuō)把閾值設(shè)在CC線(xiàn)高電平和低電平的中間位置最合適但前提是你要知道這兩個(gè)電平的實(shí)際值可以先觀察一段波形的幅度再做判斷。5.3 解碼出來(lái)了但少幀或丟包SOP識(shí)別和干擾排查有時(shí)候波形和解碼都是正常的但解出來(lái)的報(bào)文明顯缺少某些應(yīng)該出現(xiàn)的幀比如Source_Capabilities后面對(duì)應(yīng)的Request沒(méi)有出現(xiàn)。這類(lèi)問(wèn)題往往是物理層丟幀不是解碼器的鍋。BMC接收端是通過(guò)檢測(cè)SOP來(lái)判定新包開(kāi)始的如果SOP前幾個(gè)bit因?yàn)槊?、地彈或者串?dāng)_被破壞接收端就會(huì)忽略整個(gè)包。排查手段是回到原始波形放大看SOP附近的細(xì)節(jié)看是否存在多余的高頻毛刺。如果毛刺出現(xiàn)在上升沿或者下降沿附近可以考慮在代碼層面用中值濾波去抖如果是由于探針接觸不良導(dǎo)致的就先處理物理連接。另外一個(gè)隱蔽原因是采集時(shí)間窗口太短。PD協(xié)商過(guò)程中有時(shí)會(huì)有一些延遲比如Sink設(shè)備在發(fā)送Request之前會(huì)做內(nèi)部電壓測(cè)量如果采集窗口恰好在這個(gè)間隙停止記錄看起來(lái)就像丟幀了。解決辦法是把采樣時(shí)長(zhǎng)放寬到200毫秒以上甚至1秒寧可多抓數(shù)據(jù)也不要在時(shí)間窗口上省事。6. 實(shí)操心得與后續(xù)進(jìn)階建議沒(méi)有什么比親自動(dòng)手更有價(jià)值做USB PD調(diào)試這幾年我越來(lái)越覺(jué)得抓波形這件事情本身不是目的真正的目的是建立“問(wèn)題-現(xiàn)象-信號(hào)”之間的直接對(duì)應(yīng)關(guān)系。每次遇到難啃的PD握手問(wèn)題我都會(huì)先問(wèn)三個(gè)問(wèn)題是否看到了完整的協(xié)商狀態(tài)機(jī)是否有某條消息的CRC校驗(yàn)失敗CC線(xiàn)上的波形是否存在不該出現(xiàn)的跳變把這三個(gè)問(wèn)題放到邏輯分析儀上去驗(yàn)證往往比翻半天寄存器更有效。如果你剛開(kāi)始接觸USB PD我建議按這個(gè)順序練習(xí)先用帶內(nèi)置解碼器的邏輯分析儀抓一次完整的充電協(xié)商見(jiàn)識(shí)一下Source_Capabilities到PS_RDY的標(biāo)準(zhǔn)流程然后用手工方法解一小段波形把BMC編碼、SOP、Header這些概念和物理信號(hào)對(duì)上號(hào)最后再考慮寫(xiě)腳本做批量分析完善自己對(duì)BMC解碼的理解。這個(gè)過(guò)程下來(lái)你不僅能排查問(wèn)題還能對(duì)協(xié)議本身有更深的認(rèn)識(shí)。再往后如果你想進(jìn)階可以重點(diǎn)關(guān)注幾件事一是PPS可編程電源協(xié)商過(guò)程中的APDOAugmented PDO交互那里面數(shù)據(jù)對(duì)象的解析更復(fù)雜二是VDMVendor Defined Message消息尤其是供應(yīng)商自定義指令的抓取和解析三是線(xiàn)纜emark相關(guān)通信這類(lèi)通信使用SOP和普通SOP報(bào)文混在一起解碼器如果沒(méi)處理會(huì)直接跳錯(cuò)。這些都是USB PD協(xié)議里比較深的水區(qū)但基本原理還是BMC、SOP、Header、CRC這套東西大框架吃透了剩下的只是填細(xì)節(jié)而已。最后分享一個(gè)小技巧抓PD波形的時(shí)候我會(huì)同時(shí)把邏輯分析儀的一個(gè)通道接到CC1、另一個(gè)通道接到CC2剩下一個(gè)通道留出來(lái)接VBUS。這樣一次采集既能觀察CC線(xiàn)上完整的協(xié)議交互又能看到VBUS電壓何時(shí)上升、CC通信和功率輸出之間的時(shí)序關(guān)系。很多電源切換類(lèi)的疑難問(wèn)題靠這個(gè)多通道布局一眼就能定位。工具是死的思路是活的真正把邏輯分析儀用好的工程師都是把通道、觸發(fā)、解碼這些功能組合起來(lái)針對(duì)具體場(chǎng)景打組合拳的人。希望這篇文章能幫你少走一些彎路。