电子说
说起SD NAND /SD卡写保护的问题,我们先分析一下出现写保护的一些原因
首先,我们先除去SD大卡的物理开关的问题,目前TF卡和SD NAND都是通过软件进行写保护的开关。
读写中意外断电、未“安全移除”、长期使用产生坏块、空间已满等,系统为避免进一步数据损坏,可能将卡自动挂为“只读”。
恶意程序篡改分区表、文件系统设置,甚至设置隐藏的只读/写保护属性,导致无法写入或格式化。
如 Windows 驱动不兼容、用户权限不足、注册表项(如 Storage Device Policies 的 Write Protect)被修改,系统层将设备设为“只读”。
闪存磨损达到设计寿命或主控/电路异常,主控可能启用只读保护,防止数据进一步损坏
电压不足、掉电、浪涌等导致读写中断或文件系统损坏,进而触发只读/写保护现象。这个问题目前是比较常见的,所以供电电压的稳定性很重要,且要高估存储卡的峰值电流和浪涌,这样会导致电压瞬间的变化。
所以保证稳定供电,避免低电量设备中长时间写入;必要时使用稳压与浪涌抑制设计。

写保护开关和密码设定主要是存储芯片命令集中的CMD42来执行,我们也简单学习一下CMD42的功能。
CMD42 功能与用途
CMD42(Class 7,Lock Card commands)是 SD 规范中用于卡片安全与锁定的命令,可在卡内维护的寄存器(如 PWD、PWD_LEN)上执行:设置/清除密码、锁定/解锁卡片,以及在必要时执行“强制擦除”(擦除卡内数据与密码)。当卡内设置了密码(PWD_LEN ≠ 0)时,卡在上电后会自动进入锁定状态,此时常规读写将被拒绝,直到通过 CMD42 正确解锁。该命令是实现“密码保护芯片”的核心机制。
关键约束与差异
块长度设置:执行 CMD42 前需用 CMD16 设置数据块长度。块长度必须≥命令数据结构长度(至少为 PWD_LEN+2 字节)。在 SD 模式下可设为任意合法偶数值;在 SPI 模式下,CMD42 的块长度应取偶数,很多实现会直接用 1 字节或 PWD_LEN+2。
密码长度限制:PWD_LEN 最多为 16 字节;修改密码时“旧密码+新密码”的总长度最多 32 字节。
卡片自动锁定:若上电时 PWD_LEN ≠ 0,卡会自动进入锁定状态。
模式差异:CMD42 属于 SD 应用命令集,SD 模式下需通过应用命令路径(先发 CMD55 再发 CMD42);SPI 模式下通常可直接发送 CMD42。
写保护区分:CMD42 是“密码锁卡”能力;而按扇区/组的软件写保护由 CMD28/CMD29/CMD30 管理,且 SDHC/SDXC 不支持这些写保护命令(不响应)。
强制擦除:设置数据块长度为 1 并在 CMD42 数据中仅置位 ERASE 位,可清除卡内数据与密码(忘记密码时的最后手段)
。
字段与响应说明
CMD42 数据块格式(按字节):
Byte0:标志位,bit7~4 保留(置 0),bit3 ERASE,bit2 LOCK/UNLOCK,bit1 CLR_PWD,bit0 SET_PWD。
Byte1:PWD_LEN(密码长度,单位字节)。
Byte2…:密码数据(按“旧密码在前、新密码在后”的顺序提供,仅在相应标志置位时有效)。
末尾:附加 16 位 CRC(SPI 模式)。
状态查询与结果:
用 CMD13(SEND_STATUS)查询卡状态,bit0(CARD_IS_LOCKED)为 1 表示卡处于锁定。
CMD42 执行失败会在状态寄存器置位 LOCK_UNLOCK_FAILED(bit24);若强制擦除失败会置位 LOCK_UNLOCK_FAILED。
块长度与 CRC 的细节:CMD42 的数据块长度由主机在 CMD16 设定;SPI 模式下该数据块需包含 16 位 CRC。CMD16 的长度参数在 CMD42 场景下应≥PWD_LEN+2
。
典型操作流程(SPI 模式示例)
准备:确保卡处于传输状态(SD 模式用 CMD7 选中;SPI 模式按初始化流程完成选中)。
设置块长度:CMD16(ARG=块长度,RESP=R1)。CMD42 的块长度应≥PWD_LEN+2;SPI 实践中常用 1 或 PWD_LEN+2(偶数)。
设置密码(首次设置):
CMD16(ARG=PWD_LEN+2)
发送 CMD42(CMD=0x6A, ARG=0x00000000, CRC=0x95)
数据块:0x01(SET_PWD),PWD_LEN,旧密码(无则填 0),新密码
结束:附加 0xFF 填充至整块,发送 16 位 CRC
用 CMD16 恢复块长度为 512(如需后续常规读写)
锁定卡片:
CMD16(ARG=PWD_LEN+2)
CMD42 数据:0x04(LOCK),PWD_LEN,当前密码
解锁卡片:
CMD16(ARG=PWD_LEN+2)
CMD42 数据:0x08(UNLOCK),PWD_LEN,当前密码
清除密码:
CMD16(ARG=PWD_LEN+2)
CMD42 数据:0x02(CLR_PWD),PWD_LEN,当前密码
修改密码:
CMD16(ARG=OLD_LEN+NEW_LEN+2)
CMD42 数据:0x05(SET_PWD|CLR_PWD),OLD_LEN+NEW_LEN,旧密码,新密码
强制擦除(忘记密码时,会清空数据与密码):
CMD16(ARG=1)
CMD42 数据:0x08(ERASE),0xFF, 0xFF
状态查询:CMD13(R1),检查 bit0(CARD_IS_LOCKED)
以上流程与字段取值符合 SD 规范对 CMD42 的定义与示例实现。
常见坑与建议
必须在“传输状态”下执行 CMD42;在 SD 模式下未正确选卡(CMD7)会导致失败。
CMD42 的数据块长度不要小于 PWD_LEN+2;SPI 模式下块长度请用偶数(1 或 PWD_LEN+2)。
设置/修改密码时,旧密码不正确会置位 LOCK_UNLOCK_FAILED 且不改变 PWD;长度为 0 或 >16 也会失败。
上电若 PWD_LEN ≠ 0,卡会自动锁定;应用需在启动时检测 CARD_IS_LOCKED 并按需解锁。
忘记密码不可逆恢复数据;“强制擦除”会清除数据与密码,慎用。
不要将 CMD42 的“锁定/解锁”与 CMD28/29/30 的“扇区写保护”混淆;后者为可选的按组写保护,且 SDHC/SDXC 不支持
审核编辑 黄宇
全部0条评论
快来发表一下你的评论吧 !