尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

嵌入式SPI3无信号排查实战:从时钟树到引脚复用全链路解析

嵌入式SPI3无信号排查实战:从时钟树到引脚复用全链路解析 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 时遇到的情况和上面说的都不一样也欢迎交流毕竟嵌入式世界里的“没信号”千奇百怪多一个案例就多一分经验。
返回列表