ZYNQ嵌入式Linux学习——linux启动文件制作
ZYNQ嵌入式Linux学习——linux启动文件制作
一、基础知识
在zynq上成功运行linux需要制作的启动文件包括:U-Boot
,linux内核
,设备树
,根文件系统
。接下来对这四者进行简单介绍,以明白其在linux系统中的作用。
本文使用的ZYNQ型号是Zynq-7000系列的xc7z100ffg900,使用的vivado版本是2021.2
需要安装的软件:
- Vivado 2021.2
- Vitis 2021.2
- VMware
1. U-Boot
对于计算机系统而言,从开机上电到操作系统启动需要一个引导过程,这个引导过程由引导程序指定。 引导程序是系统上电启动运行的第一段软件代码。引导程序的主要运行任务就是将内核映像从硬盘读到 RAM 中,然后跳转到内核的入口点去运行,即开始启动操作系统。 嵌入式 Linux 系统同样离不开引导程序,这个引导程序一般我们叫作启动加载程序( Bootloader)。
Bootloader 是在操作系统运行之前执行的一段小程序。通过这段小程序,可以初始化硬件设备、建立内存空间的映射表,从而建立适当的系统软硬件环境,为最终调用操作系统内核做好准备。也就是说芯片上电以后先运行一段 bootloader 程序。这段 bootloader 程序会先初始化 DDR 等外设,然后将 Linux 内核从 flash(NAND, NOR FLASH, SD, MMC 等)拷贝到 DDR中,最后启动 Linux 内核。当然了, bootloader 的实际工作要复杂的多,但是它最主要的工作就是启动 Linux 内核。
Zynq-7000 嵌入式软件栈如下图:
U-Boot,通用引导加载程序的缩写,是一种开源的主引导加载程序,用于嵌入式设备,以引导 Linux 社区中经常使用的设备操作系统内核。 Xilinx 在 Zynq-7000 设备中使用 U-Boot 作为第二阶段引导加载程序。
Zynq-7000 的第一阶段引导加载程序( FSBL)使用硬件比特流(如果存在)配置 FPGA,并 将 操 作 系 统 ( OS ) 映 像 或 第 二 阶 段 引 导 加 载 器 映 像 从 非 易 失 性 存 储 器( NAND/SD/eMC/QSPI)加载到存储器( DDR/OCM)。
2. linux内核
从技术层面讲,内核是硬件与软件之间的一个中间层。作用是将应用层序的请求传递给硬件,并充当底层驱动程序,对系统中的各种设备和组件进行寻址。
从应用程序的层面讲,应用程序与硬件没有联系,只与内核有联系,内核是应用程序知道的层次中的最底层。在实际工作中内核抽象了相关细节。
内核是一个资源管理程序。负责将可用的共享资源(CPU时间、磁盘空间、网络连接等)分配得到各个系统进程。
内核就像一个库,提供了一组面向系统的命令。系统调用对于应用程序来说,就像调用普通函数一样。
3. 设备树
设备树的概念从Linux内核V2.6版本开始引入, 用于描述一个硬件平台的硬件资源信息,这些信息包括:CPU的数量和类别、内存基地址和大小、总线和桥、外设连接、中断控制器和中断使用情况、GPIO控制器和GPIO使用情况、Clock控制器和Clock使用情况等等。
设备树的特点:
- 实现驱动代码与设备硬件信息相分离。
- 通过被
bootloader(uboot)
和Linux
传递到内核, 内核可以从设备树中获取对应的硬件信息。 - 对于同一SOC的不同主板,只需更换设备树文件即可实现不同主板的无差异支持,而无需更换内核文件,实现了内核和不同板级硬件数据的拆分。
整个设备树包含DTC(device tree compiler)
,DTS(device tree source)
和DTB(device tree blob)
。
- DTS(device tree source)
DTS
是一种ASCII
文本格式的设备树描述,在ARM Linux
中,一个dts
文件对应一个ARM
的设备
Dtsi:由于一个SoC
可能对应多个设备(一个SoC可以对应多个产品和电路板),这些.dts文件势必须包含许多共同的部分,Linux内核为了简化,把SoC公用的部分或者多个设备共同的部分一般提炼为.dtsi,类似于C语言的头文件。其他的设备对应的.dts就包括这个.dtsi
- DTC(device tree compiler)
DTC
是将.dts
编译为.dtb
的工具,相当于gcc。该工具一般在编译内核的时候,默认会自动执行编译操作。
- DTB(device tree blob)
dtb文件是.dts 被 DTC 编译后的二进制格式的设备树文件,它由Linux内核解析,也可以被bootloader进行解析。
4. 根文件系统
根文件系统首先是内核启动时所mount的第一个文件系统,内核代码映像文件保存在根文件系统中,而系统引导启动程序会在根文件系统挂载之后从中把一些基本的初始化脚本和服务等加载到内存中去运行。
根文件系统首先是一种文件系统,该文件系统不仅具有普通文件系统的存储数据文件的功能,但相对于普通的文件系统,它是内核启动时挂载(mount)的第一个文件系统,内核代码的映像文件保存在根文件系统中,系统引导启动程序会在根文件系统挂载之后从中把一些初始化脚本(如rcS,inittab)和服务加载到内存中去运行。 文件系统和内核是完全独立的两个部分。在嵌入式中移植的内核下载到开发板上,是没有办法真正的启动Linux操作系统的,会出现无法加载文件系统的错误。
二、Petalinux制作启动文件
由第一章可知,需要制作的启动文件包括U-Boot
,linux内核
,设备树
,根文件系统
。本章使用petalinux制作的文件包括:
- BOOT.BIN
包含了fsbl文件、bitstream文件、U-Boot文件
- image.ub
linux内核文件,其中包含了linux内核和设备树
- boot.scr
其核心作用是为U-Boot提供自动执行的命令序列,从而完成从硬件初始化到Linux内核加载的完整启动流程
- rootfs.tar.gz
根文件系统的压缩包,解压就可以得到根文件系统
1. Petalinux简介
Petalinux 工具是 Xilinx 公司推出的嵌入式 Linux 开发套件,包括了 u-boot、 Linux Kernel、device-tree、 rootfs 等源码和库,以及 Yocto recipes,可以让客户很方便的生成、配置、编译及自定义 Linux 系统。 Petalinux 支持 Versal 、 Zynq UltraScale+ MPSoC、 Zynq-7000 SoC 以及MicroBlaze,可与 Xilinx 硬件设计工具 Vivado 协同工作,大大简化了 Linux 系统的开发工作。具体的介绍可访问 Petalinux 工具网站: https://china.xilinx.com/products/design-tools/embeddedsoftware/petalinux-sdk.html
2. Ubuntu安装
2.1 Ubuntu镜像下载
- 本篇使用VMware运行Ubuntu。需要注意的是Petalinux对Ubuntu版本有要求,详情可见https://docs.amd.com/r/2021.2-English/ug1144-petalinux-tools-reference-guide/Installation-Requirements
根据需要安装的Petalinux版本找到对应的Ubuntu版本要求即可。本篇使用Vivado2021.2和Petalinux2021.2(Vivado版本和Petalinux版本要保持一致),选择的Ubuntu版本是20.04.1,在Ubuntu官网下载历史版本https://old-releases.ubuntu.com/releases/20.04.1/
往下翻找到Ubuntu 20.04.1的ISO文件,点击下载
2.2 创建虚拟机
- 选择自定义
- 镜像选择刚刚下载的20.04.1
- 把磁盘大小设置为80GB,默认的20GB是不够的
没提到的默认下一步就可以了。
注意:千万不要点系统内提示的任何一个更新提示,否则会给更新到20.04.6
可以使用
1
lsb_release -a
命令查看当前发行版本
2.3 更新apt软件包
后续需要使用apt下载一些软件包,一般来说安装完Ubuntu系统后需要更新一下apt软件包。
1 |
|
等待更新完毕
3. Petalinux安装
3.1 下载安装包
下载需要注册账号、填写信息。需要注意的是国内的账号会出现无法下载的情况。建议科学上网另辟蹊径或者直接找现成的(
3.2 安装依赖库以及软件
在桌面上右键打开终端
一般情况下是可以使用ctrl+shift+v直接复制进终端的,如果不能复制可以尝试安装下面两个包
1 |
|
使用下面的命令安装依赖
1 |
|
3.3 修改bash
Petalinux 工具需要主机系统的/bin/sh 是 bash,而 Ubuntu 默认的/bin/sh 是 dash,所以这里需要进行更改。
在终端里运行
1 |
|
- 选择**<否>**然后按回车
3.4 安装Petalinux
把下载的petalinux安装包拖入任意一个文件夹内(可以直接从主机拖进虚拟机)
在这个文件夹下打开终端
运行下面的代码,创建文件夹,并且把/opt目录的属主和属组更改为当前用户名
1 |
|
把Petalinux安装到刚刚创建的文件夹中
1 |
|
然后会有读软件许可协议的提示,回车,然后按Q退出
然后输入y同意协议
同意所有的用户许可协议,等待下载完成
下载完成后,可以在下载目录中看到下载的文件
3.5 设置Petalinux环境变量
在正式使用 petalinux 工具之前,需要先运行 petalinux 安装目录下的 settings.sh 脚本文件设置 petalinux 工作环境, settings.sh 脚本用于 bash,还有一个 settings.csh 用于 C shell。一般默认情况下,我们使用 bash 作为登录 shell,所以 source 脚本文件 settings.sh 对petalinux 所需的运行环境进行配置,命令如下:
1 |
|
需要注意的是该命令只对当前终端有效,重新打开终端后需要重新执行这一步。执行结果如下图所示:
我们来验证下工作环境是否已设置,在终端输入如下命令:
1 |
|
打印出了Petalinux的安装路径,表示环境变量设置成功。
鉴于每次打开终端使用 Petalinux 都需要设置相应的环境变量,我们为了方便,将设置Petalinux 环境变量的命令设置成别名,这样我们使用起来就方便些。设置别名方法的很简单,在终端输入如下命令:
1 |
|
设置完成后,每次打开新的终端,只需要输入
1 |
|
就可以设置环境变量。sptl的意思是source petalinux
4. 创建vivado硬件工程
本章将创建一个制作启动文件需要的ZYNQ硬件平台,包括配置PS端外设,添加PL端IP核等。linux操作系统通过内核与硬件底层沟通,所以通过vivado设计的底层硬件决定了我们制作的linux系统具有哪些功能。
本次计划实现的功能包括:
实现linux的基本功能,能够串口打印信息
实现以zynq为时钟源1s闪烁一次的PL端的LED灯
实现可以在linux系统内使用指令控制开关的PL端LED灯
4.1 PS端配置
- 打开vivado并新建工程
- 选择项目位置
- 选择RTL Project
- 搜索你的zynq芯片型号
- 点击Create Block Design
- 点击“+”添加IP核
- 搜索
ZYNQ7 Processing System
,双击添加IP核。这个IP核就是PS端的处理器。
双击ZYNQ7 Processing System
IP核进入PS配置界面
需要配置的外设包括:
- UART 0:用于linux打印系统信息
根据原理图来选择引脚:
在PS-PL Configuration中的General里可以修改UART0的波特率。一般保持默认的115200就好。
- SD 0:zynq通过SD卡启动系统,所以需要配置SD卡
根据原理图来选择引脚:
- ENET 0:以太网配置,调试ZYNQ经常要用到ssh远程连接,以远程连接zynq,并且还能远程传输文件。
同样的,根据原理图选择引脚。
- GPIO:使能所有PS端的GPIO,同时打开以太网的Reset
- QUAD SPI:ZYNQ选择启动方式需要使能QSPI引脚
BANK 1的I/O电平改成LVCMOS 1.8V
配置完外设后,配置PS端的时钟。这里一般使用100MHz
最后是最重要的DDR配置,如果DDR型号选错了的话是无法启动Linux系统的。系统最先执行的步骤是把U-BOOT拷贝到DDR上,基本上所有程序都运行在DDR上。一定要按照原理图来正确配置DDR型号
4.2 Block Design设计
- 右键
FCLK_CLK0
和FCLK_RESET0_N
,选择Make External
FCLK_CLK0
是PS内部时钟子系统(由PS-PLL生成)输出的时钟。我们把这根线拉出来,当做时钟源给PL端的LED,以实现闪烁的功能。
FCLK_RESET0_N
是PS通过其内部时钟子系统生成的复位信号,与FCLK_CLK0
(时钟信号)同步。它提供了一种受控的、同步的复位机制,确保PL侧逻辑与PS的时钟域同步复位。我们把这根线拉出来给PL端的LED用做复位信号。
- 点击左边的M_AXI_GP0_ACLK,把它与FCLK_CLK0连接到一起
M_AXI_GP0_ACLK
是PS主通用端口Master AXI GP0
的时钟输入,用于同步PS通过AXI接口与PL或外部设备的通信。
- 添加IP核
Processor System Reset
Processor System Reset(PSR)
IP核是一个专门用于生成和管理复位信号的模块,其核心作用是为系统提供可靠、同步的复位逻辑,尤其适用于处理多时钟域、异步复位同步释放等复杂场景。
- 添加IP核
AXI GPIO
AXI GPIO(AXI General-Purpose Input/Output)
是Xilinx提供的一个基于AXI4-Lite接口的通用输入/输出IP核,主要用于通过AXI总线控制或读取外部GPIO信号。它适用于Zynq SoC或FPGA设计,允许PS(处理器系统)通过AXI接口与PL(可编程逻辑)中的GPIO交互,或者直接连接外部设备(如LED、按键、传感器等)。
双击IP核AXI GPIO
配置IP核,把GPIO Width改成1
- 点击Run Connection Automation
- 点击Run Block Automation
- 最后的Block Design如下图所示:
做完所有配置后,右键design_1 Generate Output Products
生成完成后,再右键design_1,选择Create HDL Wrapper,为Block Design创建一个硬件描述文件
创建完成后是这样的:
这样就可以把我们创建的Block Design当成一个模块写verilog代码了。
4.3 PL端verilog代码设计
本章将把章节4.2中设计的Block Design当成模块,提供时钟源和复位信号
- 创建新的硬件描述文件
然后双击刚刚创建的文件,编写led.v
- 编写闪烁LED灯代码:
1 |
|
编写保存后,Sources中的文件如图所示
led被自动设置成了top文件。如果led.v没有设置成top文件就右键led.v然后Set as Top
- 添加约束文件
点击加号添加文件
创建约束文件
双击led.xdc编写约束文件
随便在原理图上找一个PL端的LED引脚:
我们这次要点亮两个LED,一个是1s闪烁一次的LED灯,另一个是可以通过linux命令控制开关的LED灯
我这里选择T_LED2对应的引脚W29和T_LED3对应的引脚T29
- 编写led.xdc:
1 |
|
点击左侧的Open Elaborated Design
点击Schematic可以看见我们编写的模块的RTL电路
PS端为整个电路提供了时钟和复位,并且提供了一个GPIO输出
然后点击Generate Bitstream就可以生成bit流文件了(你也可以按部就班地Run Synthesis然后Run Implementation,最后再生成比特流,但我习惯直接点生成比特流,其实一样的)
生成完成:
- 导出硬件文件
linux启动文件的制作需要依赖于vivado的硬件,我们在这里导出一个xsa文件,这个xsa文件包含了所有这个工程的硬件信息。
然后一路Next就可以了
项目文件目录下面生成了项目的xsa文件
5. 使用Petalinux定制Linux系统
Petalinux一般的设计流程如下。需要说明的是,不是每一步都需要执行一遍,可以根据使用场景有选择的执行。
通过 Vivado 创建硬件平台,得到 xsa 文件
运行 source <petalinux 安装路径>/settings.sh,设置 Petalinux 运行环境
通过 petalinux-create -t project 创建 petalinux 工程
使用 petalinux-config –get-hw-description, 将 xsa 文件导入到 petalinux 工程当中并配置petalinux 工程
使用 petalinux-config -c kernel 配置 Linux 内核
使用 petalinux-config -c rootfs 配置 Linux 根文件系统
配置设备树文件
使用 petalinux-build 编译整个工程
使用 petalinux-package –boot 制作 BOOT.BIN 启动文件
制作 SD 启动卡,将 BOOT.BIN 和 image.ub 以及根文件系统部署到 SD 卡中
将 SD 卡插入开发板,并将开发板启动模式设置为从 SD 卡启动
开发板连接串口线并上电启动,串口上位机打印启动信息, 登录进入 Linux 系统
5.1 创建Petalinux工程
- 设置Petalinux环境变量
我们在安装Petalinux的时候就介绍过这个步骤
1 |
|
- 创建一个用于放工程的文件夹,并在文件夹内打开终端
- 创建petalinux工程
现在我们在该目录中创建一个名为“ ZYNQ_BASE”的Petalinux工程,在终端中输入如下命令
1 |
|
-t 是“ –type”的简写。 template 参数表明创建的 petalinux 工程使用的平台模板,此处的zynq 表明使用的是 zynq 平台模板的 petalinux 工程,用于 zynq-7000 系列的芯片。 name 参数(此处简写为“ -n”)后接的是 petalinux 工程名
5.2 配置Petalinux工程
- 把之前生成的led.xsa拖进文件夹里
首次配置Petalinux工程是将xsa文件导入到Petalinux工程中,Petalinux工具会解析xsa文件并弹出配置窗口。在终端中输入如下命令配置Petalinux工程
1 |
|
如果xsa文件有更改,只需要执行petalinux-config --get-hw-description ../led.xsa
命令重新加载文件
执行成功后,会弹出配置窗口
这个窗口不能通过鼠标操作,只能通过键盘操作。
通过键盘上的“↑”和“↓”键来选择要配置的菜单
按下“ Enter”键进入子菜单。菜单中蓝色高亮的首字母就是此菜单的热键,在键盘上按下此高亮字母对应的键可以快速选中对应的菜单。
选中子菜单以后按下“ Y”键就会将相应的配置选项写入配置文件中,菜单前面变为“ < * >”。
按下“ N”键不编译相应的代码。
按下“ M”键就会将相应的代码编译为模块,菜单前面变为“ < M >”。
按两下“ Esc”键退出,也就是返回到上一级,按下“ ?”键查看此菜单的帮助信息,按下“ /”键打开搜索框,可以在搜索框输入要搜索的内容。
在配置界面下方会有五个按钮,这五个按钮的功能如下:
Select:选中按钮,和“ Enter”键的功能相同,负责选中并进入某个菜单。
Exit:退出按钮,和按两下“ Esc”键功能相同,退出当前菜单,返回到上一级。
Help:帮助按钮,查看选中菜单的帮助信息。
Save:保存按钮,保存修改后的配置文件。
Load:加载按钮,加载指定的配置文件。
本次不需要对工程配置进行修改,按键盘上的”→”键,选择Save,按回车
选择配置文件(config)的存放位置
最后按两次键盘上的“ Esc”退出配置窗口,Petalinux工具开始自动配置工程。
如果后面想重新配置,只需输入petalinux-config
命令即可重新配置。
5.3 配置Linux内核
输入下面的命令配置内核:
1 |
|
配置页面:
也没有什么需要修改的,同样Save之后再退出就可以了
结算界面
5.4 配置Linux根文件系统
在终端输入下面的命令可配置根文件系统
1 |
|
默认配置可满足一般使用,也可以根据需求来定制根文件系统,这里保持默认配置。需要说明的是“ PetaLinux RootFS Settings”可以用来设置root用户的密码,默认为“root”。后面登录的时候会用到。
保存配置并退出。
5.5 编译Petalinux工程
输入下面的命令编译Petalinux工程
1 |
|
编译完成结算画面:
编译生成的镜像文件在项目目录下的images文件夹里
5.6 制作BOOT.BIN启动文件
Petalinux提供了petalinux-package命令将PetaLinux项目打包为适合部署的格式,其中“petalinux-package –boot”命令生成可引导映像,该映像可直接与Zynq系列设备(包括Zynq-7000和Zynq UltraScale + MPSoC)或基于MicroBlaze的FPGA设计一起使用。对于Zynq系列设备,可引导格式为 BOOT.BIN,可以从SD卡引导启动。
ZYNQ的启动文件BOOT.BIN一般包含fsbl
文件、bitstream
文件和uboot
文件。使用下面的命令可生成BOOT.BIN文件
1 |
|
选项“–fsbl”用于指定fsbl文件所在位置,后面接文件对应的路径信息,如果不指定文件位置,默认对应的是images/linux/zynq_fsbl.elf
选项“–fpga”用于指定bitstream文件所在位置,后面接该文件对应的路径信息,默认对应的是 images/linux/system.bit,实际可能有区别
选项“–u-boot”用于指定U-Boot文件所在位置,后面接该文件所在路径信息,默认为images/linux/u-boot.elf
执行结果如下图所示:
我们需要的文件是下面几个
5.7 制作SD启动卡
如果使用SD卡引导linux系统启动,一般需要在SD卡上有2个分区。一个分区使用FAT32文件系统,用于放置启动镜像文件(如BOOT.BIN,boot.scr文件和linux镜像文件等),另一分区使用EXT4文件系统,用于存放根文件系统(rootfs)
在将SD卡插入电脑之前,先配置虚拟机支持USB 3.0
左上角点虚拟机,进入设置
点击USB控制器,USB兼容性选择USB 3.1
插入USB之后,一般Ubuntu系统会自动识别U盘。如果没有,可以看右下角,右键箭头所指的图标
使用df -h
命令查看当前系统挂载的硬盘设备
U盘一般挂载在/media下面,我这里是已经分过区的SD卡,所以我会先删除所有分区,再进行分区操作,以演示整个SD卡制作流程。
可以看到红框里,我的SD卡的设备节点是/dev/sdc(节点不一定是/dev/sdc,要具体检查自己的SD卡节点的名字),执行下面的操作:
1 |
|
再输入”p”查看分区
可以看到这个SD有两个分区,键入”d”,再键入1删除分区1,再次键入d删除第二个分区。如果只有1个分区的话只需要输入一次d就可以了。
当输入d弹出“还没有定义分区!”时,表明已经没有分区。
接下来新建分区。首先键入”n”创建一个分区,再输入”p”使其为主分区。使用默认分区号1和第一个扇区2048。设置最后一个扇区,也就是设置第一个分区的大小,一般设置500M足够了,通过输入“+500M”,为该分区预留500MB,如果提示分区包含vfat签名并询问是否移除该签名,则输入“y”。
然后设置分区类型,输入”t”,再输入”c”,设置为”W95 FAT32(LBA)”,再输入”a”设置为引导分区
第一个分区就创建完成了,接下来创建第二个分区
键入”n”新建分区,后面一路默认就可以了
此时再输入”p”可以看到创建的两个分区,最后输入”w”保存到SD卡
创建完分区之后,就可以格式化分区了
1 |
|
此时再重新插拔SD卡就可以看到我们刚刚制作的SD卡了
然后我们把之前制作的启动文件放到boot分区里,包括BOOT.BIN、boot.scr、image.ub
然后我们需要把根文件系统解压到rootfs分区里
在生成rootfs.tar.gz的文件夹内打开终端,输入命令(-C后面的路径需要根据实际情况来)
1 |
|
5.8 启动开发板
- 根据原理图,将ZYNQ的启动模式设置为SD卡启动
- 打开串口上位机,进入Linux系统
上电一开始,按回车可以进入boot界面(如果超过2秒不进行操作boot会自行往下进行)
此时boot已经启动成功,bitstream也应该成功下载到板子上,此时能看见其中一个LED灯在闪烁。
在命令里输入boot,启动内核
此时,linux系统已启动成功。接下来尝试用命令行点亮第二个led
首先,进入/sys/class/gpio,查看这个目录下的内容
1 |
|
关注其中gpiochip1023,这意味着GPIO编号从1023开始
输入下面的命令创建GPIO并设置为输出模式
1 |
|
然后使用下面的命令就可以控制led灯的开关了
1 |
|
至此,使用Petalinux定制Linux系统已经走完全部流程,并且实现了当初设想的功能,控制了两个LED
三、源码编译启动文件并移植
上一章介绍了使用Petalinux制作启动文件,Petalinux虽然比较方便,将所有操作都集成到一起,但是Petalinux很占空间(40GB都不够),而且每次编译都比较慢,所以我们这里将尝试使用Xilinx官方提供的源码自己编译,速度会更快,也更加灵活。但是这种方式初次上手的时候可能会理不清关系,我在这里做一个关系梳理,展示所有需要的文件的合成路径:
可以参考上面的流程图,跟着下面的步骤,理清制作流程
- 使用vivado工程生成的xsa文件在vitis里创建设备树工程,编译生成
system-top.dts
- 把
system-top.dts
添加到u-boot源码目录里,使用交叉编译工具链编译u-boot源码,得到u-boot.elf
,system-top.dts
也被编译成我们最终需要的设备树文件system-top.dtb
- 使用xsa文件在vitis内创建fsbl工程,编译后产生文件
fsbl.elf
和bit文件
- 在vitis内把
fsbl.elf
,bit文件
,u-boot.elf
三个文件合成为引导文件BOOT.bin
- 把
system-top.dts
添加到内核源码目录里,使用交叉编译工具链编译内核源码,得到我们最终需要的内核文件zImage
1. 构建交叉编译工具链
交叉编译是编译技术发展过程中的一个重要分支。通俗的说,交叉编译就是在一个平台上生成另一个平台上的可执行代码。这里提到的平台有两方面的含义:处理器的体系结构和所运行的操作系统。
通常,程序是在一台计算机上编译,然后再分布到将要使用的其它计算机上。当主机系统(运行编译器的系统)和目标系统(产生的程序将在其上运行的系统)不兼容时,该过程就叫做交叉编译。嵌入式系统应用的日益广泛和需求推动了交叉编译技术的发展。非X86的嵌入式系统开发,一般都是基于X86的PC平台进行,这种开发方式就是交叉编译。嵌入式系统中的应用程序都是通过交叉编译得到的。
Petalinux在构建linux系统的过程中会编译生成Linux的交叉编译工具链,然后使用工具链构建linux系统。不过这种交叉编译工具链可能不方便实用,我们的目的是得到实用的linux编译工具链,这样就可以摆脱Petalinux编译linux系统了。
获取linux交叉编译工具链需要用Petalinux构建 SDK,然后安装SDK。所谓的SDK,也就是软件开发工具集,与Petalinux构建的根文件系统息息相关,里面不仅包含有Petalinux构建的根文件系统、各种库和头文件,还包含linux交叉编译工具链,用来编译linux内核及linux应用以使其能在ZYNQ开发板上运行。
1.1 定制根文件系统rootfs
前面介绍了SDK与Petalinux构建的根文件系统息息相关,这是因为SDK中包含了根文件系统,而根文件系统中又包含了我们添加的各种各样的软件库,特别是链接库,我们在电脑主机中开发编译Qt或OpenCV时就需要这些链接库。下面我们定制本章的根文件系统
在上个章节创建的petalinux的工程目录下
配置petalinux环境变量
1 |
|
配置工程
1 |
|
配置”Image Packaging Configuration —> Root filesystem type”类型为”EXT4“,将根文件系统放到SD卡第二个分区
保存设置并退出
输入如下命令配置根文件系统
1 |
|
- 1.1 添加OpenCV
退到最开始的界面
Petalinux Package Groups —>
packagegroup-petalinux-opencv —>
packagegroup-petalinux-opencv(Y)
- 添加Python
Petalinux Package Groups —>
packagegroup-petalinux-python-modules —>
packagegroup-petalinux-python-modules(Y)
- 添加gcc编译工具链(可选)
Petalinux Package Groups —>
packagegroup-petalinux-self-hosted —>
packagegroup-petalinux-self-hosted(Y)
- 添加网络工具(可选)
Petalinux Package Groups —>
packagegroup-petalinux-networking-stack —>
packagegroup-petalinux-networking-stack(Y)
1.2 编译根文件系统并构建SDK
使用如下命令编译刚才定制的根文件系统:(下面两个命令会超级慢,而且真的很占磁盘空间)
1 |
|
生成的根文件在images/linux/目录下。接下来构建SDK,输入命令:
1 |
|
完成后,在images/linux/目录下生成了sdk.sh文件,我们到该目录下查看
1 |
|
执行sdk.sh
1 |
|
默认路径是/opt/petalinux/2021.2,我这里保持默认,直接按回车就可以,然后输入y同意。
每次打开新的终端后,如果需要使用SDK,需要在使用前执行
1 |
|
执行后,输入arm再按两下Tab,可以看见交叉编译相关的命令,代表环境配置成功
此时,我们已摆脱petalinux的限制,可以直接使用交叉编译工具链编译BOOT,内核等
如果不想每次都手动配置SDK环境变量,执行下面的命令,每次有新终端打开时都会自动设置SDK环境变量
1 |
|
2. 生成设备树
首先在Github找到Xilinx发布的设备树源码,找到v2021.2的版本下载
https://github.com/Xilinx/u-boot-xlnx/tags
下载后放到合适的位置解压
打开Vitis新建工程
上方选项点击Xilinx,选择Software Repositories
点击New新建,添加刚刚下载的设备树文件所在的文件夹,并应用
新建Platform Project
填写项目名称
选择xsa文件,根据xsa文件建立设备树项目
Operating system选择device_tree
右键Build Project
编译完成后在vitis工作目录下/zynq_device_tree(你项目的名字)/ps7_cortexa9_0/device_tree_domain/bsp
下面生成了所需要的设备树文件
包括四个文件pcw.dtsi
,pl.dtsi
, system-top.dts
, zynq-7000.dtsi
如果硬件有更新,只需要右键项目然后Update Hardware Specification,再重新编译即可
3. 配置并编译u-boot
首先在Github上找到Xilinx发布的u-boot源码,选择v2021.2版本
https://github.com/Xilinx/u-boot-xlnx/tags
我们这里下载tar.gz的文件
把下载好的文件放进虚拟机里并解压
1 |
|
- 在u-boot源码目录下的configs文件夹下找到文件
xilinx_zynq_virt_defconfig
(可以ctrl+F搜索)
搜索CONFIG_DEFAULT_DEVICE_TREE,把对应的值改成system-top
搜索CONFIG_OF_LIST,把system-top
添加到list中
保存并退出
- 在include/configs目录下搜索
zynq-common.h
文件里搜索default environment
这里搜到的是u-boot的环境变量,在u-boot启动阶段会用到这些变量。
我们把环境变量改成下面的值:
1 |
|
保存并退出
- 进入
arch/arm/dts
目录,把之前生成的设备树文件拖进这个文件夹内
- 搜索文件
Makefile
这里可能要用到vim编辑文件(或者用其他文本编辑器也可以)
双击打开后发现是vim打开的,vim中按ctrl+B向前翻页,按ctrl+F向后翻页。我们往下翻翻到dtb-$(CONFIG_ARCH_ZYNQ)(大概在260行,右下角能看到是多少行)
在这一项的最后一行添加system-top.dtb
,如图所示。按”i”进入编辑模式,更改完毕后按esc退出编辑模式,再输入:wq
保存文件并退出vim
- 在u-boot源码的根目录下(一定要在源码根目录下)执行下面的命令,以xilinx_zynq_virt_defconfig的内容进行项目配置
1 |
|
- 同样在u-boot源码的根目录下执行下面的命令,使用menuconfig进行图形化配置
1 |
|
首先进入> Boot options > Autoboot options
中,把自动boot前的延迟时间改成5秒,这样在进入boot界面时会倒计时5秒再往下进行
进入> Boot options
,把bootcmd value改成run default_bootcmd
。这里对应之前在zynq-common.h中改过的环境变量,其中有一个变量名称是default_bootcmd,这里把bootcmd value改成default_bootcmd后,就把default_bootcmd设置成了boot执行的第一个脚本
进入> Environment
,把环境变量保存到FAT分区下
进入> Device Drivers > Serial drivers
,配置串口号
保存配置并退出
- 在u-boot源码根目录下执行下面的命令来编译
1 |
|
在源码根目录下生成目标文件u-boot.elf
arch/arm/dts目录下也生成了编译后的设备树文件system-top.dtb
4. 制作BOOT.bin
Vitis中创建Application Platform
选择根据xsa文件创建硬件平台
输入项目名称,这里是用来做fsbl的项目,所以命名为zynq_base_fsbl
选择Zynq FSBL
编辑fsbl_debug.h
添加一行#define FSBL_DEBUG_INFO
,这样在fsbl执行时会打印信息,从而在启动失败时判断错误原因
编译fsbl项目
右键fsbl项目Create Boot Image
如图是制作BOOT.bin需要的三个文件
他们的顺序一定是fsbl.elf > bit > u-boot.elf
fsbl.elf是执行的第一段引导程序,bit是硬件比特流,u-boot.elf是刚刚编译u-boot源码产生的文件,前两个不需要更改,只需要把最后一个文件改成u-boot.elf即可。
点击Create Image后生成Boot.bin,如图,直接右键复制就可以复制到文件夹里。
如果xsa文件有更新,右键fsbl的硬件平台,点击Update Hardware Specification,再重新编译fsbl项目即可。
至此,BOOT.bin已制作完成。
5. 配置并编译内核
首先在Github官网上找到Xilinx发布的内核源码,下载v2021.2版本
https://github.com/Xilinx/linux-xlnx/tags
拖到虚拟机里并解压
1 |
|
进入arch/arm/boot/dts
目录,把设备树文件拖进文件夹里
在此目录下搜索文件Makefile
使用同样的方法在dtb-$(CONFIG_ARCH_ZYNQ)的最后一行添加system-top.dtb
(大概在1293行)
到内核源码的根目录下,执行下面的命令使用xilinx_zynq_defconfig文件的内容做项目配置
1 |
|
一般我们不对内核进行修改,如果有需求再使用menuconfig进行配置即可。
在内核源码的根目录下运行下面的命令编译内核
1 |
|
最后会在arch/arm/boot
目录下面生成目标文件zImage
6. 启动开发板
我们已经得到了启动Linux需要的启动文件BOOT.bin
,zImage
,system-top.dtb
把这三个文件放到SD卡的第一个分区即可,根文件系统的移植操作和Petalinux章节的相同,根文件系统直接使用Petalinux编译出来的那个就可以了
在上电最开始5秒内按下回车进入uboot界面
此时应该能观察到其中一个LED闪烁,代表着bit文件已经下载到zynq里。
输入boot
启动内核
启动成功,进入Linux系统。此处仿照Petalinux章节中最后的内容,对GPIO进行操作
1 |
|
1 |
|
使用下面的命令控制另一个LED
1 |
|
至此,Linux移植部分的内容已全部介绍完毕。
参考文章
3_【正点原子】领航者ZYNQ之嵌入式Linux开发指南_V3.1