allwinner uboot引导阶段分析

目录

1.init_sequence_r

2.initr_sunxi_plat

3.sprite_test

4.关联结构体


1.init_sequence_r

uboot启动,首先遍历结构体 init_sequence_r 的函数,函数内部着重分析initr_sunxi_platmain_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 : "<UNDEFINED>");	//调试信息输出:### 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"
            );

2.initr_sunxi_plat

该阶段函数主要完成:初始化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					

3.sprite_test

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
				。。。与上流程一致

4.关联结构体

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);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Allwinner V3S是一款高性能、低功耗的嵌入式处理器,由Allwinner Technology开发。它基于ARM Cortex-A7架构,采用28纳米工艺制造,具有512MB RAM和4GB flash存储器,支持多种外设接口,包括多个串行接口、USB接口、以太网接口等。 Allwinner V3S适用于物联网、智能家居、智能穿戴、可穿戴设备和智能安防等领域,它的设计目标是提供一种低成本、高效能的解决方案,为这些领域的应用提供更好的性能和使用体验。它可以支持多种操作系统,包括Linux和Android等,并且可以充分发挥这些操作系统的优势,提高系统的性能和稳定性。 Allwinner V3S有一个详细的技术规格书(PDF),其中包含了处理器的主要规格和性能参数,开发者可以参考这个文档来进行开发和设计。此外,Allwinner Technology还提供了一系列开发板和软件支持,包括SDK、开发工具和驱动程序,为开发者提供了完整的开发环境和支持。这些资源可以帮助开发者更快地进行开发,并且提高系统的性能和稳定性,提高用户的使用体验。 ### 回答2: Allwinner V3s是一款适用于物联网、智能家居和智能穿戴等领域的低功耗系统级芯片,其采用ARM Cortex-A7架构,最高主频可达1.2GHz。V3s还支持1080P高清视频解码,具有较强的图像处理能力。此外,该芯片还集成了DDR3/DDR3L SDRAM控制器、NAND Flash控制器、SPI-NOR Flash控制器、USB OTG控制器、1-Channel MIPI-CSI以及多个I/O接口,能够满足用户在设计中的多种需求。V3s还支持多种操作系统,包括Linux、Android和RTOS等,支持WIFI、蓝牙等无线通信,具有丰富的外设支持和通用GPIO,能够为用户提供灵活的方案。Allwinner V3s的低功耗设计使得其适合应用于电量有限、功耗需求较高的场景,能够提升设备的续航能力。总之,Allwinner V3s是一款高性价比、低功耗、且功能强大的系统级芯片,适用于智能家居和物联网等领域的各种设备。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值