3.6.5. SPI NOR 加载

common/spl/spl_spi.c 中通过宏注册了 SPI NOR 的程序加载器。

SPL_LOAD_IMAGE_METHOD("SPI", 1, BOOT_DEVICE_SPI, spl_spi_load_image);

在 SPL 初始化过程中,通过 boot_from_devices(spl_boot_list) 函数调用,检查当前项目 所支持的 SPL 读取的存储介质类型,然后依次检查是否存在对应的程序加载器。

board_init_r()    // common/spl/spl.c
|-> boot_from_devices(spl_boot_list)
    |-> spl_ll_find_loader()  // 根据boot device找到spl_load_image指针
            // 这里可能是各种介质的 load image 函数
            // SPL_LOAD_IMAGE_METHOD() 定义的 Loader
            // 可能是 MMC/SPI/BROM/...

找到 SPL SPI NOR Loader 之后,从项目配置的指定位置读取数据。

SPI NOR 加载器需要编译时配置所用的 SPI 信息:

  • CONFIG_SF_DEFAULT_BUS

  • CONFIG_SF_DEFAULT_CS

  • CONFIG_SF_DEFAULT_SPEED

  • CONFIG_SF_DEFAULT_MODE

读取数据的位置通过下面的配置指定:

  • CONFIG_SYS_SPI_U_BOOT_OFFS

boot_from_devices(spl_boot_list); // common/spl/spl.c
|-> spl_ll_find_loader()  // 根据boot device找到spl_load_image指针
|   // 此处通过遍历固件的 .u_boot_list_2_spl_image_loader_* 段
|   // 找到当前支持的存储介质,然后逐个尝试
|
|-> spl_load_image(loader);
    |-> loader->load_image(spl_image, &bootdev);
        spl_spi_load_image();  // common/spl/spl_spi.c
        |-> spi_flash_probe();
        |-> spl_get_load_buffer(-sizeof(*header), sizeof(*header));
        |-> spi_flash_read(header);
        |-> spl_parse_image_header();
        |-> spi_flash_read();
            |-> spi_flash_read_dm(flash->dev, offset, len, buf);
                |-> sf_get_ops(dev)->read(dev, offset, len, buf);
                    spi_flash_std_read(dev, offset, len, buf);
                    | // drivers/mtd/spi/sf_probe.c
                    |-> mtd->_read(mtd, offset, len, &retlen, buf);
                            spi_flash_mtd_read(mtd, offset, len, &retlen, buf);
                            // drivers/mtd/spi/sf_mtd.c