菜鸟科技网

uboot sf命令如何使用及参数详解?

sfSerial Flash 的缩写,它用于与 SPI(Serial Peripheral Interface)接口的闪存芯片进行交互,这种闪存芯片在嵌入式系统中非常常见,例如用于存储引导程序(如 U-Boot 本身)、设备树、内核镜像等。

uboot sf命令如何使用及参数详解?-图1
(图片来源网络,侵删)

sf 命令是 U-Boot 提供的一个强大工具集,主要用于:

  • 读取 (read) 闪存内容。
  • 写入 (write) 数据到闪存。
  • 擦除 (erase) 闪存的某个区域。
  • 更新 (update) 闪存(一个结合了擦除和写入的原子操作)。
  • 保护 (protect) 设置闪存的写保护区域。

前提条件:环境配置

在使用 sf 命令之前,必须确保 U-Boot 已经正确配置并加载了 SPI Flash 驱动。

  1. 内核配置: 在 U-Boot 的配置文件(如 configs/<board_name>_defconfig)中,必须启用相关的 SPI 选项。

    CONFIG_CMD_SF=y          // 启用 sf 命令
    CONFIG_SPI_FLASH=y       // 启用 SPI Flash 支持
    CONFIG_SPI_FLASH_WINBOND=y // 根据你板子上实际的 Flash 型号选择对应的驱动
    // ... 其他 SPI 相关配置,如 CONFIG_DM_SPI, CONFIG_DM_SPI_FLASH 等
  2. 设备树配置: 在板子的设备树文件中,必须正确描述 SPI 控制器和 Flash 芯片,这通常包括:

    uboot sf命令如何使用及参数详解?-图2
    (图片来源网络,侵删)
    • SPI 控制器的节点(如 spi0, spi1)。
    • Flash 芯片作为 SPI 控制器的一个子节点,并指定其兼容型号(compatible),winbond,w25q32
    • Flash 芯片的寄存器大小(reg)。
  3. 运行时环境: 在 U-Boot 命令行中,可能需要先初始化 SPI 总线,这通常通过 sf probe 命令完成。


sf 命令详解

sf 命令的基本格式是 sf <operation> [offset] [size] [addr]

sf probe [bus:num]

  • 作用:探测并初始化 SPI Flash 设备。

  • 参数

    uboot sf命令如何使用及参数详解?-图3
    (图片来源网络,侵删)
    • bus:num (可选): 指定要探测的 SPI 总线号和从设备号。sf probe 0:0 表示探测第 0 个 SPI 总线上的第 0 个从设备,如果不指定,U-Boot 会使用默认配置。
  • 示例

    # 探测默认的 SPI Flash
    sf probe
    # 探测 SPI 总线 0 上的从设备 0
    sf probe 0:0

sf read <addr> <offset> <size>

  • 作用:从 SPI Flash 的指定偏移量处读取数据到内存的指定地址。
  • 参数
    • addr: 目标内存地址(0x81000000)。
    • offset: 在 SPI Flash 中的起始偏移量(0x0)。
    • size: 要读取的字节数(0x100000,表示 1MB)。
  • 示例
    # 从 Flash 的 0x0 地址读取 1MB 数据到内存 0x81000000
    sf read 0x81000000 0x0 0x100000

sf write <addr> <offset> <size>

  • 作用:将内存中的数据写入到 SPI Flash 的指定偏移量处。
  • 参数
    • addr: 源数据在内存中的地址。
    • offset: 在 SPI Flash 中的目标起始偏移量。
    • size: 要写入的字节数。
  • 示例
    # 将内存中 0x81000000 处的 1MB 数据写入到 Flash 的 0x0 地址
    sf write 0x81000000 0x0 0x100000
  • 注意:写入操作前,目标区域必须已经被擦除,Flash 芯片只能将 1 写成 0,不能将 0 写成 1

sf erase <offset> <size>

  • 作用:擦除 SPI Flash 的指定区域,擦除操作会将指定区域的所有位都设置为 1

  • 参数

    • offset: 要擦除的起始偏移量。
    • size: 要擦除的字节数。
  • 重要:擦除操作必须以 Flash 芯片支持的扇区为单位进行,你不能只擦除一个字节,如果 Flash 的扇区大小是 4KB (0x1000),那么擦除大小必须是 0x1000 的整数倍。

  • 示例

    # 擦除从 Flash 的 0x0 地址开始的 1MB 区域
    # 假设 1MB 是 Flash 扇区大小的整数倍
    sf erase 0x0 0x100000
    # 擦除一个扇区 (假设扇区大小为 4KB)
    sf erase 0x10000 0x1000

sf update <addr> <offset> <size>

  • 作用:这是一个非常有用的复合命令,它会先擦除目标区域,然后再写入数据,它比手动执行 erase + write 更安全,因为它是一个原子操作(在 U-Boot 的执行层面),可以避免在擦除和写入之间发生意外断电导致数据损坏。
  • 参数:与 write 命令相同。
  • 示例
    # 将 u-boot.bin 更新到 Flash 的 0x0 位置
    # 假设 u-boot.bin 已经加载到内存 0x82000000
    sf update 0x82000000 0x0 ${filesize}

    注意:这里使用了 U-Boot 的环境变量 ${filesize},该变量在通过 loadfatload 等命令加载文件时自动设置。

sf protect lock/unlock <offset> <size>

  • 作用:锁定或解锁 Flash 的特定区域,防止意外写入或擦除,这通常对应 Flash 芯片的 BP (Block Protection) 寄存器。

  • 参数

    • lock / unlock: 操作类型。
    • offset: 要保护/取消保护的起始偏移量。
    • size: 要保护/取消保护的区域大小。
  • 示例

    # 锁定从 0x0 开始的 512KB 区域,防止被修改
    sf protect lock 0x0 0x80000
    # 解锁上述区域
    sf protect unlock 0x0 0x80000

实用场景和完整示例

假设你的开发板上有一片 Winbond W25Q32 SPI Flash (4MB),U-Boot 已经加载到内存地址 0x81000000,你想将它烧录到 Flash 的 0x0 位置。

步骤 1:探测 Flash

U-Boot> sf probe
SF: Detected W25Q32 with page size 256 Bytes, erase size 4 KiB, total 4 MiB

看到这个输出说明 Flash 探测成功,U-Boot 识别出了它的型号(W25Q32)、页大小、擦除块大小和总容量。

步骤 2:擦除目标区域

W25Q32 的擦除块大小通常是 4KB (0x1000),我们要烧录整个 U-Boot,假设它的大小是 512KB,那么我们需要擦除一个至少 512KB 的区域,为了对齐,我们擦除 1MB (0x100000)。

U-Boot> sf erase 0x0 0x100000
SF: 1048576 bytes @ 0xx00000000 erased: OK

步骤 3:写入数据

将内存中的 U-Boot 写入到刚刚擦除的区域。

U-Boot> sf write 0x81000000 0x0 ${filesize}
SF: 524288 bytes @ 0x00000000 written: OK

注意:这里 ${filesize} 变量需要事先被设置,如果你是手动加载的二进制文件,需要先计算好大小并设置该变量。

步骤 4:验证写入(可选但推荐)

为了确保写入成功,我们可以将刚刚写入的数据读回内存的另一个地址,然后与原始数据进行比较。

# 1. 从 Flash 读回数据到新的内存地址
U-Boot> sf read 0x82000000 0x0 0x100000
# 2. 比较原始数据和读回的数据
#    假设原始数据在 0x81000000,读回的在 0x82000000,比较大小为 512KB
U-Boot> cmp.b 0x81000000 0x82000000 0x80000
# 如果输出为 "Total of 0x80000 bytes were the same",则说明写入成功。

使用 sf update 命令(更简单的方法)

上面的步骤 2 和 3 可以合并为一步,使用 sf update 命令,它会自动处理擦除和写入。

U-Boot> sf update 0x81000000 0x0 ${filesize}
SF: 524288 bytes @ 0x00000000 erased: OK
SF: 524288 bytes @ 0x00000000 written: OK

这个命令更简洁,是推荐的更新方式。


常见问题与排错

  1. sf probe 失败或未定义命令

    • 原因:U-Boot 编译时没有开启 CONFIG_CMD_SF
    • 解决:重新编译 U-Boot,确保配置文件中启用了该选项。
  2. sf erasesf write 报错 "erase/write failed"

    • 原因
      • 写入前没有擦除区域。
      • 擦除/写入的大小不是 Flash 扇区大小的整数倍。
      • Flash 芯片被锁定 (sf protect lock)。
      • SPI 时钟频率过高,导致不稳定。
      • Flash 型号在设备树中配置错误。
    • 解决
      • 检查是否先执行了 erase
      • 确认你的 Flash 芯片扇区大小,并对齐擦除/写入大小。
      • 尝试解锁 Flash (sf protect unlock)。
      • 在设备树中降低 SPI 时钟频率。
  3. sf read 读出的数据不正确

    • 原因
      • 内存地址 addr 与 U-Boot 的 memmap 冲突,导致数据被覆盖。
      • Flash 的偏移量 offset 计算错误。
    • 解决
      • 使用一个安全的内存地址,通常是 U-Boot 之后或 DRAM 的保留区域。
      • 仔细核对 Flash 的分区布局,确保偏移量正确。

希望这份详细的指南能帮助你更好地理解和使用 U-Boot 的 sf 命令!

分享:
扫描分享到社交APP
上一篇
下一篇