uboot_mt7620对SPI flash操作的分析

本文详细解析了U-Boot环境下通过TFTP方式将系统代码或BootLoader写入SPI Flash的具体流程,包括擦除与写入操作,并展示了不同配置下对Flash分区的处理方法。

接上篇文章,AR9331系统与mt7620系统对flash的划分是不一样的,AR系统划分为Flash(可能是作为NAND来处理),而mt7620(mips)系统则划分的比较明确,用的是SPI_FLASH。

在uboot的启动界面上,可以看到这样一些信息:

Please choose the operation: 
   1: Load system code to SDRAM via TFTP. 
   2: Load system code then write to Flash via TFTP. 
   3: Boot system code via Flash (default).
   4: Entr boot command line interface.
   7: Load Boot Loader code then write to Flash via Serial. 
   9: Load Boot Loader code then write to Flash via TFTP. 

于是,
grep 'write to Flash via TFTP' -r .
找到:
./lib_mips/board.c:	printf("   %d: Load system code then write to Flash via TFTP. \n", SEL_LOAD_LINUX_WRITE_FLASH);
./lib_mips/board.c:	printf("   %d: Load Boot Loader code then write to Flash via TFTP. \n", SEL_LOAD_BOOT_WRITE_FLASH);
./lib_mips/board.c:			printf("   \n%d: System Load Linux Kernel then write to Flash via TFTP. \n", SEL_LOAD_LINUX_WRITE_FLASH);
./lib_mips/board.c:			printf("   \n%d: System Load Boot Loader then write to Flash via TFTP. (.bin)\n", SEL_LOAD_BOOT_WRITE_FLASH);
打开board.c一看究竟。

void OperationSelect(void)
{
	printf("\nPlease choose the operation: \n");
	printf("   %d: Load system code then write to Flash via Serial. \n", SEL_LOAD_LINUX_WRITE_FLASH_BY_SERIAL);
	printf("   %d: Load system code to SDRAM via TFTP. \n", SEL_LOAD_LINUX_SDRAM);
	printf("   %d: Load system code then write to Flash via TFTP. \n", SEL_LOAD_LINUX_WRITE_FLASH);
	printf("   %d: Boot system code via Flash (default).\n", SEL_BOOT_FLASH);
#ifdef RALINK_CMDLINE
	printf("   %d: Entr boot command line interface.\n", SEL_ENTER_CLI);
#endif // RALINK_CMDLINE //

#if defined(ASUS_RTN14U)
	printf("   %d: Load Boot Loader code to SDRAM via Serial. \n", SEL_LOAD_BOOT_SDRAM_VIA_SERIAL);
#endif	
#ifdef RALINK_UPGRADE_BY_SERIAL
	printf("   %d: Load Boot Loader code then write to Flash via Serial. \n", SEL_LOAD_BOOT_WRITE_FLASH_BY_SERIAL);
#endif // RALINK_UPGRADE_BY_SERIAL //

#if defined(ASUS_RTN14U)
	printf("   %d: Load Boot Loader code to SDRAM via TFTP. \n", SEL_LOAD_BOOT_SDRAM);
#endif
	printf("   %d: Load Boot Loader code then write to Flash via TFTP. \n", SEL_LOAD_BOOT_WRITE_FLASH);
}
调用层次为:【./cpu/ralink_soc/start.S: la t9, board_init_r】→【board_init_r】→【OperationSelect】

		case '2':
			printf("   \n%d: System Load Linux Kernel then write to Flash via TFTP. \n", SEL_LOAD_LINUX_WRITE_FLASH);
			printf(" Warning!! Erase Linux in Flash then burn new one. Are you sure?(Y/N)\n");
			confirm = getc();
			if (confirm != 'y' && confirm != 'Y') {
				printf(" Operation terminated\n");
				break;
			}
			tftp_config(SEL_LOAD_LINUX_WRITE_FLASH, argv);
			argc= 3;
			setenv("autostart", "no");
			do_tftpb(cmdtp, 0, argc, argv);

#if defined (CFG_ENV_IS_IN_NAND)
			if (1) {
				unsigned int load_address = simple_strtoul(argv[1], NULL, 16);
				ranand_erase_write((u8 *)load_address, CFG_KERN_ADDR-CFG_FLASH_BASE, NetBootFileXferSize);
			}
#elif defined (CFG_ENV_IS_IN_SPI)
			if (1) {
				unsigned int load_address = simple_strtoul(argv[1], NULL, 16);
				raspi_erase_write((u8 *)load_address, CFG_KERN_ADDR-CFG_FLASH_BASE, NetBootFileXferSize);
			}
#else //CFG_ENV_IS_IN_FLASH
#if (defined (ON_BOARD_8M_FLASH_COMPONENT) || defined (ON_BOARD_16M_FLASH_COMPONENT)) && (defined (RT2880_ASIC_BOARD) || defined (RT2880_FPGA_BOARD) || defined (RT3052_MP1))
			//erase linux
			if (NetBootFileXferSize <= (0x400000 - (CFG_BOOTLOADER_SIZE + CFG_CONFIG_SIZE + CFG_FACTORY_SIZE))) {
				e_end = CFG_KERN_ADDR + NetBootFileXferSize;
				if (0 != get_addr_boundary(&e_end))
					break;
				printf("Erase linux kernel block !!\n");
				printf("From 0x%X To 0x%X\n", CFG_KERN_ADDR, e_end);
				flash_sect_erase(CFG_KERN_ADDR, e_end);
			}
			else if (NetBootFileXferSize <= CFG_KERN_SIZE) {
				e_end = PHYS_FLASH_2 + NetBootFileXferSize - (0x400000 - (CFG_BOOTLOADER_SIZE + CFG_CONFIG_SIZE + CFG_FACTORY_SIZE));
				if (0 != get_addr_boundary(&e_end))
					break;
				printf("Erase linux kernel block !!\n");
				printf("From 0x%X To 0x%X\n", CFG_KERN_ADDR, CFG_FLASH_BASE+0x3FFFFF);
				flash_sect_erase(CFG_KERN_ADDR, CFG_FLASH_BASE+0x3FFFFF);
				printf("Erase linux file system block !!\n");
				printf("From 0x%X To 0x%X\n", PHYS_FLASH_2, e_end);
				flash_sect_erase(PHYS_FLASH_2, e_end);
			}
#else
			if (NetBootFileXferSize <= (bd->bi_flashsize - (CFG_BOOTLOADER_SIZE + CFG_CONFIG_SIZE + CFG_FACTORY_SIZE))) {
				e_end = CFG_KERN_ADDR + NetBootFileXferSize;
				if (0 != get_addr_boundary(&e_end))
					break;
				printf("Erase linux kernel block !!\n");
				printf("From 0x%X To 0x%X\n", CFG_KERN_ADDR, e_end);
				flash_sect_erase(CFG_KERN_ADDR, e_end);
			}
#endif
			else {
				printf("***********************************\n");
				printf("The Linux Image size is too big !! \n");
				printf("***********************************\n");
				break;
			}

			//cp.linux
			argc = 4;
			argv[0]= "cp.linux";
			do_mem_cp(cmdtp, 0, argc, argv);
#endif //CFG_ENV_IS_IN_FLASH

#ifdef DUAL_IMAGE_SUPPORT
			/* Don't do anything to the firmware upgraded in Uboot, since it may be used for testing */
			setenv("Image1Stable", "1");
			saveenv();
#endif

			//bootm bc050000
			argc= 2;
			sprintf(addr_str, "0x%X", CFG_KERN_ADDR);
			argv[1] = &addr_str[0];
			do_bootm(cmdtp, 0, argc, argv);            
			break;

调用的是 raspi_erase_write 方法来对spi flash进行擦除和写入。


<think>嗯,用户想了解U-Boot如何读取MT7688单颗模块的设备ID,以及这个ID存储在哪里。首先,我需要回忆一下MT7688的相关知识。MT7688是联发科的一款SoC,常用于物联网设备,支持OpenWrt等系统。设备ID通常用于识别硬件型号或配置,可能在启动阶段由U-Boot读取。 接下来,设备ID可能存储的位置可能有几种情况。首先,考虑芯片内部的OTP(一次性可编程存储器),很多SoC会用OTP来存储唯一的设备ID。其次,检查是否有EEPROM或SPI Flash,这些外部存储设备可能包含设备信息。另外,MT7688的数据手册可能会有相关寄存器说明,直接读取寄存器地址也是一种可能。 然后,我需要思考U-Boot如何获取这个ID。U-Boot通常通过驱动访问硬件,所以可能需要查看MT7688的U-Boot代码,是否有相关的驱动函数,比如读取OTP或EEPROM的接口。例如,使用命令如otp read或者读取特定内存地址的值。 另外,用户可能需要具体的操作步骤,比如在U-Boot命令行中使用md(内存显示)命令查看某个地址,或者调用某个函数。还要注意不同版本的U-Boot可能有不同的实现方式,可能需要查阅具体版本的代码或文档。 安全方面,直接操作硬件寄存器或存储区域需要谨慎,避免误操作导致系统不稳定。建议用户参考官方文档或联系厂商获取准确信息,因为不同模块的设计可能有所差异。 总结下来,回答需要分步骤说明可能的存储位置,并提供U-Boot中读取的方法示例,同时提醒用户注意事项。确保回答结构清晰,帮助用户逐步解决问题,并建议查阅官方资料确认细节。</think>关于U-Boot读取MT7688设备ID的存储位置和流程,我们可以分以下步骤分析1. **设备ID的硬件存储位置** - **OTP区域**:MT7688芯片内部有一次性可编程存储器(OTP),通常存储厂商预烧录的唯一ID - **SPI Flash特定分区**:模块厂商可能将自定义ID存储在SPI Flash的保留区域,常见偏移地址如: $$0x00030000 \sim 0x0003FFFF$$ 这个区域通常对应"factory"分区 - **EFUSE寄存器**:通过芯片寄存器直接读取,例如: ```c #define EFUSE_BASE 0x10001000 ``` 2. **U-Boot读取方式** - **通过MTD命令访问SPI Flash**: ```bash u-boot> mtd list u-boot> mtd read factory 0x80000000 0x30000 0x100 u-boot> md 0x80000000 ``` - **直接寄存器操作**(需参考芯片手册): ```c uint32_t chip_id = readl(0x1000000C); // CHIP_ID寄存器地址示例 ``` 3. **验证步骤建议** ```mermaid graph TD A[上电启动] --> B[进入U-Boot命令行] B --> C{检测存储介质} C -->|SPI Flash| D[使用mtd命令读取] C -->|OTP/EFUSE| E[寄存器直接读取] D --> F[解析十六进制输出] E --> F F --> G[比对厂商提供格式] ``` 4. **注意事项** - 不同厂商的模块实现可能有差异,需参考具体硬件设计文档 - 直接操作寄存器存在风险,建议先备份环境变量 - OTP区域不可改写,读取时需确认地址准确性 建议通过以下命令组合验证: ```bash u-boot> sf probe 0 u-boot> sf read 80000000 30000 100 u-boot> md 80000000 10 ``` 最终获取的ID通常表现为16字节的十六进制序列,例如: $$A1\ 02\ 34\ 56\ 78\ 9A\ BC\ DE\ F0\ 12\ 34\ 56\ 78\ 9A\ BC\ DE$$ 如需更精确的信息,请提供具体模块型号或参考《MT7688 Hardware Programming Guide》第4.2章。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值