首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >SD NAND写保护问题的分析

SD NAND写保护问题的分析

原创
作者头像
杭州瀚海微
发布2025-10-21 10:26:57
发布2025-10-21 10:26:57
1710
举报

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

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

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

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

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

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

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

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

写保护开关和密码设定主要是存储芯片命令集中的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​(偶数)。
  • 设置密码(首次设置):
    1. CMD16(ARG=PWD_LEN+2)
    2. 发送 CMD42(CMD=0x6A, ARG=0x00000000, CRC=0x95)
    3. 数据块:0x01(SET_PWD),PWD_LEN,旧密码(无则填 0),新密码
    4. 结束:附加 0xFF 填充至整块,发送 16 位 CRC
    5. 用 CMD16 恢复块长度为 512(如需后续常规读写)
  • 锁定卡片:
    1. CMD16(ARG=PWD_LEN+2)
    2. CMD42 数据:0x04(LOCK),PWD_LEN,当前密码
  • 解锁卡片:
    1. CMD16(ARG=PWD_LEN+2)
    2. CMD42 数据:0x08(UNLOCK),PWD_LEN,当前密码
  • 清除密码:
    1. CMD16(ARG=PWD_LEN+2)
    2. CMD42 数据:0x02(CLR_PWD),PWD_LEN,当前密码
  • 修改密码:
    1. CMD16(ARG=OLD_LEN+NEW_LEN+2)
    2. CMD42 数据:0x05(SET_PWD|CLR_PWD),OLD_LEN+NEW_LEN,旧密码,新密码
  • 强制擦除(忘记密码时,会清空数据与密码):
    1. CMD16(ARG=1)
    2. 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​ 不支持.

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档