
1. SPI3 沒信號送出的現場形態先搞清楚問題到底長什么樣先交代一下背景。最近在調一塊板子主控是某款 Cortex-A 系列處理器板載一個 SPI3 接口外接到一顆 NOR Flash 和一片 LCD 驅動芯片。同事反饋說接口“完全沒信號”我拎著示波器過去一看CLK、MOSI、CS 三個引腳全部平得像心電圖停跳一根毛刺都看不到。這里要插一句“SPI3 接口沒有信號送出”這個描述在實際工程里至少能拆成好幾種完全不同的現象排查方向完全不一樣。現象 ACLK、MOSI、CS 全部無波形像沒初始化過一樣。現象 BCLK 有時鐘輸出但 MOSI 上什么都沒有CS 也不動。現象 CCLK、MOSI 都有但 CS 一直是高電平從機根本沒被選中。現象 D主控這邊的信號都有但到了連接器/排線那一端就沒了中間鏈路斷了。現象 E所有信號都有但電平幅度不對比如 1.8V 的主控接 3.3V 的外設中間電平轉換沒工作。我遇到的屬于現象 A但下面的排查思路對 B、C、D、E 同樣適用。先說一個最容易犯的認知錯誤很多人一聽到“SPI3”就默認它一定存在但 SPI3 這個編號的含義在不同平臺上有兩種常見解釋。一種解釋是 SoC 內部的第 3 個 SPI 控制器比如 i.MX6 的 ECSPI3、STM32H7 的 SPI3、樹莓派 BCM2711 的 SPI3 控制器另一種解釋是 SPI 工作在三線制模式即只有 CLK、MOSI雙向和 CS沒有獨立的 MISO。這兩種情況下的排查手法差別很大。我先按“第 3 個 SPI 控制器”來展開因為這是絕大多數嵌入式項目里遇到的情況三線制模式會在后面單獨說。在動手之前先把問題域收窄。SPI 是一個同步串行接口主控要發出完整的傳輸事務必須同時滿足時鐘線有翻轉、數據線有正確的電平變化、片選線有有效的拉低動作。這三根線只要有一根不對從設備就不會響應而工程師往往只看到“沒信號”這個籠統現象。所以第一步不是去懷疑某個寄存器而是用示波器把四根線CLK、MOSI、MISO、CS全部掛上看看到底哪根沒有、哪根有、哪根波形不對。如果四根線全部平直那問題幾乎可以肯定出在主控側要么外設時鐘沒使能要么引腳復用沒配要么控制器根本沒被初始化。如果 CLK 有而其他沒有往往是傳輸事務沒有真正啟動比如片選極性配置錯誤導致 CS 一直處于無效電平或者發送緩沖區為空。如果主控側波形完整但下游沒有那就是鏈路中間的問題比如電平轉換方向控制腳沒拉對、連接器虛焊、排線斷了。我習慣用一個比喻來給剛入行的同事解釋SPI 就像一場有主持人的電話會議CLK 是主持人打節拍的拍子CS 是“現在開始點名”的信號MOSI 是主持人說的話MISO 是參會者的回答。拍子沒響、沒點名、沒人說話任何一個環節斷了會議都開不起來。排查 SPI3 沒信號本質上就是沿著這條“會議鏈路”逐段檢查看是主持人的問題、接線的問題還是話筒的問題。2. 從引腳到時鐘樹SPI3 信號鏈路到底包含哪些環節確定現象之后下一步是把 SPI3 從“軟件寄存器”到“物理引腳”的完整鏈路畫在腦子里。很多人排查時喜歡一上來就翻代碼但我建議先打開原理圖從主控芯片的引腳一路看到對外連接器把每個環節都過一遍。大多數 SPI3 無聲問題根源不是 SPI 控制器本身而是鏈路中間的某個“隱形開關”沒打開。2.1 引腳復用最高頻的翻車點現代 SoC 的引腳基本都是多功能引腳同一個物理引腳可能同時掛著 UART、I2C、PWM、GPIO、SPI 等多組功能。芯片上電默認狀態往往是 GPIO 模式而且經常是帶上拉或下拉的 GPIO。如果軟件里沒有把該引腳切換成 SPI3 的復用功能那么即使 SPI 控制器已經在跑時鐘也翻轉了信號也到了引腳內部但引腳仍然以 GPIO 模式輸出表現為“寄存器看起來在工作示波器上看不到波形”。這里有個特別容易踩的坑復用功能寄存器寫入的值必須在具體芯片手冊里查不能想當然。不同芯片對相同外設的 ALT 編號可能完全不同。比如某顆芯片上 SPI3_MOSI 的復用功能是 ALT2另一顆同系列的芯片卻可能變成 ALT5。我見過不止一次有同事拿著上一顆芯片的設備樹直接改型號就上結果 SPI3 引腳全部處于 GPIO 模式死活沒波形。檢查方法很簡單讀芯片手冊的“Pin Multiplexing”章節找到 SPI3 相關引腳確認當前代碼里寫的 mux 值對應的是 SPI3 功能。如果用的是 Linux 下的設備樹重點檢查 pinctrl 節點里的pinctrl-0和pinctrl-names是否真的被 SPI3 驅動引用到了。2.2 SPI 控制器時鐘樹不開時鐘寄存器全是空氣引腳復用配對了接下來要看時鐘樹。SPI 控制器本身是一個數字外設它需要兩路時鐘一路是總線接口時鐘用來訪問寄存器另一路是外設功能時鐘用來產生 SPI 的 SCK 信號。在很多 SoC 上這兩路時鐘是獨立的門控位也可能分開。外設功能時鐘沒打開是“SPI3 完全沒有信號”的第二大常見原因。這時候寄存器能讀寫控制器狀態寄存器也顯示 enabled但 SCK 引腳就是沒有任何輸出因為波特率發生器沒有時鐘源產生的 SCK 頻率是 0。排查手段是在驅動里讀取時鐘狀態寄存器確認 SPI3 的CKEN或類似門控位已經置 1。如果是 Linux 環境檢查設備樹里 SPI3 節點的clocks屬性和assigned-clock-rates確保時鐘源頻率設置正確。用clk_summary或者/sys/kernel/debug/clk/clk_summary可以快速確認 SPI3 的時鐘樹是否 enable、頻率是多少。我遇到的這顆主控SPI3 的時鐘源來自一個 PLL 分頻PLL 默認狀態是關閉的必須由 bootloader 或內核初始化時打開。這就導致很多人只改了 SPI 驅動配置沒動時鐘樹結果 SPI3 寄存器訪問正常但沒有 SCK 輸出。檢查時鐘樹時我習慣先看/sys/kernel/debug/clk/clk_summary里 SPI3 相關節點的prepare_count和enable_count如果都是 0那基本可以斷定就是時鐘門控的問題。2.3 SPI 模式參數不是“有配置”就一定能通設好引腳和時鐘之后還要檢查 SPI 模式參數。SPI 有四種工作模式由 CPOL時鐘極性和 CPHA時鐘相位兩個參數組合而成。CPOL 決定空閑時 SCK 是高電平還是低電平CPHA 決定數據是在第一個邊沿還是第二個邊沿采樣。主從雙方必須匹配否則從機可能完全不響應甚至數據全錯。如果從機是 NOR Flash大多數器件支持 Mode 0 或 Mode 3。如果是從機是 LCD 驅動芯片不同型號支持的時序可能完全不同。如果 SPI3 接口接了多個從機一定要確認每個從機事務都用了正確的 mode而不是用一個全局配置通吃所有從機。在 Linux 下每個從設備節點都可以單獨配置spi-max-frequency和模式位別偷懶。另一個參數是數據位寬。STM32 的 SPI 外設默認是 8 位但有的 SoC 支持 4 位、16 位、32 位甚至可編程位寬。如果驅動里配置了 16 位而總線上的從機只支持 8 位波形看起來是有的但數據完全對不上。這次“沒信號”的現場里如果示波器上能看到 CLK 和數據線都有動作但數據內容不對先從位寬和模式檢查起。3. 硬件側排查實操示波器該夾哪里量什么波形軟件配置檢查完如果還是沒信號就該上硬件手段了。很多工程師在硬件排查時有個壞毛病拿起萬用表亂點一通點不出問題就一臉茫然。硬件排查必須按信號路徑逐段推進每推進一步都要能回答“這個節點上的信號應該長什么樣”。3.1 上電靜態測量先確認供電和電平域第一步是萬用表量電壓。量三個東西SPI3 相關引腳所在的電源域電壓是否正常。很多 SoC 有多個 VDDIO 域SPI3 可能在 1.8V 域也可能在 3.3V 域電壓不對引腳電平自然不對。引腳對地阻抗是否正常。SPI3 引腳如果對地短路信號會被直接拉低示波器上就是平的。量阻抗時最好在斷電狀態下測避免誤判。外部上拉/下拉電阻是否焊接正確。SPI 的 CS 引腳在系統里通常有上拉電阻保證空閑時處于高電平。如果這個上拉電阻沒焊或者焊到了錯誤的位置CS 可能一直懸空狀態不定。靜態測量能排除大概三成問題剩下的要看動態波形。3.2 動態波形測量探頭的掛法有講究我習慣用四通道示波器同時掛 CLK、MOSI、MISO、CS四根線一起看。如果沒有四通道至少也要保證 CLK 和 CS 同時看因為CS 的有效拉低是判斷一個 SPI 事務是否啟動的最直觀標志。探頭的接地夾要盡量靠近被測點最好用彈簧地針不要用長地線夾子。SPI 的時鐘頻率通常在幾 MHz 到幾十 MHz長地線會引入寄生電感導致波形上出現過沖和振鈴影響判斷。我見過有人拿著 60MHz 帶寬的示波器去量 50MHz 的 SPI 時鐘量出來的波形嚴重失真還以為是信號質量問題。觸發方式建議用 CS 下降沿觸發。CS 平時是高電平事務開始時拉低用這個沿觸發能穩定抓到整個事務的波形。如果 CS 一直沒有低電平出現說明事務根本沒有啟動如果 CS 有低電平而 CLK 沒有翻轉說明控制器認為自己在傳輸但波特率時鐘或分頻配置有問題如果 CS、CLK 都有而 MOSI 沒有說明發送數據寄存器是空的或者 DMA 沒有正確觸發。3.3 回環測試一句話區分“沒發出”和“沒收到”在排查 SPI3 沒信號的現場最快的一個定位手段是回環測試。直接把 MOSI 和 MISO 短接或者在軟件里把 SPI 配置成 loopback 模式然后發一串已知數據看能不能收回來。如果回環能收到說明 SPI 控制器的發送和接收路徑都正常問題在外部的從機設備、PCB 走線或連接器。如果回環收不到說明控制器本身可能就沒正常工作回到軟件配置和時鐘樹檢查。Loopback 有兩種實現方式一種是 SoC 自帶的硬件 loopback 模式在 SPI 控制器的配置寄存器里打開信號在芯片內部直接回環不經過引腳另一種是外部物理回環用導線或者 PCB 測試點把 MOSI 和 MISO 短接。外部回環比內部回環更能反映問題因為它把引腳復用、PCB 走線、連接器全鏈路都覆蓋了。我做外部回環時習慣在連接器的從機端做短接而不是在主控芯片引腳附近做。這樣如果回環成功說明從主控引腳到連接器這一段鏈路都是通的問題可以進一步縮小到從機端。3.4 電平轉換芯片的方向控制腳一個特別隱蔽的坑如果主控和從機的電壓域不同中間需要加電平轉換芯片比如 TXS0108、SN74LVC4245 之類。這類芯片的方向控制腳DIR、OE如果沒接對信號根本過不去。常見的坑是OE 腳應該拉低使能結果被懸空了DIR 腳方向接反導致數據從從機流向主機而不是從主機流向從機或者方向控制腳接到了某個 GPIO而該 GPIO 在軟件里沒有初始化。表現為 CPU 這邊的 SPI3 引腳有完整波形但電平轉換芯片輸出端什么都量不到。這種問題用示波器一夾就能發現但前提是你知道要在電平轉換芯片的輸入端和輸出端同時掛探頭對比。很多人在主控引腳上看到信號正常就以為整條鏈路都正常跳過了中間環節的測量這是排查效率低下的主要原因之一。4. 軟件配置里最容易埋雷的幾個位置如果說硬件排查是“看得見摸得著”的部分軟件配置就是“藏在代碼里”的部分。而且軟件配置的錯誤往往比硬件錯誤更隱蔽因為它不會在產品上留下任何物理痕跡只會在運行時表現為功能失效。4.1 設備樹或初始化結構體每個字段都得較真在 Linux 環境下SPI3 沒信號最常見的原因是設備樹節點沒有正確匹配到驅動。檢查的順序很重要我列一下我常用的核對清單檢查項典型錯誤排查方式compatible 字符串與驅動不匹配導致 probe 不執行dmesg里看是否有 spi3 相關 probe 信息reg 屬性控制器基地址寫錯訪問到無關寄存器對照芯片手冊確認基地址interrupts中斷號配置錯誤傳輸沒完成時無法觸發回調cat /proc/interrupts確認中斷是否產生pinctrl-0引腳復用配置未被引用引腳處于 GPIO 模式讀/sys/kernel/debug/pinctrl確認引腳狀態spi-max-frequency頻率設太高從機跟不上導致無響應先降到 1MHz 以下嘗試mode 位CPOL/CPHA 與從機不匹配對照從機數據手冊確認很多人看到設備樹里 SPI3 節點存在就默認驅動已經正常工作。但dmesg里如果出現spi3 supply spi not found或者failed to get clock說明還有依賴資源沒就緒。我排查時有個習慣先看dmesg | grep -i spi再看/dev/spidev3.0是否存在最后直接跑spidev_test工具發數據。4.2 時鐘使能與 GPIO 復用兩個最隱蔽的失敗點前面硬件部分已經提過時鐘但軟件側還要再強調一次很多時候不是芯片不支持而是驅動里的時鐘框架沒有正確使能 SPI3 的時鐘。在設備樹里配置了clocks屬性不代表時鐘已經打開驅動必須在probe函數里調用clk_prepare_enable()或者依賴運行時 PM 框架自動開時鐘。如果驅動本身的pm_runtime_enable沒調用或者時鐘的enable計數不對SPI3 就會處于“時鐘未使能”的狀態。GPIO 復用也一樣。設備樹里 pinctrl 節點存在不代表它生效。如果 SPI3 驅動和某個 GPIO 驅動同時請求了同一個物理引腳后加載的驅動可能把復用配置覆蓋掉。我在項目中遇到過一次某個按鍵驅動把 SPI3 的 CS 引腳當成了 GPIO 輸入加載順序剛好晚于 SPI 驅動結果 CS 引腳被切成了 GPIO 模式SPI3 的 CS 永遠無法拉低。排查這類問題需要查看/sys/kernel/debug/pinctrl/下各個引腳當前的 mux 狀態確認 SPI3 引腳沒有被別的驅動搶占。4.3 DMA 與中斷配置傳輸啟動了但數據是空的SPI 控制器支持 DMA 模式時數據搬運依賴 DMA 通道。如果 DMA 通道配置失敗或者 DMA 請求信號沒有被正確映射到 SPI3 的事件輸出那么發送時寄存器里可能只寫入了第一個字節后面的數據全部丟失。現象表現為CLK 有時鐘MOSI 上只有零星幾個脈沖然后就沒有然后了。檢查手段是看 DMA 引擎的狀態。Linux 下可以查看/sys/kernel/debug/dmaengine/summary確認 SPI3 的 DMA 通道是否注冊成功。如果驅動里使用的是dma_request_chan卻在dmesg里看到failed to get dma channel那就要檢查設備樹里dmas和dma-names屬性是否配了正確的 DMA 請求 ID。中斷配置問題也類似。SPI3 在沒有 DMA 的情況下依賴 TX FIFO 為空和 RX FIFO 非空這兩類中斷。如果中斷號配錯或者中斷處理函數里沒有正確清除標志位傳輸會卡死在某個狀態。這時候示波器上能看到 CLK 只翻轉了幾下就停了這是因為發送端在等 TX FIFO 有空位而中斷沒有觸發驅動認為 FIFO 還是滿的。4.4 從機沒響應導致的“假性無輸出”還有一種容易被誤判為“SPI3 沒信號”的情況主控確實發出了完整的事務CLK、MOSI、CS 波形全部正常但 MISO 上什么都沒有整條讀取的數據全是 0xFF。從軟件角度往回查會看到 SPI 驅動超時返回-ETIMEDOUT。這其實是從機設備沒有正常工作而不是主控沒有發送信號。遇到這種情況先查從機供電、復位引腳、使能引腳是否正常。很多從機芯片都有硬件復位腳或使能腳如果這些引腳被 GPIO 控制但 GPIO 初始化順序不對從機可能一直處于復位狀態或者掉電狀態。我遇到過一顆 LCD 驅動芯片它的 TE撕裂效應引腳被復用成了 GPIO 且被拉高導致從機認為數據輸入被暫停SPI 傳輸的數據全部被丟棄。這種問題看起來像是“SPI3 沒信號”實際上鏈路全通只是從機不干活。5. 一次真實案例的完整復現從現象到根因的排查路徑講了這么多理論拿一個實際案例串一下整個排查思路。這個案例來自我最近調試的板子過程比較典型希望能幫你建立一條可復用的排查路徑。5.1 現象確認量到的波形同事反饋 SPI3 外接的 NOR Flash 讀不出來flash_erase命令直接報錯。我用示波器掛上四根線觸發方式設成 CS 下降沿結果 CS 上的下降沿都看不到四根線全部平直。當時第一反應是軟件根本沒初始化 SPI3。5.2 排查過程從 dmesg 到時鐘樹先看dmesg | grep -i spi3輸出顯示spi3 spi3.0: setup mode 0, 8 bits, 10000000 Hz max說明驅動 probe 成功也正確配置了模式。再看/sys/kernel/debug/clk/clk_summary | grep spi3發現 spi3 的時鐘節點enable_count是 1看起來也正常。這時候陷入了僵局軟件配置看起來正常引腳復用也查過沒有沖突但就是沒有波形。于是回頭再看了一遍時鐘樹發現clk_summary里有一個父時鐘節點的prepare_count是 0。這個父節點正好是 SPI3 的源時鐘雖然是直連的分頻節點但父時鐘沒 prepare子時鐘 enable 了也沒用。查驅動代碼發現有一個時鐘是通過devm_clk_get_optional()獲取的驅動認為它是可選的獲取失敗也不報錯但這個時鐘恰恰是外設功能時鐘的父時鐘。解決辦法是在設備樹的 SPI3 節點里補上缺失的時鐘引用同時在驅動里把devm_clk_get_optional()改成必需的devm_clk_get()獲取失敗直接返回-EPROBE_DEFER。改完重新編譯燒錄示波器上立刻出現了完整波形。5.3 復盤要點為什么一開始沒發現回頭看這個問題的隱蔽性在于clk_enable_count已經置 1但父級時鐘沒有 prepare導致時鐘根本沒有真正到達 SPI3 外設。如果你只檢查 SPI3 節點本身的時鐘狀態永遠發現不了問題。必須沿著時鐘樹往上追確認每一個父節點都處于可工作狀態。排查這種問題我的經驗是在clk_summary里找到 SPI3 時鐘節點后一路往根節點方向看任何prepare_count為 0 的中間節點都有可能是問題所在。很多時候 SoC 內部的時鐘樹比你想的要復雜多一個 mux、多一個 divider就多一個開關。5.4 另一個案例外部回環定位鏈路斷點另一個案例是和 SPI3 無關但思路相同。某板子的 SPI3 連接器測不到信號但主控引腳上波形正常。我在連接器的從機端把 MOSI 和 MISO 短接主機發送 0xAA結果收不到任何數據說明從主控引腳到連接器這一段鏈路是斷的。然后拿萬用表量連接器到主控引腳的走線導通性發現某個過孔虛焊補焊后回環測試通過。整個過程用了不到十分鐘比盲改代碼高效得多。6. 幾個容易忽略但非常實用的補充細節前面算是一條主線的排查思路但實際項目里還有幾個零散但很實用的細節值得單獨拿出來說省得你在現場重復踩坑。6.1 三線制 SPI3 模式的特殊性開頭提到過有些語境下 SPI3 指的是三線制模式。三線制 SPI 只有 SCK、CS、DATA 三根線數據線是雙向的主控發送時需要把方向切到輸出接收時需要切到輸入。這種模式下如果驅動里的 GPIO 方向切換時機不對就會出現“發送正常、接收全零”或者反過來“發送時數據線上的波形是亂的”。三線制 SPI 的排查重點是數據線的方向切換時序。用示波器量數據線發送階段應該有主控驅動的電平變化接收階段應該變成高阻或從機驅動。如果在接收階段數據線上還是主控的高電平或者低電平說明方向沒有切換成功數據沖突了。這類問題在 STM32 上開啟三線制模式時尤其常見因為它依賴硬件自動切換方向一旦引腳復用配置成普通推挽輸出方向切換就失效了。6.2 CS 片選的“假正常”狀態CS 是 SPI 信號里最容易被忽略又最容易出問題的一根線。很多人看到 CS 在示波器上是高電平就認為它正常——但 SPI 空閑時 CS 本來就是高電平。要確認 CS 是否正常必須在觸發事務時看它有沒有拉低。CS 的常見問題有三個一是極性配置反了設備樹里配成spi-cs-high導致 CS 在傳輸時是高電平從機永遠處于未選中狀態二是 CS 被某個驅動當成了普通 GPIO 控制導致 SPI 控制器無法驅動它三是 CS 線上下拉電阻沒接在 EMI 干擾下電平抖動從機誤動作。排查 CS 最直接的辦法是在/sys/kernel/debug/pinctrl里查看該引腳的當前狀態如果是 GPIO 模式而設備樹里沒配置 CS 為 GPIO 控制那就說明 pinctrl 配置有問題。6.3 時序余量的判斷不要被“有波形”騙了有時候示波器上波形完整但系統就是不工作。這時候要關注信號的時序參數包括建立時間、保持時間、上升沿/下降沿時間。SPI 主控輸出的信號經過 PCB 走線、電平轉換、連接器之后到達從機引腳時可能已經變差。如果從機要求的建立時間余量不足傳輸就會偶發失敗。判斷方法是看數據線的跳變沿和 CLK 采樣沿之間的關系。在 Mode 0 下數據在 CLK 上升沿被采樣數據線的跳變應該發生在 CLK 下降沿附近給采樣留出完整的建立時間。如果數據線的跳變沿幾乎和采樣沿重合說明時序余量已經很緊張需要考慮降低 SPI 時鐘頻率、優化 PCB 走線長度、或者換用壓擺率更高的電平轉換芯片。6.4 邏輯分析儀還是示波器排查 SPI3 信號工具選擇上有講究。示波器適合看模擬特性比如電平、邊沿、振鈴邏輯分析儀適合看時序關系和數據內容尤其是需要解碼一串很長的數據時。如果只是確認“有沒有信號”示波器就夠如果要確認“數據內容對不對”邏輯分析儀更方便。實際操作中我通常是示波器先掛上確認物理層正常再用邏輯分析儀抓一段完整的事務解碼驗證。兩者配合排查效率最高。7. 最后再分享一點個人體會SPI3 接口沒有信號送出這類問題的排查過程說到底就是“沿著信號鏈路走一遍”的過程。軟件配置查完查硬件硬件查完再回頭看軟件每一步都要有明確證據而不是靠猜。我在實際工作中見過太多人一上來就反復改寄存器、改設備樹改完一測還是不行又改回去一個下午就這么耗掉了。我更推薦的做法是先花十分鐘把示波器掛好量清每一根線的實際狀態。波形是最好的證據它不會騙人。CLK 有沒有、CS 有沒有拉低、MOSI 有沒有數據這三個信息一出來問題范圍立刻縮到很小。剩下的就是對癥下藥沒有時鐘查時鐘樹沒有片選查復用配置有波形但數據錯查時序和模式參數。排查過程中養成記錄的習慣也很有價值。每次改動什么參數、波形有什么變化、最終根因是什么記下來之后下次遇到類似問題可以快速對照。我自己就維護了一份“SPI 接口排查筆記”里面記錄了每個平臺 SPI3 的引腳復用編號、時鐘樹路徑、常見坑點。遇到新項目時直接翻出來對照比重新踩一遍坑高效得多。希望這篇經驗分享能幫你少走一些彎路。如果你在排查 SPI3 時遇到的情況和上面說的都不一樣也歡迎交流畢竟嵌入式世界里的“沒信號”千奇百怪多一個案例就多一分經驗。