Fork me on GitHub
0%

SD调试笔记

协议内容

CMD

命令 名称 作用 响应类型 说明 命令类型
CMD0 GO_IDLE_STATE 复位卡到闲置状态 基本命令
CMD2 ALL_SEND_CID 请求所有卡发送其CID寄存器内容 R2 包含CID寄存器内容(136位) 基本命令
CMD3 SEND_RELATIVE_ADDR 请求新卡发送其相对地址(RCA) R6 包含16位的RCA和卡状态 基本命令
CMD7 SELECT/DESELECT_CARD 选择卡进行通信或取消选择 R1 包含卡状态(48位) 基本命令
CMD8 SEND_IF_COND 检查卡是否支持电压范围和接口条件 R7 包含接口条件回读(48位) 数据传输命令
CMD9 SEND_CSD 请求卡发送CSD寄存器内容 R2 包含CSD寄存器内容(136位) 数据传输命令
CMD10 SEND_CID 请求卡发送CID寄存器内容 R2 包含CID寄存器内容(136位) 数据传输命令
CMD12 STOP_TRANSMISSION 停止数据传输 R1b 包含卡状态,忙标志位(48位) 数据传输命令
CMD13 SEND_STATUS 请求卡发送其状态寄存器内容 R1 包含卡状态(48位) 数据传输命令
CMD16 SET_BLOCKLEN 设置单个数据块的长度(字节) R1 包含卡状态(48位) 数据传输命令
CMD17 READ_SINGLE_BLOCK 读取一个数据块 R1 包含卡状态(48位)后跟数据块 数据传输命令
CMD18 READ_MULTIPLE_BLOCK 读取多个数据块 R1 包含卡状态(48位)后跟多个数据块 数据传输命令
CMD24 WRITE_BLOCK 写入一个数据块 R1 包含卡状态(48位)后跟数据块 数据传输命令
CMD25 WRITE_MULTIPLE_BLOCK 写入多个数据块 R1 包含卡状态(48位)后跟多个数据块 数据传输命令
CMD27 PROGRAM_CSD 编程CSD寄存器 R1 包含卡状态(48位) 数据传输命令
CMD32 ERASE_WR_BLK_START 设置要擦除的第一个块的地址 R1 包含卡状态(48位) 错误处理命令
CMD33 ERASE_WR_BLK_END 设置要擦除的最后一个块的地址 R1 包含卡状态(48位) 错误处理命令
CMD38 ERASE 执行从CMD32和CMD33指定的地址范围内的块擦除 R1b 包含卡状态,忙标志位(48位) 错误处理命令
CMD55 APP_CMD 通知卡下一条命令是应用特定命令(ACMD) R1 包含卡状态(48位) 特殊应用命令
CMD23 SET_BLOCK_COUNT 置SD卡的数据块数量 R1 包含卡状态(48位) 特殊应用命令
CMD58 READ_OCR 读取操作条件寄存器(OCR) R3 包含OCR寄存器内容(48位) 特殊应用命令
ACMD6 SET_BUS_WIDTH 设置数据总线宽度 R1 包含卡状态(48位) 应用特定命令
ACMD13 SD_STATUS 请求卡发送SD状态 R1 包含卡状态(48位)后跟64字节的SD状态数据 应用特定命令
ACMD22 SEND_NUM_WR_BLOCKS 请求卡发送已写入的数据块数 R1 包含卡状态(48位)后跟4字节的块数 应用特定命令
ACMD23 SET_WR_BLK_ERASE_COUNT 设置或清除多个数据块的写保护状态 R1 包含卡状态(48位) 应用特定命令
ACMD41 SD_SEND_OP_COND 初始化卡并确定工作电压 R3 包含OCR寄存器内容(48位) 应用特定命令
ACMD51 SEND_SCR 请求卡发送SCR寄存器 R1 包含卡状态(48位)后跟8字节的SCR寄存器内容 应用特定命令
CMD6 SWITCH_FUNC 切换卡的功能 R1 包含卡状态(48位) 高级命令
CMD11 VOLTAGE_SWITCH 切换电压 R1 包含卡状态(48位) 高级命令
CMD52 IO_RW_DIRECT 直接读写I/O寄存器 R5 包含I/O操作结果(48位) SDIO相关命令
CMD53 IO_RW_EXTENDED 扩展读写I/O寄存器 R5 包含I/O操作结果(48位) SDIO相关命令

响应类型说明

  • R1: 标准响应,包含卡状态(48位)

  • R1b: R1响应,后跟忙信号

  • R2: CID和CSD寄存器响应(136位)

  • R3: OCR寄存器响应(48位)

  • R5: SDIO操作响应(48位)

  • R6: RCA和卡状态响应(48位)

  • R7: 接口条件响应(48位)

Q&A

  1. fwrite写数据失败?

    使用CMD25发送多block之后,需要紧接着发送一个CMD12,表示停止传输。

    对于MMC控制器可能有AUTO_CMD12功能,也就是当发送完数据之后自动发送CMD12,不需要手动发送CMD12。因此在实际过程中,如果遇到相关问题可以尝试这两种方式切换。如果自动发送CMD12不正常,则尝试自动CMD12。

    CMD12已用于停止多块读/写操作。然而,CMD12是依赖于时间的,并且很难控制在精确的时间上发出CMD12的时间。由于UHS104卡在时钟和数据之间有很大的延迟变化,CMD23有利于主机停止多次读/写操作,而不是CMD12。主机不需要控制CMD12的时间。此命令适用于总是512字节块长度的读/写操作,然后SDSC(Secure Digital Standard Capacity 低速小容量)卡不支持此命令。UHS104( Ultra High Speed 104 MB/s)卡必须支持CMD23

  2. fwrite向SD卡写数据只能以block size的整数倍写,否则CMD25超时?

    • 调试思路

      1. 定位到是哪一个层次出现的问题(fwrite -> glibc -> filesystem -> dfs_write -> mmc_write -> 驱动程序 -> mmc接口)
      2. 根据现有的情况进行分析。当整数倍写的时候正常,非整数倍错误,说明整个流程是没问题的,驱动程序也支持多块读写。
      3. 对两种情况有差异的地方进行分析,并尝试修改代码,不生效
      4. 进一步简化代码,将DMA模式换成Polling模式,发现与DMA在同一个地方出错,是非法地址访问
      5. 进一步查找问题,定位在数据buffer的地址没有4字节对齐,但是dma和polling都进行4字节访问,进而出错
    • 解决方案

      在Filesystem关于mmc_write文件中对数据进行处理。当判断地址不是4字节对齐的时候进行一次memcpy,在进行写入

  3. Fatfs文件系统不能正常显示中文?

    将ffconf.h文件中的:FF_CODE_PAGE 宏值改成936(简体中文)默认437(US);FF_LEN_UNICODE改成2(UTF-8)默认0(ANSI)。同时在使用串口工具的时候,需要指定UTF-8格式