ARTICLE DETAIL

资讯详情

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

SPI调试:CS正常拉低但SCK无输出?STM32MP2多核平台排查实录

SPI调试:CS正常拉低但SCK无输出?STM32MP2多核平台排查实录 见过不少 SPI 调试的怪事但 CS 线能正常拉低、SCK 却纹丝不动依然是我觉得最有迷惑性的故障之一。最近在 STM32MP257F-DK 上又遇到一次而且是在防火墙已经开了、时钟也确认在跑的情况下单片机里读状态一切正常示波器却看不到时钟脉冲。这种问题如果在普通 MCU 上多半是初始化顺序或寄存器配置漏了位但到了 STM32MP2 这种 Cortex-A35 加 Cortex-M33 的异构多核平台原因更多也更隐蔽。这篇文章就把这次排查的完整思路、踩过的坑和一套可以直接照做的检查流程整理出来希望能帮到被类似现象卡住的人。MP257F-DK 这块板子并不是普通意义上跑裸机代码的 MCU。芯片内部有双核 Cortex-A35 和单核 Cortex-M33外设通过资源隔离框架 RIF 来划分访问权限典型的安全属性和非安全属性、CID 过滤、总线主设备过滤都会影响一个外设到底能不能被正确操作。标题里那句 firewall open 听起来好像问题不大但在 STM32MP2 上“打开防火墙”往往不是一个开关而是一组属性的组合配置。更别提 SPI 这类外设它同时依赖总线接口时钟、内核时钟、引脚复用和控制器自身状态任何一个环节不到位都会出现“寄存器看起来在工作、引脚却没有输出”的现象。下面我就从实际调试的顺序出发把每个值得检查的点都过一遍。1. 现象放在多核平台上就不只是 SPI 控制器的事1.1 问题现象还原先说现象。我这边通过调试器把 SPI 初始化代码执行完GPIO 配置里 CS 为普通推挽输出SCK、MOSI、MISO 都配成对应的复用功能。初始化完成后人为把 CS 拉低用示波器量 CS 引脚电平确实从高拉低说明引脚控制链路是通的。但量 SCK 引脚时任何时刻都看不到脉冲要么一直保持低电平要么一直保持高电平仅仅在 CS 拉低期间一动不动。为了排除是我对触发点理解错了我量了整个通信窗口。CS 下降沿之后等了几十微秒SCK 没有任何波形CS 上升沿之后也没有。如果把示波器时基拉到几百微秒甚至毫秒级依然看不到任何翻转。这说明不是“时钟频率太高没抓到”而是 SCK 引脚真的没有时钟活动。我当时甚至怀疑是测试点接触不良换了一根探头、换到板子背面引脚再量结果还是一样。这种“CS 正常但 SCK 完全无输出”的现象放在普通 STM32 MCU 上我会先怀疑 GPIO 复用没配好或者 SPI 外设没使能再或者主从模式配置错了。但在 MP257F-DK 上这几个怀疑点都要再加一层多核访问控制的判断因为即使代码跑起来了外设也可能根本没有接收到你想写入的配置。这种“代码执行成功、外设没反应”的割裂感在普通 MCU 上很少见在带安全隔离的 MPU 上却是家常便饭。1.2 寄存器读到了不代表引脚能输出多核平台上最容易出现的误导是调试器连接上去后我能读到 SPI 的寄存器CR1 里的 SPE 位是 1SR 里的 TXE 标志也能置位看起来外设工作正常。但寄存器能访问只说明 APB 总线接口时钟是通的、访问权限没有被总线层完全挡住。SPI 内部要真正产生 SCK还需要两个独立条件一是 SPI 内核时钟用于产生波特率已正确供给二是 SCK 引脚本身被正确的复用控制器驱动。尤其要小心访问被部分屏蔽的情况。MP2 的 RIF 有安全属性和 CID 过滤如果某个代码运行时对外设寄存器只能读不能写读出的寄存器值可能仍然是复位默认值或上次配置值看起来就像配置过了。这种情况下外设内部状态机可能压根没启动但寄存器视图骗过了你。我的体会是在这种平台上寄存器只能作为辅助证据不能作为“外设正常”的充分条件。所以下面的排查每一层都要直接确认物理结果不能只看寄存器。1.3 排查方向总览我这次排查基本按五层推进第一层确认 SPI 的时钟输入第二层确认 RIF 访问控制第三层确认 GPIO 复用第四层确认 SPI 控制器配置第五层确认当前处理器主域和软件栈的干扰因素。下面每层都会给出具体的检查方法和典型现象。如果你也遇到 SCK 不动、CS 却正常的问题建议按同样的顺序做而不是先从控制器寄存器开始猜。因为顺序错了很容易在某一层反复绕圈最后发现根因在完全不同的位置。2. SPI 的“时钟”到底指什么PCLK 和内核时钟别混着算2.1 一个外设、两个时钟输入SPI 外设并不只有一路时钟。很多嵌入式工程师习惯了“打开外设时钟”这个动作认为只要 RCC 对应位置 1外设就有电、就能跑。实际上大多数 MCU 的 SPI 外设至少有两路时钟输入总线接口时钟 PCLK来自 APB 总线负责寄存器读写、中断逻辑、状态标志。这一路如果不开启SPI 的寄存器根本读不到写不进去程序可能直接 HardFault 或读到全 0。SPI 内核时钟 Kernel Clock负责波特率发生器、移位寄存器、时钟输出逻辑决定 SCK 频率。这一路由 RCC 中的专用选择器和分频器控制可以来自不同的 PLL、HSE、CSI 等时钟源。标题里说 “clocks running”很多人以为指的就是这两路都确认过了。但我见到的大量案例是只确认了 PCLK 使能没确认 SPI 内核时钟选到了真正有效的时钟源或者内核时钟分频器被配成了 0导致 SCK 频率计算不出来。寄存器照样能读写可 SPI 不会产生任何时钟脉冲。就好比你给一台发动机通了电油路却没接仪表盘当然能亮但轮子就是不动。2.2 内核时钟选错或没分频时会发生什么STM32MP257F-DK 的 RCC 比普通 MCU 复杂很多。SPI 的 kernel clock 不会自动跟随 PCLK它通常有一个时钟源选择位域和一个分频位域需要你把系统里某个 PLL 的输出、HSE、CSI 或者其他时钟源接到 SPI 上。如果这个选择器复位后的默认值是“无时钟”或“已关闭的 PLL”那无论怎么改 APB 使能位SCK 都不会动。这里有个更隐蔽的情况是“异步时钟模式”分频。SPI 内核时钟里有时会有额外的分频逻辑或门控逻辑如果你配置的分频值为 0某些实现可能直接关闭时钟输出而不是按最大值分频。文档里写的是 Divide 0 保留或不可用但驱动代码没做防御实际寄存器写入了 0结果就是没有 SCK。遇到 SCK 完全无输出的情况我都会先查一遍 kernel clock 选择器、分频器和门控使能位把这三个位域全部读出来而不是只看 RCC 里有没有打开 SPI 对应位。这种细节在 MCU 上几乎不用关心在 MP2 上却经常决定成败。2.3 怎么确认时钟配置真的落到寄存器里我的做法是在 SPI 使能之前先用调试器读回 RCC 中 SPI 相关寄存器确认四件事APB 总线时钟使能位为 1。SPI 内核时钟源选择位域不是 0且指向的 PLL/HSE/CSI 确实已在运行。内核时钟分频位域是一个非 0 的合理值目标 SCK
返回列表