SD NAND写保护问题的分析

电子说

1.4w人已加入

描述

说起SD NAND /SD卡写保护的问题,我们先分析一下出现写保护的一些原因

首先,我们先除去SD大卡的物理开关的问题,目前TF卡和SD NAND都是通过软件进行写保护的开关。

读写中意外断电、未“安全移除”、长期使用产生坏块、空间已满等,系统为避免进一步数据损坏,可能将卡自动挂为“只读”

恶意程序篡改分区表、文件系统设置,甚至设置隐藏的只读/写保护属性,导致无法写入或格式化。

如 ​Windows​ 驱动不兼容、用户权限不足、注册表项(如 Storage Device Policies 的 ​Write Protect)被修改,系统层将设备设为“只读”。

闪存磨损达到设计寿命或主控/电路异常,主控可能启用只读保护,防止数据进一步损坏

电压不足、掉电、浪涌等导致读写中断或文件系统损坏,进而触发只读/写保护现象。这个问题目前是比较常见的,所以供电电压的稳定性很重要,且要高估存储卡的峰值电流和浪涌,这样会导致电压瞬间的变化。

所以保证稳定供电,避免低电量设备中长时间写入;必要时使用稳压与浪涌抑制设计。

SD NAND

写保护开关和密码设定主要是存储芯片命令集中的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​ 不支持

审核编辑 黄宇

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分