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

2023-11-08

 

本文从最简单的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毛买个辣条也可

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ZYNQ #5 - 从vivado工程开始,从emmc启动Linux 的相关文章

  • bash 或 sh 中的“=”和“==”运算符有什么区别

    我意识到 和 运算符都可以在 if 语句中使用 例如 var some string if var some string then doing something fi if var some string then doing some
  • 如何重命名共享库以避免同名冲突?

    我找到了一个图书馆 libjson http sourceforge net projects libjson 我正在尝试将其构建为共享库并在项目中使用 建造很简单 修复 Makefile 错误后 SHARED 1 make install
  • 模拟用户输入以使用不同参数多次调用脚本

    我必须使用提供的脚本 该脚本在脚本运行时接受用户输入而不是参数 我无法解决这个问题 脚本的一个例子是 bin bash echo param one read one doSomething echo param two read two
  • 从汇编程序获取命令行参数

    通读 专业汇编语言书籍 似乎它提供了用于读取命令行参数的错误代码 我纠正了一点 现在它从段错误变成了读取参数计数 然后是段错误 这是完整的代码 data output1 asciz There are d params n output2
  • C中的内存使用问题

    请帮忙 操作系统 Linux 其中 sleep 1000 中 此时 top 显示Linux任务 给我写了7 7 MEM使用 valgrind 未发现内存泄漏 我明白 写得正确 所有 malloc 结果都是 NULL 但是为什么这次 睡眠 我
  • 将一个文件写入.c中的另一个文件

    我有一个读取文件然后将其内容复制到另一个文件的代码 我需要使其仅复制每 20 个符号 然后跳过 10 个符号 然后再次跳过 20 个符号 依此类推 我必须使用 lseek 函数 但我不知道如何将所有这些放入循环中来执行此操作 main ar
  • 除了 iptables 之外还有数据包管理实用程序吗? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一个 Linux 实用程序 它可以根据一组规则更改网络数据包的有效负载 理想情况下 我会使用
  • 类似 wget 的 BitTorrent 客户端或库? [关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 是否有任何
  • 在 Linux 2.6.21 (glibc 2.3.5) 上进行 ARP 和反向 ARP

    我需要在任意 IP 网络上存储对第三方设备的持久引用 其中设备的 IP 地址可能是静态的或由 DHCP 随机分配 我不控制网络上的设备 也不能依赖 DNS 和其他现有的或与设备一起使用的临时网络协议 所以我被指示使用硬件地址和 ARP 进行
  • 当存在点和下划线时,使用 sed 搜索并替换

    我该如何更换foo with foo sed 只需运行 sed s foo foo g file php 不起作用 逃离 sed s foo foo g file php Example cat test txt foo bar sed s
  • 操作系统崩溃的常见原因[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有兴趣了解 操作系统崩溃 不限于Windows崩溃 最常见的技术原因 从操作系统编程的角度 有哪些 我正在寻找一个不像 打开太多应用
  • 如何使用sprof?

    请举例说明 从邮件中找到here http sources redhat com ml libc alpha 2003 07 msg00029 html and here http sourceware org ml binutils 20
  • 如何使用 tmuxinator 在 tmux 中拆分水平窗格内的两个垂直窗格

    目前我的 tmuxinator yml 文件中有这个 windows editor layout main horizontal panes vim server rails s 这给了我两个窗口 一个用于编辑器 另一个用于服务器 在编辑器
  • 在Linux伪终端中执行从一个终端发送到另一个终端的字符串

    假设我有一个终端 其中 tty 的输出是 dev pts 2 我想从另一个终端向第一个终端发送命令并执行它 使用 echo ls gt dev pts 2 仅在第一个终端中打印 ls 有没有办法执行字符串 不 终端不执行命令 它们只是数据的
  • bash双括号问题

    我对 bash 脚本非常陌生 在使用双括号时遇到了问题 我似乎无法让它们在 Ubuntu Server 11 10 中工作 我的下面的脚本位于 if test sh 中 bin bash if 14 14 then echo FOO fi
  • 从 Linux 命令行发送 SNMP 陷阱消息

    Folks 我需要从 Linux 命令行使用此命令 snmptrap 将自定义消息发送到陷阱侦听器 我需要根据用户设置在 v1 和 v2c 中发送相同的消息 这是我发现的 For v1 snmptrap v 1 c Tas hostname
  • 如何删除树莓派的相机预览

    我在我的 raspberryPi 上安装了 SimpleCv 并安装了用于使用相机板的驱动程序 uv4l 驱动程序 现在我想使用它 当我在 simpleCV shell Camera 0 getImage save foo jpg 上键入时
  • jpackage linux 创建的桌面文件不足

    我刚刚开始使用 jpackage 它是一个非常棒的工具 只要迈出一步 我的肩上的工作就减轻了很多 我对看起来硬编码且无法定制的东西越感到惊讶 JPackage 自动生成启动器 lib
  • 使用 C++ 输出字符串覆盖 Linux 终端上的最后一个字符串

    假设我有一个命令行程序 有没有办法让我说的时候 std cout lt lt stuff 如果我不做std cout lt lt n 在另一个之间std cout lt lt stuff 东西的另一个输出将覆盖同一行上的最后一个东西 清理行
  • 如何使用libaudit?

    我试图了解如何使用 libaudit 我想接收有关使用 C C 的用户操作的事件 我不明白如何设置规则 以及如何获取有关用户操作的信息 例如 我想获取用户创建目录时的信息 int audit fd audit open struct aud

随机推荐

  • 重复代码(克隆代码)的几个概念与类型

    本文内容来源于以下两篇参考文献 1 Chanchal K Roy James R Cordy Rainer Koschke Comparison and Evaluation of Code Clone Detection Techniqu
  • C++中的生命周期

    类A 含构造函数和析构函数 普通函数fun 函数体里新建了类A的局部自动对象FunObj和局部静态对象InStaObj main方法新建了类A的局部自动对象MainObj 调用fun方法 外面新建了A的的外部静态对象ExStaObj和外部对
  • echarts图环形图带百分比

    前言 整理一些echarts中比较有个性的 效果图 实现代码 option tooltip trigger item formatter a br b c d legend orient vertical left 10 data 直达 营
  • 计算机电缆外径相差太大,DJYPVP计算机电缆标准外径

    计算机电缆用途 本产品适用于额定电压30 500v及以下防干扰性能要求较高的电子计算机 检测仪器 仪表的连接 使用条件 计算机电缆 电压等级 0 45 0 75KV 企标 本产品使用于交流额定电压为300 500及以下 对于防干扰性能要求高
  • Could not get a resource from the pool 错误解决

    Could not get a resource from the pool 错误解决 错误信息 Could not get a resource from the pool 可能造成错误原因 1 没关闭Linux防火墙 查看防火墙状态 s
  • 10 个最适合开发人员的 GitHub 代码库 ✅

    在 GitHub 的帮助下 开发人员可以轻松访问并与他人共享他们的代码 它已成为开发人员在项目上进行协作并了解最新开发趋势的重要工具 对于开发人员而言 GitHub 是寻找最佳存储库以帮助他们完成开发项目的宝贵资源 有这么多可用的存储库 可
  • Intellij IDEA 中的 Debug 控制台/ Debug 控制台的 out 窗口不见了

    1 问题 Debug 控制台 Debug 控制台的 out 窗口不见了 2 问题解决方法 显示debug窗口 3 点击后 4 如果要恢复默认窗口布局 重新启动tomcat
  • 基于java车辆监管系统计算机毕业设计源码+系统+lw文档+mysql数据库+调试部署

    基于java车辆监管系统计算机毕业设计源码 系统 lw文档 mysql数据库 调试部署 基于java车辆监管系统计算机毕业设计源码 系统 lw文档 mysql数据库 调试部署 本源码技术栈 项目架构 B S架构 开发语言 Java语言 开发
  • git. 常用操作总结

    TOC GIT指南 在GIT中任何已经提交的东西几乎总是可以恢复的 甚至那些被删除的分支中的提交或使用 amend选项覆盖的提交也可以恢复 然而任何你未提交的东西丢失后很可能再也找不到 git pull会抓取所有的远程引用 Git在进行提交
  • 【通原】采样频率往往高于原信号的2倍的原因

    采样信号不是理想冲激信号 在采样前 需要添加一个抗混叠滤波器以避免频谱混叠 带宽越低越难设计 因此采样频率设计为原信号的3 5倍
  • paddleoc onnx转换推理

    目录 paddle 文字识别验证代码 onnx c 推理 python onnx识别部分推理示例 感谢博客 PaddleOCR转ONNX模型 推理部分 favorxin的博客 CSDN博客 paddleocr转onnx paddle 文字识
  • 2023年场外个股期权研究报告

    第一章 概况 场外个股期权 Over the Counter Equity Option 是指由交易双方根据自己的需求和意愿 通过协商确定行权价格 行权日期等条款的股票期权 与交易所交易的标准化期权不同 场外个股期权的合同内容可以根据交易双
  • .NET MVC标签扩展(checkbox,radio)

    NET MVC里面自动绑定form表单功能 如 Html TextBox Name Html Hidden hide 名称会自动与后台就行绑定ViewBag Name ViewBag hide 很实用 但是感觉不足的就是 Html Chec
  • Redis学习笔记(转尚硅谷周阳)

    教学视频 Redis官网 Redis中文官网 一 NoSQL入门概述 上 1 互联网时代背景下大机遇 为什么用NoSQL 1 1 单机MySQL的美好年代 在90年代 一个网站的访问量一般都不大 用单个数据库完全可以轻松应付 在那个时候 更
  • 整形提升和数据截断

    整形提升和截断 1 整形提升 2 截断 1 整形提升 提升是将占字节小的元素赋给占字节大的元素时出现的补位现象 截断是将所占字节大的元素赋给所占字节小的元素时会出现数值的舍去现象 下面看代码来分析 include
  • html的日期选择插件

    1 效果 2 文档 https layui gitee io v2 docs 3 引入 官网地址 https layui gitee io v2 引入 在官网下载 jquery 1 7 2 min js layui layui js 4 使
  • 绘制坐标轴:Python实现

    绘制坐标轴 Python实现 在数据可视化领域 坐标轴是一种重要的图形元素 用于显示数据的分布和趋势 Python提供了多种库和工具 可以方便地绘制坐标轴和相关图表 本文将介绍如何使用Python实现绘制坐标轴的功能 并提供相应的源代码示例
  • qt5.10 串口通信 QSerialPort 的使用

    在qt5中 使用QSerialPort进行串口通信 主要用到的QSerialPort 使用步骤 步骤一 在 pro文件中进行声明 QT serialport 在 pro文件中添加这个声明 步骤二 实例化 QSrerialPort QSeri
  • 实现itoa()和atoi()

    atoi 将字符串转换为整型值 实现代码 enum Status valid unvalid int status valid 全局变量标记输入是否非法 long long AtoI const char str bool minus lo
  • ZYNQ #5 - 从vivado工程开始,从emmc启动Linux

    本文从最简单的petalinux需求的vivado工程开始 建立一个能跑起来linux的vivado工程 同时将linux kernel 根文件系统部署在接到SD1接口上的emmc中 qspi flash中放置BOOT BIN uboot唤