目录
1.init_sequence_r
2.initr_sunxi_plat
3.sprite_test
4.关联结构体
uboot启动,首先遍历结构体 init_sequence_r 的函数,函数内部着重分析initr_sunxi_plat、main_loop 两个函数的细则
static init_fnc_t init_sequence_r[] = {
...
initr_sunxi_plat //完成flash的初始化,见下定义
...
initr_env //对应的调试信息:Loading Environment from
...
sunxi_burn_key //对应的调试信息:try to burn key
sunxi_keydata_burn_by_usb
...
initr_net //初始化网络,未用
...
clou_init //厂家自研功能可添加在此
...
main_loop //主函数遍历
s = bootdelay_process()
s = env_get("bootdelay");
s = env_get("bootcmd");
autoboot_command(s)
abortboot(stored_bootdelay) //延时期间可终止uboot运行
__abortboot(bootdelay)
printf("Hit any key to stop autoboot: %2d ", bootdelay);
printf("### main_loop: bootcmd=\"%s\"\n", s ? s : ""); //调试信息输出:### main_loop: bootcmd="run sunxi_sprite_test"
run_command_list(s, -1, 0);
sprite_test read //见下定义的 sprite_test 函数
}
run_command_list中运行的命令为run sunxi_sprite_test,这里非常重要,决定了接下来要执行的动作,调用 sunxi_sprite_test 函数,具体详见内部的细节,sunxi_sprite_test 可通过控制台进入uboot的命令接口,输入 printenv 命令查看,信息如下。
uboot阶段进入控制台的环境变量查看,sunxi_sprite_test 被重定向为 sprite_test read,
=> printenv
bootcmd=run sunxi_sprite_test
bootdelay=0
console=ttyS0,115200
fdtcontroladdr=5be66e70
sunxi_sprite_test=sprite_test read
而 sprite_test 属于uboot的命令,具体如下
U_BOOT_CMD(
sprite_test, 2, 0, do_sprite_test,
"do a sprite test",
"NULL"
);
该阶段函数主要完成:初始化flash设备树、初始化spi设备、flash探测(分区创建)
initr_sunxi_plat
sunxi_flashmap_init //初始化flash设备树
init_spi_all() //初始化spi,包括spi设备树初始化
sunxi_flash_init_ext() //flash初始化
tick_printf("workmode = %d,storage type = %d\n", workmode, storage_type); //“workmode = 16,storage type = 0”:storage_type输出的类型是1,正常是spi-nand STORAGE_SPI_NAND=5
sunxi_flash_probe() //flash探测
current_flash = &sunxi_nand_desc; //sunxi_nand_desc 结构体见下定义
current_flash->probe() //.probe = sunxi_flash_nand_probe
sunxi_flash_nand_probe
ubi_nand_probe_uboot()
spinand_mtd_init() //mtd初始化
aw_spinand_probe(&dev) //从这里开始,见下面 aw_spinand_probe 函数的调用
//1.初始化spinand芯片
aw_spinand_chip_init(slave, chip) //路径:u-boot-2018/drivers/mtd/awnand/spinand/physic/core.c
aw_spinand_chip_preinit(slave, chip) //u-boot-2018/drivers/mtd/awnand/spinand/physic/core.c
spic0_init() //u-boot-2018/drivers/mtd/awnand/spinand/physic/spic_op.c
spic0_pio_request() //u-boot-2018/drivers/mtd/awnand/spinand/physic/spic_op.c
sunxi_dma_request(0)
sunxi_dma_request(0)
spic0_clk_request()
spic0_set_clk(20)
spi_print_info() //未开启,需要使用
aw_spinand_chip_ecc_init(chip)
chip->ecc = &aw_spinand_ecc //见下定义
aw_spinand_chip_ops_init(chip)
chip->ops = &spinand_ops //见下定义
aw_spinand_chip_detect(chip) //u-boot-2018/drivers/mtd/awnand/spinand/physic/core.c
ops->read_id(chip, id, MAX_ID_LEN, dummy)
spinand_detect_munufacture(id[0])
for (index = 0; index < ARRAY_SIZE(spinand_factory); index++)
m = &spinand_factory[index]; //见下定义
aw_spinand_chip_init_last(chip) //u-boot-2018/drivers/mtd/awnand/spinand/physic/core.c
aw_spinand_chip_update_cfg
aw_spinand_chip_cache_init
aw_spinand_chip_bbt_init
bbt->en_bitmap = bbt->bitmap + longcnt; //使能bitmap位
//2.初始化spinand分区
spinand_mtd_init
aw_spinand_init_mtd_info
#if SIMULATE_MULTIPLANE
mtd->oobavail = AW_OOB_SIZE_PER_PHY_PAGE * 2;
mtd->subpage_sft = 1;
#else
mtd->oobavail = AW_OOB_SIZE_PER_PHY_PAGE;
mtd->subpage_sft = 0;
#endif
//3.初始化spinand设备
add_mtd_device
U_BOOT_CMD(
sprite_test, 2, 0, do_sprite_test,
"do a sprite test",
"NULL"
);
do_sprite_test
printf("sunxi work mode=0x%x\n", get_boot_work_mode());
printf("run usb efex\n")
sunxi_usb_main_loop(2500)
sunxi_usb_init(delaytime)
printf("delay time %d\n", delaytime)
otg_phy_config
printf("weak:otg_phy_config\n")
sunxi_udev_active->state_loop //sunxi_efex_state_loop
sunxi_efex_state_loop
调用sunxi_efex_state_loop函数,该函数具体调用流程如下
sunxi_efex_state_loop
dram_data_recv_finish //u-boot-2018/drivers/sunxi_usb/usb_efex.c
nand_get_mbr((char *)trans_data.base_recv_buffer, 16 * 1024); //日志信息:total part: 6 路径:u-boot-2018/drivers/sunxi_flash/nand/nand_for_uboot.c
sunxi_sprite_erase_flash //u-boot-2018/sprite/sprite_erase.c
get_boot_storage_type
ubi_nand_probe_uboot
ubi_nand_attach_mtd
spinand_mtd_attach_mtd
set_env_mtdparts_spinand()
pr_info("mtdparts: %s\n", ubinfo->mtdparts); //mtdparts: mtdparts=nand:2048k@0(boot0)ro,6144k@2097152(uboot)ro,2048k@8388608(secure_storage)ro,-(sys)
create_mtdparts_do()
init_mtd_info(mtd_info)
spinand_init_mtd_info(mtd_info)
pr_info("MTD info (%d)\n", mtd_info->part_cnt);
pr_info("pagesize: 0x%x\n", mtd_info->pagesize);
pr_info("blksize: 0x%x\n", mtd_info->blksize);
pr_info("%-4s %-10s %-10s %s\n", "num", "offset", "bytes", "name");
num = get_mtd_num_to_attach();
pr_info("ubi attach the last part of mtd device: NO.%d\n", num);
ubi_attach_mtd_do
sunxi_do_ubi(0, 3, argv)
do_ubi(NULL, flag, argc, argv)
ubi_part(argv[2], vid_header_offset)
mtd_probe_devices
add_mtd_partitions //分区信息
allocate_partition
mtd_block_isbad(master, offs + slave->offset)
mtd->_block_isbad(mtd, ofs) //slave->_block_isbad = part_block_isbad
part_block_isbad
mtd->parent->_block_isbad(mtd->parent, ofs) // mtd->_block_isbad = aw_spinand_block_isbad;!!!!
aw_spinand_block_isbad
addr_to_req(chip, &req, offs) //这里转换的block出问题了!!!明天待分析
//是这里引发的两页
static unsigned int aw_spinand_info_page_size(struct aw_spinand_chip *chip)
{
#if SIMULATE_MULTIPLANE
return aw_spinand_info_phy_page_size(chip) * 2;
#else
return aw_spinand_info_phy_page_size(chip);
#endif
}
ops->phy_is_bad(chip, &req) //见下调用 aw_spinand_chip_isbad_single_block
sunxi_sprite_force_erase
ubi_nand_force_erase
spinand_mtd_force_erase
spinand_mtd_erase
spinand_mtd_erase_boot 或者 spinand_mtd_erase_data
do_erase_block
ops->phy_is_bad(chip, &req) //.phy_is_bad = aw_spinand_chip_isbad_single_block
aw_spinand_chip_isbad_single_block
bbt->is_badblock(chip, req->block) //aw_spinand_bbt_is_badblock
_aw_spinand_chip_isbad_single_block //u-boot-2018/drivers/mtd/awnand/spinand/physic/non-ops.c
aw_spinand_chip_read_single_page //u-boot-2018/drivers/mtd/awnand/spinand/physic/non-ops.c
aw_spinand_chip_load_page(chip, req) //发起请求:从flash读取一页,block的页大小,以下三条是正常的spi-nandflash指令
spi0_write(txbuf, 4, SPI0_MODE_AUTOSET)
aw_spinand_chip_wait(chip, &status) //等待请求
ops->read_status(chip, &s)
aw_spinand_chip_read_from_cache(chip, req) //读取应答数据
chip->cache->read_from_cache(chip, req);
aw_spinand_chip_check_ecc //校验ECC
ecc->check_ecc
aw_spinand_ecc_check_ecc
general_check_ecc
bbt->mark_badblock(chip, req->block, true) //标记坏块或好块 aw_spinand_bbt_mark_badblock
spinand_mtd_erase_data
。。。与上流程一致
static struct aw_spinand_ecc aw_spinand_ecc = {
.copy_to_oob = aw_spinand_ecc_copy_to_oob,
.copy_from_oob = aw_spinand_ecc_copy_from_oob,
.check_ecc = aw_spinand_ecc_check_ecc,
};
static struct aw_spinand_chip_ops spinand_ops = {
.get_block_lock = aw_spinand_chip_get_block_lock,
.set_block_lock = aw_spinand_chip_set_block_lock,
.get_otp = aw_spinand_chip_get_otp,
.set_otp = aw_spinand_chip_set_otp,
.get_driver_level = aw_spinand_chip_get_driver_level,
.set_driver_level = aw_spinand_chip_set_driver_level,
.reset = aw_spinand_chip_reset,
.read_status = aw_spinand_chip_read_status,
.read_id = aw_spinand_chip_read_id,
.write_reg = aw_spinand_chip_write_reg,
.read_reg = aw_spinand_chip_read_reg,
#if SIMULATE_MULTIPLANE
.is_bad = aw_spinand_chip_isbad_super_block,
.mark_bad = aw_spinand_chip_markbad_super_block,
.erase_block = aw_spinand_chip_erase_super_block,
.write_page = aw_spinand_chip_write_super_page,
.read_page = aw_spinand_chip_read_super_page,
#else
.is_bad = aw_spinand_chip_isbad_single_block,
.mark_bad = aw_spinand_chip_markbad_single_block,
.erase_block = aw_spinand_chip_erase_single_block,
.write_page = aw_spinand_chip_write_single_page,
.read_page = aw_spinand_chip_read_single_page,
#endif
.phy_is_bad = aw_spinand_chip_isbad_single_block,
.phy_mark_bad = aw_spinand_chip_markbad_single_block,
.phy_erase_block = aw_spinand_chip_erase_single_block,
.phy_write_page = aw_spinand_chip_write_single_page,
.phy_read_page = aw_spinand_chip_read_single_page,
.phy_copy_block = aw_spinand_chip_copy_single_block,
};
sunxi_flash_desc sunxi_nand_desc =
{
.probe = sunxi_flash_nand_probe,
.init = sunxi_flash_nand_init,
.exit = sunxi_flash_nand_exit,
.read = sunxi_flash_nand_read,
#if defined(CONFIG_AW_MTD_SPINAND) || defined(CONFIG_AW_MTD_RAWNAND)
.phyread = sunxi_flash_nand_phyread,
.phywrite = sunxi_flash_nand_phywrite,
#endif
.write = sunxi_flash_nand_write,
.erase = sunxi_flash_nand_erase,
.force_erase = sunxi_flash_nand_force_erase,
.flush = sunxi_flash_nand_flush,
.size = sunxi_flash_nand_size,
.secstorage_read = sunxi_flash_nand_secstorage_read,
.secstorage_write = sunxi_flash_nand_secstorage_write,
#ifdef CONFIG_SUNXI_FAST_BURN_KEY
.secstorage_fast_write = sunxi_flash_nand_secstorage_fast_write,
.secstorage_flush = sunxi_flash_nand_secstorage_flush,
#endif
.download_spl = sunxi_flash_nand_download_spl,
.download_toc = sunxi_flash_nand_download_toc,
.write_end = sunxi_flash_nand_write_end,
};
#define SPINAND_FACTORY_INFO(_id, _name, _info) \
{ \
.id = _id, \
.name = _name, \
.info = _info, \
.cnt = ARRAY_SIZE(_info), \
}
static struct spinand_manufacture spinand_factory[] = {
SPINAND_FACTORY_INFO(MICRON_MANUFACTURE, "Micron", micron),
SPINAND_FACTORY_INFO(GD_MANUFACTURE, "GD", gigadevice),
SPINAND_FACTORY_INFO(ATO_MANUFACTURE, "ATO", ato),
SPINAND_FACTORY_INFO(WINBOND_MANUFACTURE, "Winbond", winbond),
SPINAND_FACTORY_INFO(MXIC_MANUFACTURE, "Mxic", mxic),
SPINAND_FACTORY_INFO(TOSHIBA_MANUFACTURE, "Toshiba", toshiba),
SPINAND_FACTORY_INFO(ETRON_MANUFACTURE, "Etron", etron),
SPINAND_FACTORY_INFO(XTXTECH_MANUFACTURE, "XTX", xtx),
SPINAND_FACTORY_INFO(DSTECH_MANUFACTURE, "Dosilicon", dosilicon),
SPINAND_FACTORY_INFO(FORESEE_MANUFACTURE, "Foresee", foresee),
SPINAND_FACTORY_INFO(ZETTA_MANUFACTURE, "Zetta", zetta),
SPINAND_FACTORY_INFO(FM_MANUFACTURE, "FM", fm),
};
enum ecc_type {
ECC_TYPE_ERR = 0,
BIT3_LIMIT3_TO_6_ERR7,
BIT2_LIMIT1_ERR2,
BIT2_LIMIT1_ERR2_LIMIT3,
BIT4_LIMIT3_TO_4_ERR15,
BIT3_LIMIT3_TO_4_ERR7,
BIT3_LIMIT5_ERR2,
BIT4_LIMIT5_TO_7_ERR8_LIMIT_12,
BIT4_LIMIT5_TO_7_ERR8,
BIT2_LIMIT3_ERR2,
BIT3_LIMIT3_LIMIT_5_ERR2,
BIT4_LIMIT5_TO_8_ERR15,
BIT3_LIMIT2_TO_6_ERR7,
};
extern __s32 spinand_check_ecc(enum ecc_type type, __u8 status);