ZYNQ #5 - 从vivado工程开始,从emmc启动Linux

本文详细介绍了如何在Zynq-7000系列上配置从QSPI Flash启动Linux,引导emmc中的image.ub,并解决petalinux在SD0未插卡时从SD1启动的bug。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

本文从最简单的petalinux需求的vivado工程开始,建立一个能跑起来linux的vivado工程。同时将linux kernel、根文件系统部署在接到SD1接口上的emmc中,qspi-flash中放置BOOT.BIN,uboot唤起emmc中的image.ub。并填坑关于petalinux在SD0为空时,配置从SD1启动的bug

目录

1 - VIVADO工程建立

1.1 - PS配置

1.2 - 加个AXI-GPIO

1.3 - 引脚约束,bitstream生成与压缩

1.4 - 生成bitstream,导出hdf

2 - Petalinux工程

2.1 - 配置BOOT.BIN从QSPI FLASH唤起emmc中的image.ub

2.2 - petalinux从跳过空SD0从SD1启动的bug修复

2.3 - 编译,打包

3 - 启动


1 - VIVADO工程建立

这里我们从建立一个petalinux所要求的最小linux系统开始,从这个工程搭建我们后面所需的PL框架。

依照UG1144中介绍,在zynq-7000系列上启动linux所需要的必备器件有以下三个:

  • 三态时钟
  • 外部32MB以上的内存
  • UART串口(用作基本串口登录linux使用)

1.1 - PS配置

新建一个vivado工程,创建框图设计(Block Design),添加ZYNQ7 Processing System

MIO配置,添加QSPI Flash,根据你的板子来设置引脚,注意Bank0和Bank1的电平设置

MIO配置,添加外设,这里添加了一个以太网ENET0,一个USB0,SD0 和SD1分别是连接到SD卡和eMMC,UART1被选中,它将被作为linux系统基本串口登录

Clock配置,修改IO上的外设时钟

DDR配置,修改为PS上接入的内存

1.2 - 加个AXI-GPIO

添加一个AXI GPIO IP核,用来控制板上的4个LED。将其GPIO设置为4bit地址宽度,设置GPIO为外部引脚

点击“Run Connection Automation”和“Run Block Automation”,自动连接部分信号线和自动添加缺少的ip

完成后我们可以点击Diagram框内的Optimiz Routing,优化一下布局

可以看到,整个框图比较简单,PS核DDR和部分FIXED_IO引出,AXI GPIO通过一个AXI桥连入到PS核上的AXI_GP通用总线上

1.3 - 引脚约束,bitstream生成与压缩

创建HDL wrapper

在生成的 design_1_wrapper.v 文件中,我们可以看到我们外连的led引脚(名称会因为你外连后是否修改名称而定)

添加一个xdc约束文件

这里名称我们取“myLinuxBase”,添加完毕后在其内加入下述代码:

set_property PACKAGE_PIN F13 [get_ports led_0_tri_o[0]]
set_property PACKAGE_PIN E13 [get_ports led_0_tri_o[1]]
set_property PACKAGE_PIN G12 [get_ports led_0_tri_o[2]]
set_property PACKAGE_PIN G11 [get_ports led_0_tri_o[3]]

set_property IOSTANDARD LVCMOS18 [get_ports led_0_tri_o[*]]


#bit compress 
set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]

可以看到,前4行代码都是led引脚管脚约束,第6行是约束这4个管脚的电平

后面3行则是对生成的bitstream进行压缩,否则bitstream生成后会有13MB之大。

1.4 - 生成bitstream,导出hdf

生成bitstream,因为之前没有进行综合,这里会提示进行综合,无错误后会成功生成bitstream文件

生成bitstream后,我们导出hdf硬件描述文件 File -> Export -> Export Hardware,一定勾选包括bitstream!!

bitstream是vivado中生成的,导出为hdf文件时需要include bitstream。

hdf实际只是个压缩文件,其中包括硬件信息、bitstream等等,petalinux需要解包hdf然后将其中的bitstream用于后面进行petalinux-package

这样,我们就得到petalinux所需的包含bitstream的hdf文件了,接下来开始petalinux生成

2 - Petalinux工程

petalinux工程的建立、导入hdf就不赘述了。

我们板上现在的情况是,SD0和SD1口都被使用,其中SD0口是SD卡使用,SD1口是接到了板上的eMMC。

eMMC被分区为两个部分,mmcblock1p1是FAT分区,里面存放image.ub,mmcblock1p2是EXT4分区,里面是根文件系统。

eMMC的分区和根文件系统的部署可以用以下的方法:

先使用一个从SD启动的linux,在板上启动SD-Linux后,使用fdisk对emmc进行分区,使用mount进行挂载,挂载EXT4分区后将已经制作好的根文件系统放入eMMC上的EXT4分区

也可以使用uboot对eMMC进行读写,我这里只是取巧而已

我们期望的是板子上电后,从QSPI-FLASH读取BOOT.BIN,执行到uboot后,uboot从eMMC的FAT分区读取image.ub,并将内核释放到内存中运行。

ZYNQ-7000系列只支持SD启动和QSPI启动,不支持直接的从eMMC启动BOOT.BIN,但是UltraScale的支持

参考:

2.1 - 配置BOOT.BIN从QSPI FLASH唤起emmc中的image.ub

主要有以下几点需要配置

  • 配置boot image从primary flash启动
  • 配置kernel镜像从primary sd启动
  • 配置SD/SDIO中,主SD为SD1
  • 配置根文件系统从mmcblk1p2读取(这里我们已经将根文件系统放到了eMMC的p2分区)

这里暂时不做别的配置了,保存退出

2.2 - petalinux从跳过空SD0从SD1启动的bug修复

petalinux2018.3中会有一个这样的bug(实际上之前也存在,官方修复还是有漏洞),当像我们这样SD0接入SD卡,SD1接入eMMC时,当SD卡没有插入时启动,尽管配置petalinux的主sd为ps7_sd_1,但是其uboot启动时会报错找不到mmc 0 

“no mmc device at slot 0”

"card did not respond to voltage select"

这个问题实际上官方之前已经发现,并且在petalinux2017.4之后的版本进行了修复(AR#69780),但是修复并没有完全解决问题。在版本修复之前,问题的来源是在petalinux-config设置主SD为1后,并没有能够成功修改uboot的启动指令,故给出了AR69780中的解决方案,但是解决方案并不完美。

在版本修复之后,我们打开 <plnx-proj-root>/project-spec/meta-plnx-generated/recipes-bsp/u-boot/configs/platform-auto.h 文件,可以看到官方加上了一个sdbootdev变量,并让这个变量表示我们在petalinux-config中标识的主SD编号:

看到光标高亮的cp_kernel2ram变量,其在后面会被执行

"default_bootcmd=run uenvboot; run cp_kernel2ram && bootm ${netstart}\0" \ 
""

/* BOOTCOMMAND */
#define CONFIG_BOOTCOMMAND	"run default_bootcmd"

但是这里,如果当板上使用了两个SD/SDIO,但是用户将SD0作为SD卡使用,SD1作为eMMC使用,则会有一个问题。那就是虽然在petalinux中配置使用eMMC作为主启动SD(也的确修改了sdbootdev变量),但是当SD0,即SD卡槽没有插入SD卡时,uboot在执行mmcinfo时会报错提示mmc0 卡槽未检测成功,导致后面的命令全部终止。

这里介绍简单的解决方法:

在 project-spec/meta-user/recipes-bsp/u-boot/files/platform-top.h 文件的末尾加入下面的代码

/*   fix codes  */
#ifdef CONFIG_BOOTCOMMAND
#undef CONFIG_BOOTCOMMAND
#define CONFIG_BOOTCOMMAND	"mmc dev ${sdbootdev}; run default_bootcmd"
#endif

 

实际上是在执行默认启动环境变量前先将mmc切换到sdbootdev所表示的SD设备(可能是0,也可能是1,这取决于用户在petalinux中设置primary SD是哪一个)

也可以直接看我在xilinx论坛中关于这个问题的解答(https://forums.xilinx.com/t5/Embedded-Linux/BOOting-image-ub-from-eMMC/m-p/979363/highlight/false#M33948

2.3 - 编译,打包

$ petalinux-build
$ petalinux-package --boot --fsbl --fpga --u-boot --force

然后将BOOT.BIN烧录到QSPI-FLASH中,image.ub写入emmc的FAT分区中

还记得我们前面的SD-Linux吗,我们依旧可以用这个作为媒介进行写入

首先擦除QSPI-FLASH:flash_erashall /dev/mtd0

使用 dd 或者 flash_write 指令将 BOOT.BIN 写入flash:dd if=BOOT.BIN of=/dev/mtdblock0

使用mount挂载eMMC的FAT分区:mount /mnt/mmcFat /dev/mmcblk1p1 

直接将image.ub使用cp指令拷贝进 /mnt/mmcFat即可

3 - 启动

上电启动,拨码设置从QSPI启动,我们可以看到下面的uboot输出

U-Boot 2018.01-00083-gd8fc4b3b70 (Jun 01 2019 - 09:37:43 +0000) Xilinx Zynq ZC702

Board: Xilinx Zynq
Silicon: v3.1
DRAM:  ECC disabled 1 GiB
MMC:   Card did not respond to voltage select!
mmc_init: -95, time 24
mmc@e0100000 - probe failed: -95
sdhci_transfer_data: Error detected in status(0x208000)!
Card did not respond to voltage select!
mmc_init: -95, time 25

SF: Detected n25q256 with page size 256 Bytes, erase size 4 KiB, total 32 MiB
*** Warning - bad CRC, using default environment

In:    serial@e0001000
Out:   serial@e0001000
Err:   serial@e0001000
Board: Xilinx Zynq
Silicon: v3.1
Net:   ZYNQ GEM: e000b000, phyaddr ffffffff, interface rgmii-id
eth0: ethernet@e000b000
U-BOOT for osrc_myLinuxBase

ethernet@e000b000 Waiting for PHY auto negotiation to complete...... done
BOOTP broadcast 1
DHCP client bound to address 192.168.2.54 (8 ms)
Hit any key to stop autoboot:  0 
sdhci_transfer_data: Error detected in status(0x208000)!
switch to partitions #0, OK
mmc1(part 0) is current device
Device: mmc@e0101000

可以看到,在最开始,MMC报错还是Card did not respond to voltage select

但是在读秒过后,执行我们修改了的BOOTCOMMAND,在上面的启动代码片段的末尾我们可以看到,mmc切换到了1为主启动mmc,然后升高的从mmc中读取了image.ub,解压了linux到内存,启动了系统

救救穷学生,5毛买个辣条也可

 

<think>好的,我现在需要帮助用户了解如何配置ZynqeMMC启动。根据用户提供的引用内容,特别是引用[3],其中提到了在ZYNQ开发中使用eMMC固化程序的方法,适用于需要高稳定性或量产的设备。我需要结合这些信息,给出一个结构清晰的步骤教程。 首先,我应该明确用户的需求。用户可能是在进行嵌入式系统开发,特别是使用Xilinx的Zynq系列芯片,想要将系统或应用程序固化到eMMC存储中,以便设备能够从eMMC启动。这可能涉及到Uboot的配置、镜像文件的生成以及启动参数的设置。 接下来,我需要回忆Zynq启动流程的基本知识。Zynq启动过程通常分为多个阶段:首先是BootROM,然后是FSBL(First Stage Boot Loader),接着可能由SSBL(如U-Boot)接管,最后加载Linux内核或应用程序。从eMMC启动的话,需要确保启动镜像正确写入eMMC,并且Uboot的环境变量正确指向eMMC中的位置。 根据引用[2],用户提到了修改Uboot启动参数,这可能涉及到设置bootcmd和bootargs,例如指定根文件系统在eMMC中的位置。引用[3]提到了eMMC固化的步骤,可能需要生成BOOT.BIN和镜像文件,并通过工具将其写入eMMC。 现在,我需要将这些信息整理成步骤。首先,生成启动镜像,包括FSBL、比特流和U-Boot。然后,准备根文件系统,可能使用tar解压到某个目录,如引用[2]中的命令。接着,使用dd命令或专用工具将镜像写入eMMC的分区。之后,配置Uboot的环境变量,设置正确的启动命令和参数,确保从eMMC加载内核和根文件系统。最后,测试启动过程。 需要注意的是,用户可能不熟悉如何具体操作这些步骤,比如如何生成BOOT.BIN,如何确定eMMC的设备节点,如何正确分区和格式化eMMC。因此,步骤中需要详细说明这些关键点,可能涉及使用Xilinx的Vivado和Petalinux工具链,以及Linux下的命令如mkfs和dd。 同时,用户提供的引用[1]提到了分区信息,如“Device Boot Start End Blocks Id System”,这可能涉及eMMC的分区布局,需要确保启动分区和根文件系统分区的正确划分。例如,第一个分区可能用于存放BOOT.BIN和镜像,而第二个分区用于根文件系统。 在编写步骤时,要确保逻辑清晰,每个步骤都有明确的目的和操作命令。例如,生成启动镜像可能需要使用Petalinux的构建命令,配置Uboot参数可能涉及修改环境变量或设备树。此外,要提醒用户注意备份数据,因为写入eMMC可能会覆盖原有内容。 可能遇到的问题包括eMMC设备识别不正确、镜像文件路径错误、Uboot参数设置不当等。需要给出一些常见问题的解决方法,或者建议查阅相关文档。 最后,生成相关问题,可能涉及如何验证启动配置、如何优化eMMC的读写速度、在量产中如何批量固化等。</think>### 如何配置ZynqeMMC启动 以下是配置ZynqeMMC启动的详细步骤: --- #### **1. 生成启动镜像(BOOT.BIN)** - **步骤说明**:使用Xilinx工具链(Vivado/PetaLinux)生成包含FSBL(First Stage Boot Loader)、硬件比特流(Bitstream)和U-Boot的镜像文件。 - **操作命令**(PetaLinux环境): ```bash petalinux-package --boot --fsbl <fsbl.elf> --fpga <system.bit> --u-boot --force ``` 生成的`BOOT.BIN`将保存在`images/linux/`目录下[^3]。 --- #### **2. 准备根文件系统(RootFS)** - **步骤说明**:将根文件系统打包为`rootfs.tar.gz`,并通过命令解压到目标目录。 - **操作示例**: ```bash tar -xzvf /xxx/images/linux/rootfs.tar.gz -C /xxx/nfs/rootfs/ [^2] ``` 确保文件系统包含Linux内核(`Image`)和设备树(`system.dtb`)。 --- #### **3. 将镜像写入eMMC** - **分区要求**:通常将eMMC分为两个区: - **分区1(FAT32)**:存放`BOOT.BIN`、`Image`、`system.dtb`。 - **分区2(EXT4)**:存放根文件系统。 - **操作命令**(Linux主机): ```bash sudo dd if=BOOT.BIN of=/dev/mmcblk0p1 # 将BOOT.BIN写入eMMC启动分区 sudo mkfs.ext4 /dev/mmcblk0p2 # 格式化根文件系统分区 sudo cp -r rootfs/* /mnt/mmcblk0p2/ # 复制根文件系统 ``` --- #### **4. 配置U-Boot启动参数** - **关键变量**:在U-Boot中设置`bootcmd`和`bootargs`,指定从eMMC加载内核和根文件系统。 - **示例配置**: ```bash setenv bootcmd &#39;mmc dev 0; fatload mmc 0 0x8000 Image; fatload mmc 0 0x1000 system.dtb; booti 0x8000 - 0x1000&#39; setenv bootargs &#39;root=/dev/mmcblk0p2 rw rootwait earlyprintk&#39; saveenv ``` 其中`mmc dev 0`选择eMMC设备。 --- #### **5. 固化验证** - **操作步骤**:重启Zynq设备,观察U-Boot日志是否从eMMC加载镜像,并确认Linux成功挂载根文件系统。 --- ###
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值