这个命令是 uboot实现了 对flash 的读写初始化功能,挂载在spi总线下;
执行sf probe 就是对spi总线和 flash的初始化;
命令声明: u_BOOT_CMD大家都知道就是定义uboot模式下的命令行;然后uboot在main_loop下循环检测串口指令来解析调用相应命令
U_BOOT_CMD(
sf, 5, 1, do_spi_flash,
"SPI flash sub-system",
"probe [[bus:]cs] [hz] [mode] - init flash device on given SPI bus\n"
" and chip select\n"
"sf read addr offset|partition len - read `len' bytes starting at\n"
" `offset' or from start of mtd\n"
" `partition'to memory at `addr'\n"
"sf write addr offset|partition len - write `len' bytes from memory\n"
" at `addr' to flash at `offset'\n"
" or to start of mtd `partition'\n"
"sf erase offset|partition [+]len - erase `len' bytes from `offset'\n"
" or from start of mtd `partition'\n"
" `+len' round up `len' to block size\n"
"sf update addr offset|partition len - erase and write `len' bytes from memory\n"
" at `addr' to flash at `offset'\n"
" or to start of mtd `partition'\n"
"sf protect lock/unlock sector len - protect/unprotect 'len' bytes starting\n"
" at address 'sector'\n"
SF_TEST_HELP
);
最初就是调用这个函数:
static int do_spi_flash(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[])
{
const char *cmd;
int ret;
/* need at least two arguments */
if (argc < 2)
goto usage;
cmd = argv[1];
--argc;
++argv;
if (strcmp(cmd, "probe") == 0) {
ret = do_spi_flash_probe(argc, argv);
goto done;
}
/* The remaining commands require a selected device */
if (!flash) {
puts("No SPI flash selected. Please run `sf probe'\n");
return 1;
}
if (strcmp(cmd, "read") == 0 || strcmp(cmd, "write") == 0 ||
strcmp(cmd, "update") == 0)
ret = do_spi_flash_read_write(argc, argv);
else if (strcmp(cmd, "erase") == 0)
ret = do_spi_flash_erase(argc, argv);
else if (strcmp(cmd, "protect") == 0)
ret = do_spi_protect(argc, argv);
#ifdef CONFIG_CMD_SF_TEST
else if (!strcmp(cmd, "test"))
ret = do_spi_flash_test(argc, argv);
#endif
else
ret = -1;
done:
if (ret != -1)
return ret;
usage:
return CMD_RET_USAGE;
}
就是调用这个函数:
static int do_spi_flash_probe(int argc, char * const argv[])
{
unsigned int bus = CONFIG_SF_DEFAULT_BUS;
unsigned int cs = CONFIG_SF_DEFAULT_CS;
unsigned int speed = CONFIG_SF_DEFAULT_SPEED;
unsigned int mode = CONFIG_SF_DEFAULT_MODE;
char *endp;
#ifdef CONFIG_DM_SPI_FLASH
struct udevice *new, *bus_dev;
int ret;
/* In DM mode defaults will be taken from DT */
speed = 0, mode = 0;
#else
struct spi_flash *new;
#endif
if (argc >= 2) {
cs = simple_strtoul(argv[1], &endp, 0);
if (*argv[1] == 0 || (*endp != 0 && *endp != ':'))
return -1;
if (*endp == ':') {
if (endp[1] == 0)
return -1;
bus = cs;
cs = simple_strtoul(endp + 1, &endp, 0);
if (*endp != 0)
return -1;
}
}
if (argc >= 3) {
speed = simple_strtoul(argv[2], &endp, 0);
if (*argv[2] == 0 || *endp != 0)
return -1;
}
if (argc >= 4) {
mode = simple_strtoul(argv[3], &endp, 16);
if (*argv[3] == 0 || *endp != 0)
return -1;
}
#ifdef CONFIG_DM_SPI_FLASH
/* Remove the old device, otherwise probe will just be a nop */
ret = spi_find_bus_and_cs(bus, cs, &bus_dev, &new);
if (!ret) {
device_remove(new, DM_REMOVE_NORMAL);
}
flash = NULL;
ret = spi_flash_probe_bus_cs(bus, cs, speed, mode, &new);
if (ret) {
printf("Failed to initialize SPI flash at %u:%u (error %d)\n",
bus, cs, ret);
return 1;
}
flash = dev_get_uclass_priv(new);
#else
if (flash)
spi_flash_free(flash);
new = spi_flash_probe(bus, cs, speed, mode);
flash = new;
if (!new) {
printf("Failed to initialize SPI flash at %u:%u\n", bus, cs);
return 1;
}
flash = new;
#endif
return 0;
}
函数内部都是对flash的操作,就是内存向flash 写入; 从flash读取写入内存;擦除flash 块等操作
命令是:
那么sf 命令功能也就清楚了,就是对flash操作的指令;
sf probe初始化flash 或者说初始化spi总线;
sf read addr offset|partition len - read `len' bytes starting at\n"
sf write addr offset|partition len - write `len' bytes from memory\n"
addr :内存地址
offset|partition: flash的偏移地址
len:读取的大小(字节为单位)
举例:
sf probe; sf read 0x2000000 0 0x400000
初始化 spi; 从 flash 0 地址 读取 0x400000 个字节 ,读取到0x2000000 ,结束地址就是0x2000000+0x400000;
从flash 中读取,然后通过md 查看内存中数据;
sf erase offset|partition [+]len - erase `len' bytes from `offset'
sf write addr offset|partition len - write `len' bytes from memory\n"
sf write 之前一定要先执行初始化和 擦除
sf probe && sf erase 0x1a00000 +4
&& sf write 0x2000000 0x1a00000 4 && sf read 0x2000010 0x1a00000 4
初始化,擦除 flash 0x1a00000 地址为起点,擦除大小 4个字节(这里+4没错哈,人家就是这约定的),
吧内存中0x2000000 的值写入到 0x1a00000 写四个字节大小
从flash 0x1a00000的地址读取四个字节, 读取到内存0x2000010
验证:
这样可以验证我们能不能写入成功;下面是我操作的步骤;
我们先通过mw 向内存 0x2000000 写123456789 但是我操作有问题哈;
之后擦除flash 然后选个空间 吧 0x2000000 对应的值123456789写进去
我们换个内存地址再读取出来;
我多写了几个地址没问题哈能写进去的;