第8章 zynq uboot更新系统镜像并引导启动和个人心得


文章目录


前言

由于本人较懒,记录主要是过程,由于zynq的比stm32做的人少很多,资料也少很多,我会简要介绍原理,操作流程主要由图片加少量文字组成,每一章都是在之前的章节基础上做的


上一章成功启动了linux系统,这一章在uboot下更新sd卡镜像并启动

一、精简和修改uboot环境变量

默认uboot的启动命令为run $modeboot || run distro_bootcmd,而modebootboard/xilinx/zynq/board.c中的board_late_init会根据启动模式来选择,distro_bootcmd则是在前者启动失败后进行一系列的启动测试,而我们使用的启动模式并非标准,因此将其修改为

之所以选择从sd卡启动而不用nand,是因为nand坏块管理起来比较麻烦,而且sd卡速度更快。修改include/configs/zynq-common.h内的环境变量,添加IP地址和升级命令,删除大部分用不到的环境变量

c 复制代码
#define CONFIG_EXTRA_ENV_SETTINGS	\
	"ethaddr=00:0a:35:00:01:22\0"	\
	"ipaddr=192.168.0.10\0" \
	"serverip=192.168.0.11\0" \
	"kernel_image=uImage\0"	\
	"kernel_load_address=0x2080000\0" \
	"ramdisk_image=rootfs.cpio.uboot\0"	\
	"ramdisk_load_address=0x4000000\0"	\
	"devicetree_image=system-top.dtb\0"	\
	"devicetree_load_address=0x2000000\0"	\
	"bitstream_image=design_1_wrapper.bit\0"	\
	"loadbit_addr=0x100000\0"	\
	"boot_image=BOOT.bin\0"	\
	"bootenv=uEnv.txt\0" \
	"mmc_loadbit=echo Loading bitstream from SD/MMC/eMMC to RAM.. && " \
		"mmcinfo && " \
		"load mmc 0 ${loadbit_addr} ${bitstream_image} && " \
		"fpga loadb 0 ${loadbit_addr} ${filesize}\0" \
	"sdboot=if test -e mmc 0 /design_1_wrapper.bit; then run mmc_loadbit;fi;" \
		"echo Copying Linux from SD to RAM... && " \
		"load mmc 0 ${kernel_load_address} ${kernel_image} && " \
		"load mmc 0 ${devicetree_load_address} ${devicetree_image} && " \
		"load mmc 0 ${ramdisk_load_address} ${ramdisk_image} && " \
		"bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}\0 " \
	"jtagboot=echo TFTPing Linux to RAM... && " \
		"tftpboot ${kernel_load_address} ${kernel_image} && " \
		"tftpboot ${devicetree_load_address} ${devicetree_image} && " \
		"tftpboot ${ramdisk_load_address} ${ramdisk_image} && " \
		"bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}\0" \
	"up_bin=tftpboot 80000 ${boot_image} &&  nand erase 0 ${filesize} && nand write 80000 0 ${filesize} \0" \
	"up_kernel=tftpboot ${kernel_load_address} ${kernel_image} && " \
		"fatwrite mmc 0:1 ${kernel_load_address} ${kernel_image} ${filesize} \0" \
	"up_tree=tftpboot ${devicetree_load_address} ${devicetree_image} && " \
		"fatwrite mmc 0:1 ${devicetree_load_address} ${devicetree_image} ${filesize}  \0" \
	"up_rootfs=tftpboot ${ramdisk_load_address} ${ramdisk_image} && " \
		"fatwrite mmc 0:1 ${ramdisk_load_address} ${ramdisk_image} ${filesize} \0" \
	"up_fpga=tftpboot ${loadbit_addr} ${bitstream_image} && " \
		"fatwrite mmc 0:1 ${loadbit_addr} ${bitstream_image} ${filesize} \0" \
	"up_all_boot=run up_kernel && run up_tree && run up_rootfs && " \
		"run sdboot \0"

修改完重新生成uboot和BOOT.bin,烧录重启后发现环境变量没有变化,这是因为之前执行了saveenv保存了旧的环境变量,每次启动都会默认加载,此时输入env default -a便会使用uboot内的环境变量,再执行saveenv保存

删除后的环境变量仅2153bytes

二、更新系统镜像

输入run up_all_boot即可更新系统镜像,烧录完会从sd上启动

之后每次重启都会自动从sd卡加载系统镜像启动,需要更新系统镜像时只需执行对应的run up_*即可

三、关于uboot的简单个人心得

芯片启动开始时,芯片会根据内部ROM代码,对时钟和存储器初始化,根据启动引脚选择启动方式从相应的器件启动,大部分由于内部内存小无法正常运行uboot,在uboot之前还有一级启动程序(像spl或fsbl)来对DDR初始化和管理,等到了uboot时几乎可以操作所有的硬件来完成简单的程序,类似于裸机开发

很多硬件如果只需要做一次初始化就可以在uboot下通过指令脚本来实现。像I2C、SPI等这些外设的读写测试都很适合在uboot下完成,很多裸机程序修改为uboot程序较linux简单许多

在uboot引导系统时也有很多操作可以秀,像多系统、系统冗余,除了Linux,也可以引导其他系统像vx,或者直接运行裸机程序

四、常见的启动失败的原因分析

1、开机没有任何反应

在硬件没有问题时,首先要考虑ddr和串口配置有问题,建议先运行裸机测试程序测试,再打开调试信息查看,分析卡在哪一步

2、uboot卡在某一行

通过复制打印信息在源码里查找,一步一步很容易查到卡在哪,因为uboot的流程较短,熟悉后很容易查到问题处,这也是我喜欢用uboot而不是uefi的原因,解决问题很有成就感,然而对项目来说好像这并不重要。这也是软件开发很悲哀的一个点,大量的重复性没有成就感的项目很容易消磨一个人的好奇心导致技术停滞不前,然后陷入担忧中年危机的死循环之中。还是要钻研的深一点才好打动技术面试人的心


总结

主要介绍了zynq uboot更新系统镜像并引导启动和个人心得

参考

相关推荐
TE-茶叶蛋13 小时前
Spec-Driven Development(规范驱动开发)
驱动开发
仲南音14 小时前
Xilinx FPGA——时钟IP核MMCM、PLL
fpga开发
I'm a winner1 天前
基于Xilinx FPGA的LVDS高速串行通信系统(三)--数据训练及握手机制【文末源码】
fpga开发
upper20201 天前
coremark移植坑之-nostartfiles -nostdlib参数
学习·fpga开发·coremark移植·riscv设计
云栖梦泽1 天前
Camera驱动开发与应用开发中的零拷贝与DMA
linux·驱动开发·嵌入式硬件
Eloudy2 天前
Vivado 纯命令行构建 FPGA 项目教程
fpga开发
Rambo.xia2 天前
AXI跨时钟域与数据一致性——CDC FIFO深度不够、写后读冒险、多Master仲裁、乱序返回,出了Bug根本查不出来
fpga开发·bug
upper20202 天前
FPGA部署卷积神经网络识别MINST图片
fpga开发·卷积神经网络·minst·minst识别·部署神经网络·神经网络识别图片
脱胎换骨-军哥2 天前
C++ 嵌入式编程实例:从寄存器操作到底层驱动开发
开发语言·c++·驱动开发
智者知已应修善业2 天前
【使用D触发器74HC175实现0001 0011 0111 1111 1110 1100 1000的循环彩灯电路。】2025-4-28
驱动开发·经验分享·笔记·硬件架构·硬件工程