芯片調(diào)試實(shí)戰(zhàn):從硬件鏈路到千兆轉(zhuǎn)發(fā))
簡(jiǎn)介面向嵌入式網(wǎng)絡(luò)設(shè)備開發(fā)場(chǎng)景這套源碼資源聚焦RK3568處理器與YT9215交換機(jī)芯片的驅(qū)動(dòng)程序適配適用于從事Linux內(nèi)核驅(qū)動(dòng)、硬件接口調(diào)試的工程師學(xué)習(xí)參考。壓縮包共2個(gè)文件包含1個(gè).c源文件和1個(gè).h頭文件整體大小僅4KB其中.c源文件主要實(shí)現(xiàn)設(shè)備初始化、數(shù)據(jù)收發(fā)與中斷處理等驅(qū)動(dòng)核心邏輯.h頭文件則定義驅(qū)動(dòng)所需的結(jié)構(gòu)體、常量與函數(shù)聲明兩者配合構(gòu)成一個(gè)精簡(jiǎn)可研究的驅(qū)動(dòng)模塊。目前已有5129人瀏覽學(xué)習(xí)說明該主題在同類調(diào)試場(chǎng)景中有一定代表性。參照這兩個(gè)文件可梳理出從設(shè)備樹描述、驅(qū)動(dòng)注冊(cè)到收發(fā)測(cè)試的完整思路。同時(shí)也能輔助定位硬件接口分析及驅(qū)動(dòng)代碼編寫階段的常見問題為后續(xù)優(yōu)化與維護(hù)提供直接參考。1. RK3568 YT9215 在做什么從多網(wǎng)口需求到交換機(jī)芯片一塊 RK3568 的板子原生網(wǎng)口通常只有兩三個(gè)而一臺(tái)千兆交換機(jī)的需求往往起步就是四個(gè)千兆口起步有的還要帶光口或 PoE。與其換主控不如在 RK3568 的 PCIe 或 SGMII 接口上外掛一顆 YT9215 交換機(jī)芯片把網(wǎng)口數(shù)量一次性擴(kuò)到五六個(gè)。方案聽起來順理成章但真正把板子拿到手開始調(diào)的人都知道這從來不是“插上就能用”的活。YT9215 不是普通 PHY它是一顆帶完整交換內(nèi)核的芯片上電后默認(rèn)配置可能連 CPU 端口都不通MDIO 讀不到 ID、寄存器寫不進(jìn)去、內(nèi)核里根本沒有對(duì)應(yīng)驅(qū)動(dòng)這才是常態(tài)。這篇文章要講的就是我在 RK3568 上把 YT9215 從頭調(diào)到能跑滿千兆的完整路徑適合正在做多網(wǎng)口網(wǎng)關(guān)、工業(yè)交換機(jī)或邊緣計(jì)算底板的開發(fā)者內(nèi)容會(huì)一直寫到驗(yàn)證工具和坑的解法。2. RK3568 與 YT9215 的硬件鏈路接口選型與上電檢查2.1 接口選型SGMII、RGMII 還是 PCIeRK3568 與 YT9215 之間的連接方式?jīng)Q定了我后續(xù)所有調(diào)試路徑的走向。常見的接法有三種SGMII、RGMII 和 PCIe。YT9215 這類交換芯片通常帶有多個(gè) SerDes 通道通道可以被復(fù)用成 SGMII 接口連接主控也可以配置成 PCIe RC 模式或者作為 PCIe EP 被主控枚舉。硬件設(shè)計(jì)階段選哪種直接決定驅(qū)動(dòng)方式是把它當(dāng)普通 PHY 用還是當(dāng) PCIe 交換機(jī)用。我一般會(huì)優(yōu)先選 PCIe原因很實(shí)際。RK3568 原生 PCIe2.0 控制器打開后YT9215 會(huì)被識(shí)別成一個(gè) PCIe 設(shè)備Linux 自帶的 switchtec 或者 mdio 觸達(dá)方式更靈活吞吐量上限也高SerDes 跑 5Gbps 跑滿千兆毫無壓力。如果板子上 PCIe 通道已經(jīng)被 NVMe 或 Wi-Fi 占用那就退一步用 SGMII把 YT9215 接到 RK3568 的 GMAC 控制器上讓 Linux 把它當(dāng)作一個(gè)“帶內(nèi)部交換功能的 PHY”。RGMII 是最后的選擇16bit 數(shù)據(jù)線布線要求高頻率跑不上 1000Mbps 以上速率只適合低成本的百兆場(chǎng)景。選型這件事上踩過的最大一個(gè)坑是把 PCIe 通道復(fù)用當(dāng)成理所當(dāng)然。RK3568 的 PCIe2.0 控制器和 SATA、USB3 之間本身就存在引腳復(fù)用硬件工程師如果沒在原理圖階段確認(rèn)引腳的 mux 配置板子回來之后 PCIe 怎么都枚舉不到。軟件上可以通過修改 pinctrl 節(jié)點(diǎn)做嘗試但如果硬件上已經(jīng)走線錯(cuò)誤系統(tǒng)端是無能為力的。2.2 上電前的硬件檢查先量電壓再做時(shí)鐘測(cè)量很多 YT9215 調(diào)不通的案子根因并不在軟件而是硬件細(xì)節(jié)不規(guī)范。YT9215 這類交換芯片比普通 PHY 復(fù)雜供電通常有 1.0V 核心電壓、1.8V 和 3.3V 三個(gè)域而且對(duì)上下電時(shí)序敏感。拿到板子第一步我習(xí)慣用示波器同時(shí)測(cè)三路電源的上升沿確認(rèn) 1.0V 不要比 3.3V 先掉電。這個(gè)看似玄學(xué)的問題實(shí)際導(dǎo)致的典型故障是芯片經(jīng)常第一次能工作、重啟后失聯(lián)而且用萬用表量電壓全是正常的不加示波器根本發(fā)現(xiàn)不了。之后必須測(cè)量 YT9215 的時(shí)鐘輸入。25MHz 參考晶振是這顆芯片正常工作的基礎(chǔ)測(cè)的時(shí)候不要只看有沒有波形要關(guān)注頻率偏差超過 50ppm 的信號(hào)會(huì)影響 SerDes 的位同步表現(xiàn)為主控側(cè)鏈路反復(fù) training 失敗。另外一個(gè)容易被忽略的是復(fù)位引腳的上電釋放時(shí)間YT9215 的復(fù)位釋放要晚于所有電源穩(wěn)定至少 10ms很多 ARM 板上的 GPIO 復(fù)位是系統(tǒng)起來之后才拉高導(dǎo)致第一次上電時(shí)芯片復(fù)位釋放時(shí)電源還沒完全穩(wěn)定后續(xù)初始化一團(tuán)糟。硬件檢查做完后我習(xí)慣在 uboot 階段先做一個(gè)最基礎(chǔ)的探測(cè)。如果走的是 PCIe 連接在 uboot 命令行里直接執(zhí)行 pci enum然后查看設(shè)備樹中 PCIe 控制器是否識(shí)別到了設(shè)備。如果 VENDOR ID 讀出來是 0xFFFF說明物理鏈路就有問題這時(shí)候我會(huì)直接量 SerDes 的差分信號(hào)是否在輸出排除主控側(cè) PCIe 控制器沒有正常 link up 的情況。Rockchip U-Boot pci enum Rockchip U-Boot pci 0執(zhí)行后如果沒有任何設(shè)備號(hào)顯示把 dmesg 打開看 PCIe 控制器報(bào)錯(cuò)信息重點(diǎn)找 PHY PLL lock 失敗和 LTSSM 狀態(tài)的打印。LTSSM 停在 Detect 狀態(tài)基本就是時(shí)鐘或復(fù)位問題停在 Configuration 之前的狀態(tài)則大概率是 SerDes 通道配置不一致。2.3 用 devmem 驗(yàn)證 YT9215 是否在總線上可見在 Linux 系統(tǒng)起來之后第一件事不是急著配置 switch而是確認(rèn) YT9215 在地址空間里可訪問。PCIe 連接的情況下查看 /sys/bus/pci/devices/ 目錄下多沒多設(shè)備再用 setpci 看配置空間里的 VENDOR ID 和 DEVICE ID。rootboard:/# ls /sys/bus/pci/devices/ 0000:01:00.0 rootboard:/# setpci -s 01:00.0 vendor_id如果讀到 ID 正常說明物理鏈路已經(jīng)打通了。這時(shí)候直接讀寫 YT9215 的寄存器空間還是借道 PCIe config space 或者是 BAR 空間映射取決于這顆芯片的設(shè)計(jì)。常見做法是 YT9215 會(huì)提供一塊內(nèi)部寄存器映射通過 PCIe BAR0 窗口暴露給主控??梢杂?devmem 把 BAR0 的地址映射出來直接讀芯片的 ID 寄存器驗(yàn)證訪問通路。rootboard:/# setpci -s 01:00.0 base-address-0拿到 BAR0 的物理地址之后用 devmem 讀芯片內(nèi)部基地址偏移處的 chip ID 寄存器。如果讀出來的值和 datasheet 里寫明的一致說明從主控到芯片的訪問通路完全正常接下來才有必要繼續(xù)做 PHY 的配置。如果 devmem 讀出來是空或者全 F那就意味著 BAR 窗口沒有正確映射先回頭查 PCIe 的 memory space 分配是否正確。3. 把 MDIO 和 PHY 狀態(tài)打通最小驅(qū)動(dòng)加載路徑3.1 最小驅(qū)動(dòng)加載路徑從設(shè)備樹描述一張外掛設(shè)備YT9215 在 Linux 下沒有現(xiàn)成驅(qū)動(dòng)的概率很高內(nèi)核 mainline 未必會(huì)收錄這顆芯片的完整 switch 驅(qū)動(dòng)。常見做法是把它當(dāng)作普通的 MDIO 設(shè)備來描述讓 Linux 的 MDIO 總線框架管理起來再由用戶態(tài)工具直接操作寄存器完成核心的配置工作。在設(shè)備樹里我一般會(huì)在 GMAC 節(jié)點(diǎn)下面掛一個(gè) mdio 子節(jié)點(diǎn)然后描述這顆 PHY。這種描述方式的最大價(jià)值在于讓內(nèi)核的網(wǎng)絡(luò)子系統(tǒng)認(rèn)為這個(gè)端口上連著一個(gè) PHY從而 eth0 這個(gè)網(wǎng)絡(luò)設(shè)備能正常 up后續(xù) MDIO 的訪問路徑也是通的。設(shè)備樹描述示例如下gmac0 { status okay; phy-mode sgmii; mdio0: mdio { compatible snps,dwmac-mdio; #address-cells 1; #size-cells 0; switch_phy: ethernet-phy1 { reg 1; compatible ethernet-phy-id1234.5678; }; }; };這里的 phy-mode 根據(jù)實(shí)際硬件連接方式填寫如果走的是 PCIe 連接就不需要這個(gè)描述直接用 PCIe 驅(qū)動(dòng)去枚舉。ethernet-phy1中的 reg 是 YT9215 在 MDIO 總線上的物理地址這個(gè)地址取決于硬件上 PHYAD 引腳的上下拉配置不能隨意修改否則驅(qū)動(dòng)會(huì) probe 不到設(shè)備。compatible里的 ID 號(hào)要和 YT9215 的實(shí)際 PHY ID 對(duì)應(yīng)起來大部分人這一步會(huì)卡住因?yàn)樾酒锏?PHY ID 和 datasheet 上寫的不完全一致最穩(wěn)妥的辦法是先用 MDIO 工具讀寄存器把 ID 算出來再填。設(shè)備樹配好之后內(nèi)核啟動(dòng)日志里如果能看到 MDIO bus 上發(fā)現(xiàn)了一個(gè) PHY說明內(nèi)核已經(jīng)識(shí)別到設(shè)備。這時(shí)候 eth0 可能還沒有 IP但鏈路狀態(tài)應(yīng)該可以從 down 變成 up。當(dāng)然YT9215 有多組 SerDes 和多哥 PHY 端口需要在 mdio 節(jié)點(diǎn)下重復(fù)掛多端口描述后續(xù)每個(gè)對(duì)外網(wǎng)口才能有對(duì)應(yīng)的 net_device。3.2 用 mdio-tools 直接驗(yàn)證 PHY 寄存器內(nèi)核識(shí)別之后不要急著寫驅(qū)動(dòng)邏輯先用 mdio-tools 手動(dòng)讀一遍寄存器。mdio-tools 是 mdio 讀寫工具集的常見實(shí)現(xiàn)一般在 buildroot 里勾選就能編譯進(jìn)去。如果系統(tǒng)里沒有直接用 busybox 自帶的 mdio 命令也可以只是功能略少。我用的是 mdio-tools 的 mdio read 和 mdio write命令直觀適合一步一步踩。先讀 PHY ID 寄存器組標(biāo)準(zhǔn) PHY 的 ID 寄存器的地址是 2 和 3。執(zhí)行命令之后把兩個(gè)寄存器讀取的值拼起來得到的是一個(gè) 32 位 PHY ID。rootboard:/# mdio read eth0 1 2 0x1234 rootboard:/# mdio read eth0 1 3 0x5678讀出來的 ID 值和 datasheet 里標(biāo)準(zhǔn)的 OUI 對(duì)照確認(rèn)這顆 PHY 在內(nèi)核的 PHY ID 列表里有沒有被定義。通常 YT9215 這種交換芯片內(nèi)部的 PHY 核心 ID 是已知的但也不排除芯片廠家用的自定義 ID這種情況下要把 compatible 換成實(shí)際讀到的數(shù)字否則驅(qū)動(dòng) probe 不了。之后讀寄存器 0BMCR和寄存器 1BMSR看它們的默認(rèn)值是否和 reset 后的狀態(tài)一致。rootboard:/# mdio read eth0 1 0 0x1140 rootboard:/# mdio read eth0 1 1 0x796dBMSR 寄存器里的 bit5 表示 autoneg completebit2 表示 link status。如果讀出來 link 狀態(tài)位為 0表示物理層沒有檢測(cè)到對(duì)端這并不一定是壞事因?yàn)?YT9215 的某些 SerDes 端口在默認(rèn)配置下是處于低功耗或未啟用狀態(tài)的。此時(shí)可以嘗試手動(dòng)配置 BMCR 寄存器強(qiáng)制 1000Mbps 全雙工再讀 BMSR 確認(rèn)鏈路是否能起來。3.3 驅(qū)動(dòng)加載失敗時(shí)的三處關(guān)鍵日志如果 mdio read 命令執(zhí)行不了或者 PHY ID 讀出來全是 F大概率是內(nèi)核網(wǎng)絡(luò)設(shè)備沒有真正起來。這時(shí)候我會(huì)按順序排查三處日志。首先是 dmesg 里和 stmmac 或 dwmac 相關(guān)的行。RK3568 的 GMAC 驅(qū)動(dòng)是 stmmac 框架日志里會(huì)打印 phy mode、MDIO 時(shí)鐘頻率、初始化狀態(tài)。如果打印顯示 MDIO 時(shí)鐘配置失敗檢查設(shè)備樹里 mdio 子節(jié)點(diǎn)的時(shí)鐘屬性通常需要顯式指定 MDC 的頻率上限否則總線的時(shí)序和 YT9215 不匹配。其次是 /sys/class/net 目錄下有沒有出現(xiàn)對(duì)應(yīng)的 ethX 設(shè)備。如果設(shè)備樹里 GMAC 節(jié)點(diǎn)狀態(tài)沒有改為 okay整個(gè) MAC 控制器都不會(huì) probe自然沒有網(wǎng)絡(luò)接口。這個(gè)低級(jí)問題出現(xiàn)的頻率比想象中高很多時(shí)候是設(shè)備樹 overlay 沒有正確加載。最后是 interrupts 相關(guān)的報(bào)錯(cuò)。YT9215 的 interrupt 引腳如果接到 RK3568 的 GPIO 上設(shè)備樹里必須配置正確的中斷號(hào)和觸發(fā)方式。中斷配置錯(cuò)了表現(xiàn)為鏈路狀態(tài)變化時(shí)內(nèi)核不感知即使物理連接恢復(fù)了網(wǎng)絡(luò)接口依舊顯示 down這種問題非常容易讓人困惑看起來像硬件壞了實(shí)際只是內(nèi)核沒有收到中斷。4. 讓數(shù)據(jù)從網(wǎng)口真正走到 CPUPCS 環(huán)回與轉(zhuǎn)發(fā)配置4.1 先做 PCS 環(huán)回把物理鏈路的鍋關(guān)掉當(dāng) PHY 層已經(jīng)能正常 link但 ping 不通的時(shí)候先別急著查轉(zhuǎn)發(fā)邏輯在第一層做環(huán)回測(cè)試是最快的隔離手段。YT9215 這類芯片內(nèi)部支持 PCS 層的環(huán)回把從主控 MAC 發(fā)出的數(shù)據(jù)在芯片內(nèi)部直接環(huán)回到 MAC 接收側(cè)。這一步通過 MDIO 寫一個(gè)特定寄存器不需要外部接網(wǎng)線就能驗(yàn)證主控到芯片之間的通路是否正常。rootboard:/# mdio write eth0 1 0x8000 0x0040這個(gè)操作的實(shí)質(zhì)是設(shè)置 MII 控制寄存器里的 loopback 位。配置完之后從 eth0 ping 一個(gè)指定 IP 地址比如 192.168.1.1如果在環(huán)回模式下能 ping 通說明以太網(wǎng) MAC 到 YT9215 的 SerDes 通路是完好的。如果 ping 不通問題就出在 RK3568 的 GMAC 控制器配置或者 DMA 描述符鏈上沒必要去查后續(xù)的交換邏輯。PCS 環(huán)回測(cè)試通過后立即把環(huán)回位清除避免后面調(diào)試時(shí)數(shù)據(jù)平面被干擾。環(huán)回測(cè)試的另一個(gè)變種是 MAC 層的環(huán)回通過 RK3568 的 GMAC 控制器本身的 loopback 功能來做。兩者可以結(jié)合使用出現(xiàn)問題時(shí)能快速確認(rèn)是主控側(cè)的問題還是 YT9215 側(cè)的問題。我在實(shí)際調(diào)試中最怕的就是這兩層問題交織在一起不做好環(huán)回隔離后面查 VLAN 和轉(zhuǎn)發(fā)配置時(shí)很容易被底層鏈路問題誤導(dǎo)。4.2 轉(zhuǎn)發(fā)路徑與 CPU 收包寄存器級(jí)最小配置YT9215 默認(rèn)狀態(tài)下各端口之間未必自動(dòng)轉(zhuǎn)發(fā)CPU 端口更是需要顯式配置。要把數(shù)據(jù)從某個(gè) LAN 口送到主控的內(nèi)核協(xié)議棧必須做兩件事讓 CPU 端口成為交換矩陣的成員端口并且配置 VLAN 和端口成員關(guān)系。YT9215 的寄存器空間里有一組端口控制寄存器我用 MDIO 寫的方式逐一配置端口使能和端口模式。常見配置是把所有端口設(shè)為千兆全雙工同時(shí)使能 802.1Q 的 VLAN 感知功能。最小化的配置是把所有 LAN 口劃入同一個(gè) VLAN ID比如 VLAN 1CPU 端口也加入這個(gè) VLAN這樣從 LAN 口收到的 untagged 數(shù)據(jù)幀會(huì)被打上 VLAN 1 的標(biāo)簽并轉(zhuǎn)發(fā)到 CPU 端口。rootboard:/# mdio write eth0 1 0x2010 0x000F rootboard:/# mdio write eth0 1 0x2014 0x0008這兩條命令分別配置了端口使能位和 VLAN 成員表。寄存器地址的偏移量每顆芯片略有差異我這里寫的地址是 YT9215 一類芯片的常見布局實(shí)際使用時(shí)要以 datasheet 的寄存器偏移為準(zhǔn)。這一步最容易翻車的地方就是把 CPU 端口的標(biāo)簽位配錯(cuò)。有些交換芯片要求 CPU 端口收上來的幀帶一個(gè)自定義的 tag不配置這個(gè) tag 識(shí)別規(guī)則CPU 收到幀后會(huì)被網(wǎng)卡驅(qū)動(dòng)當(dāng)成錯(cuò)誤幀丟掉。配置完成后用 tcpdump 在 eth0 上抓包從某個(gè) LAN 口接一臺(tái) PC 發(fā) ping 包。tcpdump 如果能收到 ICMP 請(qǐng)求幀說明轉(zhuǎn)發(fā)路徑已經(jīng)通了。如果只能收到廣播幀但收不到單播幀通常是 VLAN 設(shè)置里端口間的單播地址學(xué)習(xí)沒有打開需要查地址學(xué)習(xí)相關(guān)的寄存器。4.3 軟件轉(zhuǎn)發(fā)還是硬件轉(zhuǎn)發(fā)DSA 與普通 PHY 的選擇YT9215 在 Linux 里的角色定位會(huì)影響后續(xù)開發(fā)的復(fù)雜度是把整顆芯片當(dāng)作一個(gè) DSA switch 接入內(nèi)核還是簡(jiǎn)單地當(dāng)作多路 PHY 來使用這是需要權(quán)衡的。DSA 方式能讓 YT9215 的各個(gè)端口在 Linux 里分別顯示為獨(dú)立的網(wǎng)絡(luò)接口比如 lan1、lan2、wan每個(gè)口可以獨(dú)立配置 IP、防火墻、流量策略內(nèi)核的 bridge、VLAN 子系統(tǒng)天然適配。但 DSA 驅(qū)動(dòng)要求芯片的寄存器接口符合 Linux 的 dsa_switch_ops 定義YT9215 如果沒有現(xiàn)成的 DSA 驅(qū)動(dòng)就需要自己實(shí)現(xiàn)一套 port_vlan_add、port_stp_state_set 等回調(diào)函數(shù)工作量不小。另一種思路是把 YT9215 當(dāng)作一個(gè)多端口的 PHY 組所有 LAN 口在硬件上直接做二層轉(zhuǎn)發(fā)CPU 端口收到的數(shù)據(jù)全部進(jìn) eth0再由軟件做路由或橋接。這種模式適合流量不需要在單個(gè)端口之間做硬件隔離的場(chǎng)景配置量小但缺點(diǎn)是 VLAN、速率控制、端口統(tǒng)計(jì)相關(guān)的功能都要自己去寫寄存器操作。我在網(wǎng)關(guān)類項(xiàng)目里通常會(huì)選擇 DSA 方式因?yàn)楹罄m(xù)維護(hù)功能時(shí)內(nèi)核的標(biāo)準(zhǔn)接口能省下大量代碼和時(shí)間。如果只是要快速出一個(gè) Demo 驗(yàn)證硬件選擇后者更快落地。5. 避坑調(diào)試 YT9215 時(shí)最容易翻車的五個(gè)點(diǎn)5.1 復(fù)位引腳釋放時(shí)序不對(duì)導(dǎo)致設(shè)備偶發(fā)失聯(lián)現(xiàn)象板子第一次上電能識(shí)別到 YT9215但軟件重啟之后設(shè)備經(jīng)常消失必須徹底斷電再上電才能恢復(fù)。有少數(shù)板卡表現(xiàn)為溫度降低后概率明顯上升看起來非常像硬件虛焊。原因YT9215 的復(fù)位釋放時(shí)序要求比普通 PHY 嚴(yán)格。系統(tǒng)復(fù)位時(shí) GPIO 拉高的時(shí)間如果在電源電壓還沒完全穩(wěn)定的窗口內(nèi)芯片內(nèi)部邏輯可能進(jìn)入不可恢復(fù)狀態(tài)PCIe link training 永遠(yuǎn)失敗。軟件重啟不觸發(fā)大電容完全放電所以每次軟復(fù)位都在賭時(shí)序恰好正確。解決把復(fù)位控制從默認(rèn)的 GPIO 操作改到硬件復(fù)位芯片上或者在設(shè)備樹里通過 pinctrl 控制復(fù)位引腳確保復(fù)位引腳默認(rèn)拉低、系統(tǒng)啟動(dòng)后期再拉高。更穩(wěn)妥的辦法是在驅(qū)動(dòng)里加上一段延時(shí)操作從復(fù)位釋放到訪問芯片寄存器之間至少留 100ms 的等待時(shí)間。5.2 MDIO 讀到的 PHY ID 全是 0xFFFF現(xiàn)象mdio read 命令執(zhí)行正常但讀 PHY ID 寄存器返回的結(jié)果全部是 0xFFFF而且讀取沒有任何報(bào)錯(cuò)提示。設(shè)備樹里無論怎么寫 reg 都無法讀到有效 ID。原因這個(gè)現(xiàn)象通常不是 MDIO 總線故障而是 MDIO 地址根本沒有映射到正確的 PHY。YT9215 有多個(gè)內(nèi)部 PHY每個(gè) PHY 都有一個(gè)獨(dú)立的 MDIO 地址地址由芯片外部引腳配置。讀 0xFFFF 意味著該地址上沒有任何 PHY 響應(yīng)或者 MDIO 控制器時(shí)鐘配置太快芯片來不及在規(guī)定的時(shí)序窗口內(nèi)回復(fù)。解決先用邏輯分析儀抓 MDIO 波形確認(rèn) MDC/MDIO 信號(hào)確實(shí)有活動(dòng)。然后檢查設(shè)備樹里 MDIO clock 頻率許多 RK3568 方案的默認(rèn)配置是 2.5MHz如果 YT9215 要求 2.0MHz 以下就會(huì)偶發(fā)讀不到數(shù)據(jù)。最后核對(duì)板卡原理圖上 PHYAD 引腳的連接是否存在浮空或者接錯(cuò)的情況。5.3 CPU 端口能收到廣播卻收不到單播現(xiàn)象從 PC 連續(xù) ping 板卡 IPtcpdump 在 eth0 上只能看到 ARP 請(qǐng)求看不到 ICMP echo 幀。同一時(shí)刻PC 上的 ARP 表里板卡地址的狀態(tài)是 incomplete。原因這是典型的地址學(xué)習(xí)表問題。YT9215 的端口之間默認(rèn)可能禁用 MAC 地址學(xué)習(xí)或者學(xué)習(xí)到的地址表項(xiàng)沒有自動(dòng)老化刷新。CPU 端口的單播轉(zhuǎn)發(fā)依賴 FDB 表項(xiàng)而 FDB 表項(xiàng)需要交換芯片在收到源地址時(shí)更新。地址學(xué)習(xí)被關(guān)掉單播幀就無法反向查找端口只能被丟掉。解決找到地址學(xué)習(xí)控制寄存器顯式使能所有端口的學(xué)習(xí)功能。同時(shí)確認(rèn)發(fā)貨缺省配置里 FDB 的靜態(tài)表項(xiàng)沒有被設(shè)置成錯(cuò)誤的手動(dòng)綁定。如果學(xué)習(xí)和老化都正常但依然丟單播查一下端口之間是否存在 STP 狀態(tài)位被設(shè)為 blocking也會(huì)產(chǎn)生同樣的癥狀。5.4 VLAN 標(biāo)簽在 CPU 端口上未被剝離現(xiàn)象eth0 抓包能看到 VLAN ID 存在但板卡不能訪問外部網(wǎng)關(guān)。內(nèi)部 LAN 口之間互通正常但只要涉及 CPU 收發(fā)的數(shù)據(jù)就全部異常tcpdump 里能看到大量的 vlan 100 標(biāo)簽。原因交換芯片把從 LAN 口進(jìn)入的 untagged 數(shù)據(jù)自動(dòng)打上了 PVID轉(zhuǎn)發(fā)到 CPU 端口時(shí)幀完整保留了這個(gè) tag。但 RK3568 的 stmmac 驅(qū)動(dòng)默認(rèn)沒有啟用 VLAN 處理接收到帶 tag 的幀后要么錯(cuò)誤地提交到協(xié)議棧后被丟棄要么直接在硬件層過濾掉。解決配置 CPU 端口為 tag 剝離模式所有發(fā)往 CPU 的幀由芯片先去 tag?;蛘叻催^來在內(nèi)核里把 eth0 的 vlan 接收功能顯式打開用 vlan 子接口去匹配對(duì)應(yīng)的 VID。我通常推薦前者改動(dòng)只涉及一組寄存器而且對(duì)系統(tǒng)路由的影響最小。5.5 吞吐量只有百兆但鏈路顯示 1000Mbps現(xiàn)象鏈路協(xié)商是千兆全雙工但通過 iperf3 測(cè)速穩(wěn)定在 95Mbps 左右而且無論換 PC 換網(wǎng)線結(jié)果都一樣。CPU 占用率不高網(wǎng)卡 ethtool 統(tǒng)計(jì)沒看到大量丟包。原因這種情況基本可以斷定是 SerDes 的工作模式配置問題。YT9215 的某些 SerDes 通道被復(fù)用成千兆接口時(shí)如果對(duì)應(yīng)寄存器沒有設(shè)置成正確的速率匹配組物理層會(huì)在協(xié)商時(shí)撒謊報(bào)告千兆但實(shí)際上內(nèi)部串口跑在百兆速率。另一個(gè)常見誘發(fā)點(diǎn)是 PCB 上的差分走線阻抗嚴(yán)重不匹配但一般硬件評(píng)審會(huì)擋掉這種問題軟件配置出錯(cuò)更常見。解決把涉及 SerDes 速率匹配的寄存器全部重讀一遍重點(diǎn)看強(qiáng)制速率位和 auto-neg 配置位的組合是否合法。不要只依賴 ethtool 的協(xié)商結(jié)果用 iperf3 打流做實(shí)測(cè)通過不同速率下的吞吐對(duì)比來判斷 SerDes 配置是否生效。6. 把鏈路質(zhì)量釘死iperf3 與 tcpdump 的組合驗(yàn)證6.1 一次完整的鏈路驗(yàn)證流程配置完成后單純 ping 通并不能說明系統(tǒng)能長(zhǎng)期穩(wěn)定運(yùn)行。我會(huì)用 iperf3 做雙向打流驗(yàn)證同時(shí)配合 tcpdump 抓包確認(rèn)轉(zhuǎn)發(fā)路徑中不存在隱藏的重傳或亂序。先做單方向的 TCP 打流再做雙向同時(shí)打流這一步能暴露交換芯片緩沖區(qū)在擁塞場(chǎng)景下的行為。rootboard:/# iperf3 -s rootboard:/# iperf3 -c 192.168.10.1 -t 60 -P 4在打流過程中tcpdump 的統(tǒng)計(jì)結(jié)果能清楚看到每個(gè) 5 秒窗口里的重傳數(shù)和亂序包數(shù)量。這個(gè)數(shù)值在空閑系統(tǒng)里應(yīng)當(dāng)接近零如果持續(xù)增長(zhǎng)基本可以判斷交換芯片的隊(duì)列管理策略有問題或者 CPU 端口描述符緩沖區(qū)太小。通過 ethtool 查看網(wǎng)卡錯(cuò)誤計(jì)數(shù)也能快速區(qū)分是 MAC 層問題還是交換芯片轉(zhuǎn)發(fā)能力問題。6.2 中斷綁核與系統(tǒng)級(jí)調(diào)優(yōu)的邊界RK3568 是四核處理器網(wǎng)絡(luò)中斷默認(rèn)可能落在 CPU0。當(dāng)批量轉(zhuǎn)發(fā)同時(shí)還有業(yè)務(wù)進(jìn)程運(yùn)行時(shí)CPU0 容易成為瓶頸。通過 /proc/irq 接口把網(wǎng)卡中斷綁到 CPU2 或 CPU3 上配合 RPSReceive Packet Steering進(jìn)一步分散軟中斷負(fù)載。但要清醒認(rèn)識(shí)一個(gè)邊界YT9215 的硬件轉(zhuǎn)發(fā)能力遠(yuǎn)超 RK3568 的軟件處理能力在千兆模式下 CPU 是瓶頸而不是交換芯片所以系統(tǒng)調(diào)優(yōu)能改善的幅度是有限的。做完吞吐驗(yàn)證和中斷綁定之后系統(tǒng)才算真正達(dá)到了交付狀態(tài)。我記得第一次在模擬項(xiàng)目X上把 YT9215 徹底調(diào)通那天結(jié)果反而沒有想象中興奮因?yàn)檎麄€(gè)調(diào)試過程中反復(fù)出現(xiàn)的都是這些小問題——時(shí)序、地址、標(biāo)簽剝離沒有一項(xiàng)涉及高深技術(shù)但每一項(xiàng)都足以卡住一兩天。從那以后我的習(xí)慣變了拿到板子先做硬件清單核對(duì)再寫驅(qū)動(dòng)順序絕不調(diào)換。這套方法在后續(xù)幾個(gè)項(xiàng)目上一直沿用希望能幫到你。本文還有配套的精品資源點(diǎn)擊獲取