调试SD NAND的时候,很多人卡在同一个地方:初始化过了,卡也回了ready,但一发CMD17读扇区就出问题。超时、非法命令、CRC校验失败,几种错误轮着来。
换卡、换驱动、换开发板,折腾一圈,问题还在。

这篇文章换个角度,不从协议时序讲起,从实际调试中遇到的几个典型现象入手,看看问题通常出在哪。
现象一:发完命令,读回来全是0xFF
这是最常见的情况。主机在CMD线上发了CMD17,读回来的数据全是0xFF,说明卡根本没理这条命令。

有个工程师用STM32的SPI接口驱动SD NAND,初始化正常,一读扇区就返回0xFF。查了半天驱动没找到问题,最后发现是CS片选时序不对——SPI模式下,片选拉低后需要给一定的建立时间,命令之间不能频繁抖动CS。他程序里CS拉低之后立刻发命令,卡还没来得及响应。
还有一种情况是初始化时钟太高。SD协议规定CMD0到ACMD41这段握手期间时钟必须低于400kHz,有些工程师初始化阶段用了1MHz甚至更高,卡直接不响应。
排查方向:CS时序、初始化时钟频率、上电等待时间。先用低速SPI跑通,再考虑提速。
现象二:R1返回0x04,非法命令
R1非0的时候,说明卡收到了命令但不认。0x04是最常见的,意思是非法命令。
这个问题的根源往往在命令序列上。SD协议规定,发ACMD类命令之前必须先发CMD55切换前缀。比如切换4位总线要用ACMD6,但直接发ACMD6卡是不认的,必须先发CMD55告诉卡"下一条是ACMD"。
另一个容易出错的地方是版本判断。SD协议V2.0以上的卡和V1.0的卡,初始化流程不一样。V2.0以上的卡在CMD8之后回R7响应,V1.0的卡回0x05(idle位和非法命令位同时置1)。如果程序里没处理这个分支,后面的命令序列就全乱了。
排查方向:检查CMD55前缀是否发对、CMD8的版本分支是否处理、命令号有没有写错。
现象三:R1正常,但等不到0xFE
命令被正确接受了,R1也回了0x00,但主机等不到数据起始令牌0xFE。这一步最容易被误判成超时,然后工程师开始盲目加大延时,从100ms加到500ms,问题照旧。
实际上,等不到0xFE通常有两个原因。
卡正忙。写操作或内部垃圾回收期间,DAT0会被拉低输出0x00,主机要持续读这根线直到它释放。用固定延时代替状态轮询,等多久都没用。
寻址口径错了。SDHC和SDXC卡按块号寻址,SDSC老卡按字节寻址。如果程序里把字节地址传给了SDHC卡,卡会认为地址越界,不返回数据。这个问题在从老卡迁移到新卡的时候特别容易踩。
排查方向:确认是轮询忙状态还是固定延时、确认寻址方式(块号还是字节地址)。
现象四:数据读回来了,但CRC校验失败
这是SDIO 4位模式下最高发的问题。命令和前几个块都正常,跑一段时间或者一提频就报CRC错误。
有个做工业HMI的客户遇到过这种情况:用SDIO 4位模式驱动SD NAND,低速下读写正常,时钟提到20MHz就开始报COM CRC和DATA CRC错误。
查了一圈发现两个问题:一是CMD和DAT线上拉电阻没接,信号边沿悬空;二是CLK和DAT走线长度差了将近一倍,建立时间不满足。降频到10MHz问题消失,补上拉电阻、重新走线之后,20MHz也能稳定跑。
排查方向:上拉电阻是否齐全、走线是否等长、时钟是否提得太快、4位切换是否在低速下完成。
现象五:写操作正常,但读操作失败
有些项目读能跑,写就出问题。写路径上有几个独立的坑。
CMD24写完要等忙。卡把数据烧进NAND需要时间,DAT0拉低期间主机不能继续发下一块。程序里发完CMD24就以为写完了,接着发下一条命令,卡会报错。
多块写结束要发停止令牌。CMD25写多块的时候,主机必须发STOP_TRAN令牌结束写操作,否则卡一直保持写状态,后面的命令全被拒绝。
写块中途掉电可能让块或者映射表不一致。工业场景要配掉电保护或者安全写流程。
排查方向:写完后是否等待忙释放、多块写是否发停止令牌、是否有掉电保护机制。
一个容易被忽略的点:CRC校验模式不同
SPI模式和SDIO模式对CRC的要求不一样。SPI模式默认关闭CRC校验,除了CMD0的CRC7必须正确,其他命令的CRC字段可以填占位值,数据块的CRC16也可以忽略。SDIO模式默认开启CRC,命令CRC7和数据CRC16都必须对得上。
有些工程师从SPI方案迁移到SDIO方案,CRC校验相关的代码没改,结果命令发出去就报CRC错误。反过来,从SDIO迁到SPI,CRC代码留着也没问题,但要注意SPI模式下CRC被忽略,不要因为CRC校验通过就以为信号质量没问题。
现场排查的推荐顺序
遇到读写失败,不要一上来就改驱动或者换卡。按这个顺序走效率更高:
第一步,退回SPI低速模式,用已知好卡验证主机基线。先确认供电和最基本通路没问题。
第二步,抓逻辑分析仪或者示波器,看CLK、CMD、DAT0上的波形。命令有没有发出去、R1有没有回来、0xFE有没有出现,把问题定位到具体哪一步。
第三步,核对供电电压和纹波、上拉电阻、DMA缓冲区对齐和长度。
第四步,按R1错误位和信号完整性逐项处理,最后再考虑提频和切4位。
SD NAND读写失败,问题很少出在卡本身。更多时候是命令序列、时序、寻址方式、信号完整性这些环节上的细节没处理好。
初始化成功只是命令线握手通过,数据线通路、忙等待、寻址口径、CRC校验任何一环出问题,都会表现成"读不出扇区"。用R1错误位和0xFE令牌把问题定位到具体一步,比盲目改代码有效得多。
米客方德SD NAND和SD卡走同一套协议,排查思路通用。区别在于SD NAND是贴片焊接,没有卡座接触问题,可以少查一个物理层面的变量。如果项目卡在读写调试上,可以把R1返回值、时钟配置和报错现象整理出来,对照上面的分层逐项排查。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。