You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SD卡SPI驱动CRC7校验异常问题排查及代码正确性验证请求

SD卡SPI驱动CRC7校验异常问题

问题现象

开发SD卡SPI驱动时,启用CMD59开启CRC7校验后,部分SD卡出现异常;关闭CRC7校验后,所有支持SPI的SD卡均可正常读写。

初步推测问题出在CRC7计算逻辑。异常SD卡启用CRC7后可正常初始化,能读写少量文件,但最多10-15个文件后报错,具体表现:

  • 发送CMD17后收到R1=0x00,但后续仅能读取到0xFF,无数据令牌或错误令牌,等待200ms(远超标准100ms超时)仍无变化。
  • 用CMD13读取状态,R1=0x00、R2=0x00,无错误提示。
  • 此后所有读写操作失效:CMD17、18、24、25等命令的R1/R2均无错误,但读取始终返回0xFF,无法获取令牌,也无错误提示。

SD卡初始化流程

  • 波特率<400000Hz
  • CMD0 → CMD59 → CMD8
  • 若为SDSC:CMD58 → 循环执行(CMD55 → ACMD41)
  • 若为SDHC/SDXC:CMD58(获取OCR寄存器值)→ 循环执行(CMD55 → ACMD41) → CMD50(获取OCR寄存器值并检查CCS)
  • CMD9 → 检查CSD版本并获取参数
  • CMD10(获取CID寄存器值)
  • CMD55 → ACMD13(获取SD寄存器值)
  • CMD55 → ACMD51(获取SCR寄存器值)
  • 检查是否支持CMD42
    • 若支持且需设置/已设置密码:
      • CMD16(为CMD42设置块长度)
      • CMD42
  • CMD16(为所有卡设置块长度为51字节)
  • 挂载文件系统
  • 切换至12MHz波特率
  • 使用CMD17、18进行读取(CMD12用于停止传输)
  • 使用CMD24、25进行写入
  • 出现错误时用CMD13检查状态

CRC7计算代码检查请求

希望排除CRC7计算逻辑仅在特定输入下出错的可能,以下是Python/Micropython实现的CRC7计算代码,请求检查正确性:

def crc7(self, cmd, arg1, arg2, arg3, arg4):
    crc = 0x00
    poly = 0x89
        
    cmd_token = bytes([cmd, arg1, arg2, arg3, arg4])
    # Example: CMD0 -> 0x40, 0x00, 0x00, 0x00, 0x00

    for byte in cmd_token:
        for bit in range(8):
            bit = ((byte >> (7 - bit)) & 1)
            crc_bit = ((crc >> 6) & 1)
            crc = ((crc << 1) & 0x7F)
            if bit ^ crc_bit:
                crc ^= poly
                    
    crc = crc & 0x7F
    crc = (crc << 1) | 0x01 # CRC7 and end bit = 1 for CMD    
    return crc

注:关闭CRC7校验时从未出错,启用校验后出错前的CRC7值均经在线CRC计算器验证正确。


代码问题分析

你的CRC7计算逻辑存在一处关键错误:SD卡标准中CRC7的多项式是0x09(对应二进制1001),而不是代码中的0x89。

错误细节

SD卡的CRC7定义为:

  • 生成多项式:G(x) = x^7 + x^3 + 1,对应十六进制是0x09(二进制00001001)
  • 初始值:0x00
  • 输入位顺序:高位先传(你的代码中处理字节的高位到低位是正确的)
  • 输出处理:CRC结果左移1位并附加结束位1(这部分你的代码是正确的)

代码中使用0x89作为多项式,对应的是x^7 + x^4 + x^3 + x^0,不符合SD卡标准,这会导致部分命令的CRC计算错误,尤其是在频繁读写后积累错误,触发SD卡的保护机制,出现你描述的无响应现象。

修正后的代码

def crc7(self, cmd, arg1, arg2, arg3, arg4):
    crc = 0x00
    poly = 0x09  # 修正为SD卡标准CRC7多项式
        
    cmd_token = bytes([cmd, arg1, arg2, arg3, arg4])

    for byte in cmd_token:
        for bit in range(8):
            bit = ((byte >> (7 - bit)) & 1)
            crc_bit = ((crc >> 6) & 1)
            crc = ((crc << 1) & 0x7F)  # 保持7位CRC寄存器
            if bit ^ crc_bit:
                crc ^= poly
                    
    crc = crc & 0x7F
    crc = (crc << 1) | 0x01  # 附加结束位1
    return crc

验证建议

修正多项式后,重新测试启用CRC7校验的场景:

  1. 对常用命令(如CMD17、CMD24)计算CRC,对比在线SD卡CRC计算器的结果
  2. 长时间读写文件,确认是否再出现无响应问题

内容的提问来源于stack exchange,提问作者user31736217

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 03:44:51