4. 存储设备操作命令(mmc/sf/sata):MMC/SD 卡探测与读写、SPI Flash 操作、SATA 硬盘操作

存储设备操作,是 U-Boot 调试中最常打交道的一类命令。说白了,你总得把内核镜像、设备树、文件系统塞到某个地方去。MMC/SD 卡、SPI Flash、SATA 硬盘,这三样几乎覆盖了嵌入式设备 90% 的存储场景。我个人习惯,拿到一块新板子,第一件事就是把这几个命令挨个敲一遍,确认存储通路是通的。

核心要点: 本章聚焦三大存储接口的探测、读写与故障定位。掌握这些命令,你就掌握了 U-Boot 下数据搬运的基本功。

4.1 MMC/SD 卡操作:从探测到读写

MMC 子系统是 U-Boot 里最成熟的驱动之一。但成熟不代表不出问题。我遇到过好几次,板子启动后执行 mmc list 啥也看不到,最后发现是硬件上电时序没满足。

4.1.1 设备探测与信息查看

先看几个最常用的命令:

# 列出所有 MMC 设备
U-Boot> mmc list
# 输出示例:
# mmc@fe320000: 0 (eMMC)
# mmc@fe330000: 1 (SD)

# 切换到指定设备
U-Boot> mmc dev 0
# 切换到 mmc 0 (eMMC)

# 查看当前设备详细信息
U-Boot> mmc info
# 输出示例:
# Device: mmc@fe320000
# Manufacturer ID: 15
# OEM: 100
# Name: 8GTF4R
# Bus Speed: 52000000
# Mode: HS200
# Rd Block Len: 512
# Capacity: 7.3 GiB
# ...

这里有个细节:mmc info 显示的 Bus Speed 和 Mode 非常关键。如果速度上不去,或者模式不对(比如本该跑 HS400 却只跑了 HS200),大概率是时序配置或者电压切换出了问题。

我的习惯: 每次换一块新板子,我都会先跑一遍 mmc info,把容量、速度、模式记下来。后面调试启动速度时,这些数据就是基准线。

4.1.2 分区查看与读写操作

MMC 设备通常有多个分区。eMMC 更是有 Boot 分区、RPMB 分区、用户数据分区。你得知道怎么切分区:

# 查看分区表
U-Boot> mmc part

# 切换到 eMMC 的 Boot 分区 1
U-Boot> mmc dev 0
U-Boot> mmc partconf 0 1 1 0

# 读取数据:从 mmc 0 的 0x200 扇区开始,读 0x100 个扇区到内存 0x10000000
U-Boot> mmc read 0x10000000 0x200 0x100

# 写入数据:将内存 0x10000000 的数据写入 mmc 0 的 0x200 扇区,写 0x100 个扇区
U-Boot> mmc write 0x10000000 0x200 0x100

嗯,这里要注意 扇区地址 的单位。U-Boot 里 MMC 的地址默认是 512 字节块 地址,不是字节地址。我见过有人把 mmc read 的地址当字节地址用,结果读出来的数据全是乱的。

避坑指南: 我曾经在调试一个量产项目时,发现 mmc write 总是写到一半卡死。排查了半天,发现是 eMMC 的 Boot 分区被写保护了。执行 mmc wp 查看写保护状态,果然 Boot 分区是只读的。解决方案:先切到用户数据分区再写。

4.1.3 常见故障与定位

故障现象 可能原因 排查命令/方法
mmc list 无输出 硬件未上电、时钟未使能、驱动未匹配 检查 clk_summary,确认 GPIO 上电时序
mmc read 返回错误 地址越界、CRC 校验失败、电压不匹配 用 mmc dev 确认当前设备,检查电压切换日志
读写速度极慢 总线宽度未配置、时钟频率过低 查看 mmc info 的 Bus Speed,检查 dts 中 bus-width 属性
写操作卡死 写保护、坏块、电源不稳 执行 mmc wp 查看保护状态,换一个扇区测试

4.2 SPI Flash 操作:小而精的存储

SPI Flash 虽然容量小,但在嵌入式系统里地位特殊——它通常用来存 U-Boot 本身、环境变量、或者 FPGA 配置文件。你想想看,如果 SPI Flash 读写出了问题,板子可能连 U-Boot 都起不来。

4.2.1 探测与擦除

SPI Flash 的操作命令以 sf 开头。先探测:

# 探测 SPI Flash 设备
U-Boot> sf probe
# 输出示例:
# SF: Detected w25q128 with page size 256 Bytes, erase size 4 KiB, total 16 MiB

# 擦除:从 0x100000 地址开始,擦除 0x10000 字节
U-Boot> sf erase 0x100000 0x10000

这里有个关键信息:erase size。SPI Flash 的擦除是以扇区(Sector)为单位的,不同型号的扇区大小不一样。W25Q128 是 4 KiB,有些老型号是 64 KiB。如果你擦除的起始地址不对齐扇区边界,命令会直接报错。

我个人经验: 写 SPI Flash 之前,一定要先擦除。不擦除直接写,数据会乱掉。我习惯用 sf erase 先清空目标区域,再用 sf write 写入。虽然多了一步,但稳。

4.2.2 读写操作

# 读取:从 SPI Flash 0x100000 地址读 0x10000 字节到内存 0x10000000
U-Boot> sf read 0x10000000 0x100000 0x10000

# 写入:将内存 0x10000000 的数据写入 SPI Flash 0x100000 地址,写 0x10000 字节
U-Boot> sf write 0x10000000 0x100000 0x10000

注意,sf 命令的地址是 字节地址,跟 MMC 的扇区地址不一样。这个很容易搞混。我刚开始用的时候也犯过这个错,把 SPI Flash 的地址当扇区地址用,结果读出来的数据长度差了 512 倍。

4.2.3 保护与校验

SPI Flash 通常有硬件写保护引脚(WP#)和状态寄存器保护位。如果你发现写不进去,先检查保护状态:

# 查看 SPI Flash 状态寄存器
U-Boot> sf protect
# 输出示例:
# SPI Flash protection: Blocks 0-255 are protected

# 解除保护(如果支持)
U-Boot> sf protect off
避坑指南: 我曾经在一个工控项目上,量产阶段发现 SPI Flash 写入偶尔失败。排查到最后,发现是 WP# 引脚被拉低了。硬件设计上 WP# 接了上拉电阻,但 PCB 走线过长,导致信号不稳定。解决方案:在 U-Boot 里加了一段延时,等 WP# 稳定后再操作。

4.3 SATA 硬盘操作:大容量存储的王者

SATA 硬盘在嵌入式系统里用得相对少一些,但一旦用上,就是大容量场景——比如 NAS、视频监控、边缘服务器。U-Boot 对 SATA 的支持已经很成熟了,操作命令跟 MMC 类似。

4.3.1 设备探测与初始化

# 扫描 SATA 总线,探测设备
U-Boot> sata init
# 输出示例:
# SATA link 0 found.
# SATA device 0: Model: ST1000DM003-1CH162, Capacity: 931.5 GiB

# 列出所有 SATA 设备
U-Boot> sata info

sata init 这一步很关键。如果 SATA 链路没有建立,后面的读写操作全都会失败。我遇到过一种情况:硬盘本身是好的,但 SATA 线缆接触不良,导致链路训练失败。重新插拔一下就好了。

4.3.2 分区与读写

# 查看分区表
U-Boot> sata part

# 读取:从 sata 0 的 0x800 扇区开始,读 0x2000 个扇区到内存 0x20000000
U-Boot> sata read 0x20000000 0x800 0x2000

# 写入:将内存 0x20000000 的数据写入 sata 0 的 0x800 扇区
U-Boot> sata write 0x20000000 0x800 0x2000

跟 MMC 一样,SATA 的地址也是 512 字节扇区地址。但 SATA 硬盘的扇区大小可能是 4K(Advanced Format),U-Boot 内部会做转换,你不用担心。

4.3.3 性能与故障排查

故障现象 可能原因 排查命令/方法
sata init 找不到设备 SATA 链路未建立、电源不足、驱动未加载 检查 SATA 电源指示灯,用示波器看 SATA 差分信号
读写速度慢 SATA 版本协商为 1.5Gbps、DMA 未开启 查看 sata info 的链路速度,检查 dts 中 ahci 配置
写入时断时续 电源纹波大、线缆屏蔽不良 换电源、换线缆、检查接地
我的建议: 如果 SATA 读写速度异常,先别急着调软件。用 sata init 看链路速度,如果只有 1.5Gbps,说明硬件协商出了问题。我遇到过 SATA 线缆太长导致信号衰减,换了一根短一点的线,速度直接翻倍。

4.4 知识体系总览

下面这张图,把本章的三大存储接口的操作流程和关键命令串起来了。你可以把它当作调试时的速查地图。

存储设备操作命令知识体系 存储设备操作命令知识体系 MMC/SD 卡 SPI Flash SATA 硬盘 mmc list / dev mmc info / part mmc read mmc write sf probe sf erase sf read sf write sata init sata info sata read sata write 故障排查公共流程 ① 确认设备枚举 ② 检查链路/速度 ③ 验证读写通路 ④ 检查保护/电源 核心原则:先探测 → 再查看信息 → 最后读写操作 遇到故障时,按 ①→②→③→④ 顺序排查

4.5 本章小结

存储设备操作命令,说白了就是三板斧:探测、查看、读写。MMC、SPI Flash、SATA 的命令虽然不同,但逻辑是一样的。你只要记住每个接口的地址单位(MMC/SATA 是扇区地址,SPI Flash 是字节地址),再记住先擦除后写入的原则,基本不会出大问题。

嗯,最后再啰嗦一句:调试存储设备时,日志是最好的朋友。U-Boot 的串口输出里,驱动初始化阶段会打印很多关键信息——比如 MMC 的电压切换日志、SPI Flash 的 JEDEC ID、SATA 的链路协商结果。把这些日志抓下来,很多问题一眼就能看出来。