1.場景還原:在我開發USB PD測試模塊時,發現待測主板始終不回復Request消息,導致我的測試失敗;此時我的任務就是快速定位這個協議交互失敗的原因,無論是軟件、硬件還是協同。
2.大致的調試步驟:
? ? ? ? 1.首先使用了邏輯分析儀抓取了CC線(這里是CC1)上面的物理波形,并在分析儀的軟件上啟用了BMC解碼,確認了DUT確實發出了Request消息,并且波形解碼出來的CRC值與我手動計算出來的值結果一致。
? ? ? ? 2.然后,我檢查了Linux驅動層的調試日志,發現驅動收到的同一條消息的CRC值與波形完全不同。好了,此時有兩種可能,一種就是在PL端和PS端進行數據通信的時候發生了問題,導致校驗失敗;另一種可能就是PL端出現了某些問題。
? ? ? ? 3.我排查了我的驅動讀取FIFO的代碼,發現一切正常,所以不是我軟件的問題。那么只有一種可能,那就是FPGA的PL端出現了問題。
? ? ? ? 4.好了,我此時定位了是FPGA的硬件問題了。然后就是和硬件工程師排查一下是哪里出現了問題,Review了PL端IP核的Verilog代碼,發現其CRC生成器的初始值配置錯誤。
3.解決方案:
? ? ? ? 1.在定位了是PL端的問題以后,先進行了自己的軟件CRC 校驗作為臨時的方案,保證了項目的進度;
? ? ? ? 2.過了大概兩天,提交了我們的硬件團隊,協助他們修復了IP核,并驗證了新的比特流文件,最終徹底解決了該問題。
4.總結一個這個令人自豪的調試過程以及DEBUG思路吧。
? ? ? ? 總的來說,發現問題要先利用工具來進行問題的定位,這里用到了邏輯分析儀和Linux 內核調試日志,日志會打印出關鍵的信息,但是這需要很大的耐心去分析波形,在分析的過程中,不僅僅是對波形的分析,還是對于USB PD協議的每一步結構進行深入透徹的了解,不能忽略每一個細節,要精確到每一個時刻,哈哈哈,有點廢人說實話。此外,在日志查看的階段,也是非常需要耐心的,每一個日志信息都有可能成為突破的關鍵點,所以能不能有人開發一個一鍵解決的軟件啊,要不這樣有點廢牛馬,哈哈哈哈。
5.下面是一些詳細的,便于回顧的,同時有具有體會性的調試思路。(其實我可以寫一個JSION腳本來描述,但是。。。。。。自行體會吧)
? ? ? ? 1.復現問題與收集數據
? ? ? ? ? ? ? ? 1.邏輯分析儀的使用,這里可是重中之重啊,硬件的邏輯分析儀要插好,這里我們要捕獲的是PL端和DUT的通信波形,所以就是插在CC線上咯;然后就是配置一下邏輯分析儀軟件的配置啦,第一個是采樣率,由于USB PD協議的波特率是300kbps,所以采樣率要比他高,但是高多少啊,其實俺不知道,那就3Mbps吧,上網查一下就知道了。第二個是要設置一下觸發方式,這里選擇下降沿觸發,看了BMC通信的波形,起始位是高電平,所以要捕獲下他下降的那一刻。第三個是要啟用一下BMC解碼的功能,不然啥都沒有哦(嗚嗚嗚,誰知道我踩了多少坑,卡了多久)。
? ? ? ? ? ? ? ? 2.啟動內核調試日志,因為我的Linux驅動代碼是有調試打印功能的,所以說在開始運行的時候直接開一個終端跑log就行。
? ? ? ? ? ? ? ? 如果沒有開啟,那就完了。好吧,我開玩笑的,你可以手動開啟???我好像在說廢話。。。
? ? ? ? ? ? ? ? 首先要確保Linux驅動代碼中的dev_dbg()、print_hex_hump_bytes()等調試打印功能是開啟的。因為實際上有好多個log,是不是感覺好麻煩,沒事,看關鍵信息就行。
? ? ? ? ? ? ? ? 你可能需要通過dynamic_debug機制動態開啟:這里不展示代碼,只說怎么做。
? ? ? ? ? ? ? ? 你可以通過echo命令將一個驅動文件的輸出重定向到control 里面。
? ? ? ? ? ? ? ? 例如:echo 'file pd_driver.c +p' > /sys/kernel/debug/dynamic_debug/control
? ? ? ? ? ? ? ? 好吧好吧,你贏了,我還是寫了。
? ? ? ? ? ? ? ? 3.復現與捕獲:
? ? ? ? ? ? ? ? 開始運行程序,觸發PD協議的交互,直到交互失敗。可以從dmesg命令中打開日志,查看內核日志。
? ? ? ? 2.聯合分析,定位矛盾(看邏輯分析儀的波形,看日志)
? ? ? ? ? ? ? ? 1.看波形:當然是在邏輯分析儀軟件上看啦,注意這個時候不要從頭開始看波形,直接找儀器發送的Source_Capabilities消息和DUT(Sink)回復的Request消息。重點關注我的Request消息,但是儀器發送的消息也要看啊,萬一是我發的有問題呢,不要排除任何一種可能,邏輯分析儀,邏輯一定要完美,不能有漏洞。
? ? ? ? ? ? ? ? 2.當然說了這么多廢話,還是要重點看Requset消息,因為大多數是回的有問題,別問我怎么回事,我瞎說的,哈哈哈哈。
? ? ? ? ? ? ? ? 言歸正傳,在Request消息里,要展開這條消息的詳情,查看軟件解碼出的每一個字段:消息頭、數據對象、CRC32(有的人說CRC16,其實現在多是32,這樣效果更好,數據安全性更好)。
? ? ? ? ? ? ? ? 這里要驗證一下我的邏輯分析儀,為了以防萬一啊,萬一邏輯分析儀壞了咋辦呢。啊,邏輯分析儀壞了,是不是感覺累了,哈哈哈,啥都得提防,壞人好多。
? ? ? ? ? ? ? ? 怎么驗證呢,當然是把消息頭、數據對象那些十六進制數據自己手算一下CRC校驗值啦。什么,你說你不會,好吧,其實我也不會,但是沒有計算器嗎?
? ? ? ? ? ? ? ? 好,通過計算器驗證了一下,發現和邏輯分析儀解碼出來的一樣,說明我們的邏輯分析儀還是可信的,是好人捏。
? ? ? ? ? ? ? ? 好了,既然邏輯分析儀解碼正確,說明這里波形是正確的,說明DUT傳過來的是正確的,消息也確實是發給我儀器了。但是我的驅動卻認為CRC錯誤。那問題可能出現在傳輸過程中,或者在PL端,這里其實已經初見端倪了。嘿嘿,小黑子終于露出了犄角。
? ? ? ? ? ? ? ? 那接下來就看一下內核日志這一塊是怎么說的吧。查看內核日志,找出驅動記錄“CRC錯誤”或者“丟棄無效的消息”的那一行。日志會顯示驅動實際接收到的完整消息和CRC值。對比一下邏輯分析儀的正確CRC值,發現這個日志里面的和那個正確的CRC值不一樣。好,確定了我上面的猜測。
? ? ? ? ? ? ? ? 這個時候我可以百分之百確定就是在傳輸的過程中或者是PL端哪里出現了問題。其實后面想了一下,可能是DUT向PL端傳輸時出現了錯誤,也可能是PL端,還有可能是PL端向PS端傳輸的過程中出現了錯誤,到底是哪個啊,好難猜啊哈哈哈哈哈。其實我是想知道先排查哪一個,那就分析分析吧。
? ? ? ? 3.深入挖掘原因
? ? ? ? ? ? ? ?1. 首先,PL端應該放最后,因為那是FPGA硬件工程師的錯誤,最后再說,DUT向PL端傳輸也應該放后,因為目前沒有手段直接讀到FPGA端接收到的CRC32值,先排查我軟件驅動讀到的值吧,而且從軟件到硬件排查也是通常的一個順序。
? ? ? ? ? ? ? ?2. 好了,分析了好久,還是回到了我驅動讀到的CRC值。驅動一般不會“寫”,不會修改CRC值,那么只有可能是驅動從RX_FIFO寄存器中讀取錯了,檢查一下代碼,看看是邏輯錯誤,還是一次性連續讀取4個uint32_t,字節序的問題(畢竟是arm架構和FPGA架構),還有緩存或者內存對齊的問題?
? ? ? ? ? ? ? ? 如果這些代碼沒有問題,那么就是寄存器里面的數據本身就是有問題的!!!好了,這個時候我的驅動這邊問題排除了。那接下來就是PL端的問題了,或者說肯定是PL端的問題了,不不不,大概率是他的問題(差點草率了,其實還有DUT向PL的過程,但是這個概率太小了,但是我不能排除,不然會出問題)。
? ? ? ? ? ? ? ? 好了,將問題丟給硬件工程師,我的調試基本上結束了。
????????4.解決方案
? ? ? ? ? ? ? ? 1.我不從PL端的RX-FIFO寄存器讀取CRC值,根據數據直接在驅動里計算CRC值。這樣做可能看著有點別扭,但是你先別別扭,因為不能因為這個錯誤把進度卡了,所以先這樣吧。
? ? ? ? ? ? ? ? 2.修復FPGA端的錯誤,定位在了IP核中的CRC模塊,配置錯誤,CRC寄存器初始值不是0XFFFFFFFF,很細節是不是哈哈哈,一個配置錯誤直接卡了我好久。
????????????????