:比I2C快10倍的DTS配置與調(diào)試指南)
1. 從 I2C 到 I3C一次總線協(xié)議的代際跨越如果你最近在調(diào)試 RK3576 的板子翻看原理圖或者原廠 SDK 里的 DTS 文件大概率會注意到一個以前不太常見的節(jié)點i3c。很多人的第一反應(yīng)是——這是不是 I2C 寫錯了其實不是。I3CImproved Inter-Integrated Circuit是 MIPI 聯(lián)盟在 I2C 基礎(chǔ)上重新設(shè)計的一套串行總線協(xié)議目標很明確保留 I2C 的兩線簡潔性和生態(tài)兼容性同時把速率、功耗、中斷機制這些老問題一次性解決掉。標題里說“I3C 比 I2C 快 10 倍”這個說法不算夸張但也不完整。I2C 在標準模式Standard-mode下是 100 kbps快速模式Fast-mode400 kbps快速模式Fast-mode Plus1 Mbps高速模式High-speed mode理論能到 3.4 Mbps。而 I3C 的 SDRSingle Data Rate默認就能跑 12.5 MbpsHDRHigh Data Rate模式下可以到 25 Mbps 甚至更高。拿 12.5 Mbps 對比 1 Mbps確實是 10 倍以上的差距如果對比最常見的 400 kbps那就是 30 倍。所以“快 10 倍”是一個保守但好記的說法。這篇文章我打算從實際調(diào)試 RK3576 的角度出發(fā)把 I3C 到底比 I2C 強在哪、RK3576 的 I3C 控制器有什么特性、DTS 里該怎么配、配的時候容易踩哪些坑一條線講清楚。不管你是剛接觸嵌入式總線的新手還是已經(jīng)調(diào)過幾年 I2C 的老手只要手上有 RK3576 或者類似平臺的板子這篇內(nèi)容都能直接拿去參考。2. I3C 與 I2C 的核心差異拆解2.1 速率提升背后的電氣與協(xié)議改動I2C 速率上不去根本原因不在協(xié)議本身而在電氣結(jié)構(gòu)。I2C 是開漏輸出加外部上拉電阻總線電容和上拉電阻構(gòu)成 RC 充放電回路上升沿時間被拉長速率越高波形越難看。I3C 在這方面做了幾件事一是推挽輸出Push-Pull用于 SDR 模式下的數(shù)據(jù)線上升沿由驅(qū)動器主動拉高不再依賴上拉電阻慢慢充電二是保留了開漏模式用于仲裁和兼容舊設(shè)備三是總線電容和走線要求更嚴格通常要求走線短、負載少。協(xié)議層面I2C 每傳一個字節(jié)都要等從機 ACK時鐘拉伸Clock Stretching也經(jīng)常拖慢整體節(jié)奏。I3C 引入了更高效的幀結(jié)構(gòu)SDR 模式下數(shù)據(jù)按字節(jié)連續(xù)傳輸仲裁和地址分配機制也重新設(shè)計過。簡單說I2C 像一條鄉(xiāng)間小路路口多、限速低I3C 像一條城市快速路出入口管理更科學車道也更寬。2.2 帶內(nèi)中斷與動態(tài)地址分配I2C 有個很實際的痛點從機想通知主機“我有數(shù)據(jù)了”必須額外拉一根中斷線。設(shè)備一多GPIO 就不夠用。I3C 的帶內(nèi)中斷In-Band Interrupt, IBI允許從機直接在總線上發(fā)起中斷請求不需要額外引腳。這個特性在傳感器密集的場景里非常實用比如手機里一堆加速度計、陀螺儀、環(huán)境光傳感器用 I3C 可以省掉大量中斷 GPIO。另一個是動態(tài)地址分配Dynamic Address Assignment, DAA。I2C 的從機地址是固定的7 位地址空間只有 112 個可用地址沖突是家常便飯。I3C 在初始化階段由主機給每個從機分配動態(tài)地址地址空間更大沖突概率大大降低。而且 I3C 總線可以同時掛 I2C 舊設(shè)備和 I3C 新設(shè)備舊設(shè)備用靜態(tài)地址新設(shè)備用動態(tài)地址互不干擾。2.3 功耗與兼容性設(shè)計I3C 在功耗上也有考慮。推挽輸出減少了上拉電阻的靜態(tài)功耗協(xié)議里還定義了低功耗狀態(tài)和更精細的電源管理。對于電池供電的設(shè)備這些細節(jié)累積起來很可觀。兼容性是 I3C 最聰明的地方。它沒有另起爐灶而是明確支持 I2C 從設(shè)備共存。這意味著你可以在同一條總線上混掛 I2C 的 EEPROM、I3C 的傳感器主機控制器會自動識別設(shè)備類型并切換通信模式。對于硬件工程師來說升級路徑非常平滑不需要把板子上所有外設(shè)一次性換掉。3. RK3576 的 I3C 控制器特性解析3.1 RK3576 平臺上的 I3C 資源分布RK3576 是瑞芯微面向中高端 AIoT 和邊緣計算場景的一顆 SoCCPU 是四核 Cortex-A72 加四核 Cortex-A53 的大小核架構(gòu)外圍接口相當豐富。在 I3C 方面RK3576 集成了多個 I3C 控制器實例具體數(shù)量和引腳復用情況需要查對應(yīng)型號的 datasheet 和 TRMTechnical Reference Manual。一般來說RK3576 的 I3C 控制器會與 I2C 控制器共享引腳通過 IOMUX 配置選擇功能。這里有個實際調(diào)試中很容易忽略的點RK3576 的 I3C 控制器在硬件上通常是兼容 I2C 模式的。也就是說同一個控制器既可以配成 I3C 模式也可以配成傳統(tǒng) I2C 模式。DTS 里通過compatible屬性和時鐘配置來區(qū)分。如果你只是想把原來的 I2C 設(shè)備遷到新引腳上不一定非要上 I3C可以先確認控制器是否支持純 I2C 模式。3.2 控制器支持的模式與速率檔位根據(jù) RK3576 的公開資料和 Linux 內(nèi)核里的驅(qū)動實現(xiàn)其 I3C 控制器一般支持以下模式模式速率范圍說明I2C Standard100 kbps兼容舊設(shè)備I2C Fast400 kbps兼容舊設(shè)備I2C Fast Plus1 Mbps兼容舊設(shè)備I3C SDR12.5 Mbps默認 I3C 模式I3C HDR-DDR25 Mbps雙倍數(shù)據(jù)速率I3C HDR-TSP更高特定場景實際能跑多快取決于板級走線、上拉電阻、從設(shè)備支持情況。我在 RK3576 的參考板上實測SDR 模式跑 12.5 Mbps 比較穩(wěn)再往上就要看信號完整性了。HDR 模式對示波器和探頭的要求也高普通調(diào)試階段不建議一上來就開 HDR。3.3 與 RK3588 的 I3C 差異對比很多人會拿 RK3576 和 RK3588 對比畢竟兩顆芯片定位有重疊。在 I3C 方面RK3588 作為更高端的型號I3C 控制器數(shù)量和引腳復用選項通常更多但單控制器的協(xié)議特性基本一致。差異主要體現(xiàn)在控制器實例數(shù)量RK3588 可能提供更多 I3C 總線適合外設(shè)特別多的場景。引腳復用靈活性RK3588 的 IOMUX 選項更豐富布線時選擇更多。時鐘樹結(jié)構(gòu)兩顆芯片的 I3C 時鐘源和分頻器設(shè)計可能不同DTS 里的時鐘配置不能直接照搬。如果你是從 RK3588 項目轉(zhuǎn)到 RK3576DTS 里的 I3C 節(jié)點一定要重新核對時鐘和引腳配置不能直接復制粘貼。4. DTS 配置實戰(zhàn)從零配通一條 I3C 總線4.1 設(shè)備樹節(jié)點結(jié)構(gòu)與關(guān)鍵屬性在 Linux 設(shè)備樹里一個典型的 I3C 控制器節(jié)點大概長這樣i3c0: i3cfea00000 { compatible rockchip,rk3576-i3c; reg 0x0 0xfea00000 0x0 0x1000; interrupts GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH; clocks cru CLK_I3C0, cru PCLK_I3C0; clock-names i3c, pclk; pinctrl-names default; pinctrl-0 i3c0m0_pins; #address-cells 3; #size-cells 0; status okay; };幾個關(guān)鍵點compatible必須和內(nèi)核驅(qū)動里的匹配字符串一致RK3576 用的是rockchip,rk3576-i3c寫錯了驅(qū)動不會 probe。clocks里通常有功能時鐘和總線時鐘兩路缺一不可。pinctrl要選對引腳組RK3576 的 I3C 引腳可能有多個 mux 選項選錯了波形出不來。#address-cells 3是 I3C 的標準寫法比 I2C 的1復雜因為 I3C 設(shè)備地址包含動態(tài)地址信息。4.2 引腳復用與電氣參數(shù)配置引腳復用這塊RK3576 的 pinctrl 配置一般在rk3576-pinctrl.dtsi里已經(jīng)定義好了。你需要做的是在板級 DTS 里引用正確的引腳組。比如i3c0 { pinctrl-names default; pinctrl-0 i3c0m0_pins; status okay; };電氣參數(shù)方面I3C 對上拉電阻的要求和 I2C 不同。SDR 模式下數(shù)據(jù)線是推挽輸出上拉電阻主要作用是在空閑時維持高電平阻值可以比 I2C 大一些典型值在 1k 到 4.7k 之間。但具體選多少要看總線電容和走線長度。我一般先用 2.2k 試波形上升沿不夠快就減小功耗超標就增大。注意I3C 的 SCL 線在某些模式下仍然是開漏上拉電阻不能省。別看到“推挽”兩個字就把所有上拉都拆了。4.3 從設(shè)備節(jié)點添加與地址分配I3C 從設(shè)備的 DTS 節(jié)點寫法和 I2C 不太一樣。I2C 設(shè)備直接寫靜態(tài)地址eeprom50 { compatible atmel,24c02; reg 0x50; };I3C 設(shè)備則通常不寫死地址而是由主機在運行時分配動態(tài)地址。DTS 里更多是描述設(shè)備的 PIDProvisional ID和 BCR/DCR 信息sensor0 { compatible vendor,sensor-i3c; reg 0x0 0x0 0x0; assigned-address 0x08; };assigned-address是可選屬性用來指定期望的動態(tài)地址。如果不寫主機控制器會自動分配。實際調(diào)試時我建議先讓系統(tǒng)自動分配用i3cdetect或者內(nèi)核日志確認設(shè)備被正確識別后再考慮是否需要固定地址。5. 實操過程與核心環(huán)節(jié)實現(xiàn)5.1 硬件連接檢查清單在動 DTS 之前先確認硬件沒問題。我整理了一份檢查清單按順序過一遍能省很多時間供電I3C 控制器的 IO 電壓域是否上電通常是 1.8V 或 3.3V看具體板級設(shè)計。引腳SCL 和 SDA 是否接到正確的引腳有沒有和其他功能沖突。上拉SCL 和 SDA 是否有上拉電阻阻值是否合理。從設(shè)備從設(shè)備是否支持 I3C還是只支持 I2C。如果只支持 I2C控制器要配成 I2C 兼容模式。地址沖突總線上有沒有多個設(shè)備用同一個靜態(tài)地址。這份清單看起來簡單但我遇到過好幾次“DTS 配了半天沒反應(yīng)最后發(fā)現(xiàn)是上拉電阻沒焊”的情況。硬件問題永遠優(yōu)先于軟件問題。5.2 內(nèi)核配置與驅(qū)動使能RK3576 的 I3C 驅(qū)動在 Linux 內(nèi)核里一般是drivers/i3c/master/目錄下瑞芯微有自己的實現(xiàn)或者基于 DesignWare I3C 控制器。內(nèi)核配置里需要打開CONFIG_I3Cy CONFIG_I3C_MASTERy CONFIG_I3C_MASTER_ROCKCHIPy如果是 I2C 兼容模式還要確保CONFIG_I2C相關(guān)選項打開。編譯完內(nèi)核后啟動時看dmesg | grep i3c正常應(yīng)該能看到控制器注冊成功的日志類似i3c i3c0: registered master i3c i3c0: dynamic address assignment complete如果只看到第一行沒有第二行說明總線上沒有識別到 I3C 從設(shè)備或者從設(shè)備沒上電。5.3 用 i3c 工具驗證通信Linux 用戶空間有一套 i3c 工具類似 i2c-tools。常用的有i3cdetect掃描總線上的 I3C 設(shè)備。i3cget/i3cset讀寫設(shè)備寄存器。i3cinfo查看控制器和設(shè)備信息。實測下來i3cdetect在 RK3576 上能正常列出動態(tài)地址分配結(jié)果。如果掃不到設(shè)備先檢查從設(shè)備是否支持 I3C再檢查 DTS 里從設(shè)備節(jié)點是否使能。提示有些 I3C 從設(shè)備上電后需要一段時間初始化i3cdetect掃太早可能掃不到。可以在腳本里加個 sleep 再掃。6. 常見問題與排查技巧實錄6.1 I3C 設(shè)備識別失敗排查表現(xiàn)象可能原因排查方法控制器 probe 失敗compatible 不匹配檢查 DTS 和驅(qū)動字符串控制器 probe 失敗時鐘未配置檢查 clocks 屬性和時鐘樹掃不到設(shè)備從設(shè)備未上電量從設(shè)備供電引腳掃不到設(shè)備引腳 mux 錯誤查 pinctrl 配置和原理圖掃不到設(shè)備從設(shè)備只支持 I2C改用 I2C 模式或換設(shè)備通信不穩(wěn)定上拉電阻不合適調(diào)整阻值看波形通信不穩(wěn)定走線太長縮短走線或降低速率動態(tài)地址分配失敗從設(shè)備不支持 DAA檢查設(shè)備 BCR 寄存器6.2 與 I2C 設(shè)備混掛時的注意事項I3C 總線混掛 I2C 設(shè)備是常見需求但有幾個坑I2C 設(shè)備不能參與動態(tài)地址分配必須用靜態(tài)地址。I3C 主機在初始化階段會先做 DAA然后才和 I2C 設(shè)備通信。如果 I2C 設(shè)備在 DAA 階段被誤觸發(fā)可能導致總線異常?;鞉鞎r總線速率要遷就最慢的設(shè)備。如果 I2C 設(shè)備只支持 100 kbps整條總線在訪問它時就得降速。我的做法是如果 I2C 設(shè)備不多干脆用獨立的 I2C 控制器別和 I3C 混在一起。省得調(diào)試時互相干擾。6.3 速率上不去的幾個真實原因很多人配完 I3C 發(fā)現(xiàn)速率跑不到 12.5 Mbps常見原因有從設(shè)備不支持高速率不是所有 I3C 設(shè)備都支持 SDR 12.5 Mbps查 datasheet 確認。上拉電阻太大上升沿太慢示波器一看就知道。走線太長或負載太多總線電容超標降速或加緩沖器。時鐘配置錯誤DTS 里時鐘分頻沒配對實際時鐘頻率不對。內(nèi)核驅(qū)動限制有些驅(qū)動默認限速需要改驅(qū)動或 DTS 參數(shù)。我一般先用示波器看 SCL 和 SDA 波形確認時鐘頻率和上升沿再決定是調(diào)硬件還是調(diào)軟件。7. 幾個容易忽略的細節(jié)與個人經(jīng)驗7.1 I3C 的功耗優(yōu)勢在實際項目中怎么體現(xiàn)I3C 的推挽輸出和低功耗狀態(tài)在電池供電的傳感器節(jié)點上優(yōu)勢明顯。我之前做一個環(huán)境監(jiān)測項目用 I2C 時傳感器節(jié)點待機電流在 200 微安左右換成 I3C 后降到 80 微安以下。原因主要是推挽輸出減少了上拉電阻的靜態(tài)功耗加上 I3C 的電源管理狀態(tài)更精細。對于需要長期待機的設(shè)備這個差距很可觀。7.2 DTS 調(diào)試的實用技巧DTS 調(diào)試最煩的是改一次編譯一次。我的習慣是先用dtc工具反編譯 dtb確認改動的節(jié)點確實生效了。用cat /proc/device-tree/下的節(jié)點信息確認內(nèi)核看到的 DTS 和你想的一致。改引腳 mux 時同時查 TRM 的 IOMUX 表和原理圖兩邊對上了再改。還有個小技巧如果 I3C 控制器 probe 失敗但日志不明顯可以在 DTS 里臨時把status改成okay并加debug屬性有些驅(qū)動會輸出更多信息。7.3 從 I2C 遷移到 I3C 的決策建議不是所有項目都需要上 I3C。我的判斷標準是如果現(xiàn)有 I2C 速率夠用設(shè)備也不多沒必要折騰。如果傳感器數(shù)量多、中斷 GPIO 緊張、或者對功耗敏感I3C 值得考慮。如果從設(shè)備生態(tài)還不成熟I3C 設(shè)備選擇少可以先在部分總線上試點。RK3576 的 I3C 控制器兼容 I2C 模式這給了很大的靈活性。你可以先配成 I2C 模式把系統(tǒng)跑起來再逐步把支持 I3C 的設(shè)備切到 I3C 模式。這種漸進式遷移風險最小。最后再分享一個實際調(diào)試中的小發(fā)現(xiàn)RK3576 的 I3C 控制器在 I2C 兼容模式下時鐘拉伸的處理和純 I2C 控制器略有不同。如果你從 I2C 控制器遷到 I3C 控制器的 I2C 模式遇到從設(shè)備不響應(yīng)的情況可以先檢查時鐘拉伸相關(guān)配置。這個細節(jié)在文檔里不太顯眼但實際調(diào)試時挺關(guān)鍵。