zybo上运行linux,Zybo Board 开发记录: 执行 Linux 操作系统 - 全文

eef916dfdd0af44e3e33b48491c21529.png

本文转载自:coldnew's blog

在 zybo board 开发记录: Zynq 与 LED 闪烁控制 一文中我们谈到了如何透过 C 语言撰写独立的程序,让它控制 Zynq 的处理器系统 (Processing System, PS) 去闪烁 LED 的亮暗。既然 Zynq 的处理器系统 (Processing System, PS) 使用的是 ARM Cortex-A9 的处理器,那当然也可以让我们跑 Linux 在 Zybo Board 上。

本文将简述如何自行编译 u-boot 以及 Linux Kernel,并搭配 Busybox 制作简单的 RootFS 执行于 Zybo Board 上。

开发目标

在这次的开发中,我们要编译 u-boot、Linux,并使用 Busybox 制作简单的 Rootfs 后,透过制作 SD 卡来让 Zybo Board 透过 SD 卡开机。

要注意到的是,由于我们要透过 SD 卡开机进入到 Linux 系统,因此我们要透过 JP5 去更改开机模式。

5b4a5683d9be9f6004768dc8a34b97a7.png

了解开机流程

既然我们要让 Zybo board 执行 Linux 系统,就要先来了解一下开机流程,才知道我们大概需要准备哪些东西。从Zynq-7000 All Programmable SoC: Embedded Design Tutorial - A Hands-On Guide to EffecTIve Embedded System Design (UG1165) 可以看到 Zynq-7000 执行 Linux 系统的开机流程图。

685350cfec4b4c59320616194886b3fc.png

也就是说,当开始提供电源给 Zynq 处理器系统 (Processing System, PS) 并完成重置(reset) 后,Zynq 内建的 Boot ROM 会去加载 第一阶段开机程序 (First Stage Boot Loader, FSBL) ,接着加载 比特流 (bitstream) 去初始化整个 可程序逻辑(Programmable Logic, PL) 。 完成后,接下来就是透过 U-Boot 去加载 Linux Kernel、Device Tree 以及 Root File System。

了解了这个,我们就知道我们大概要准备哪些东西了。

设定好环境

在安装玩 Vivado 与 Xilinx SDK 后,实际上包含 Zynq 在用的 ARM toolchain 亦同时被安装到系统中,我们只要使用 source 命令即可让当前的环境知道 xilinx-arm toolchain 的路径。这边以 Viavdo 2016.2 作为范例。

coldnew@gentoo ~ $ source /opt/Xilinx/Vivado/2016.2/setTIngs64.sh

这样就可以获得 arm-xilinx-* toolchain 的命令,实际上有哪些呢? 输入个 arm-xilinx- 按下 TAB 看看

5be036c9dcb68fe0b4db56ebdc267ffa.png

如果你系统上已经有其他的 ARM toolchain 的话,可以考虑跳过这一步骤,接下来要格式化 Micro SD 卡。

格式化 MicroSD 卡

在这次的开发中,我们要设定 MicroSD 卡片成两个分区,第一个是 fat32 格式,第二个则使用 ext4 格式,若不会使用 fdisk 命令的话,可以透过 gparted 来进行格式化,以下是我格式化卡片的范例 (8GB 卡片)。

667a62265a52611bab682d21152e417f.png

(实际上在本文的范例中,只会用到第一个分区,第二个分区是为了往后文章要开机到大一点的 rootfs 准备的。)

编译 u-boot

我们首先去 GitHub 下载 DigilenTInc 加入 zybo board 后的 u-boot 版本,要注意这边要选择 master-next 分支。

git clone https://github.com/DigilenTInc/u-boot-Digilent-Dev.git -b master-next

完成后进入到该文件夹

coldnew@gentoo ~ $ cd u-boot-Digilent-Dev

编译 u-boot,记得指派编译目标为 zynq_zybo_config

coldnew@gentoo ~/u-boot-Digilent-Dev $ CROSS_COMPILE=arm-xilinx-linux-gnueabi- make zynq_zybo_config

coldnew@gentoo ~/u-boot-Digilent-Dev $ CROSS_COMPILE=arm-xilinx-linux-gnueabi- make

编译完成后,注意一下 u-boot 这个档案,他就是我们等等要用到的 u-boot 执行档,不过由于 Xilinx Tool 要找有 .elf 扩展名的档案,因此我们把它复制成 u-boot.elf 。

coldnew@gentoo ~/u-boot-Digilent-Dev $ cp u-boot u-boot.elf

编译 Linux kernel

编译好 u-boot 后,接下来就是编译 Linux Kernel 了,我们一样选择 DigilentInc 加入 zybo board 后的 Linux Kernel 版本,记得要选 master-next 分支。

git clone https://github.com/DigilentInc/Linux-Digilent-Dev.git -b master-next

接着,当然就是编译了,不过在这之前请先确定你有装 u-boot-tools 这套件,我们需要里面的 mkimage 指令,Gentoo Linux 可以直接用以下命令来安装。

coldnew@gentoo ~ $ sudo emerge dev-embedded/u-boot-tools

完成后进入 Linux Kernel 文件夹

coldnew@gentoo ~ $ cd Linux-Digilent-Dev

编译我们需要的 uImage 文件,记得要指定 config 为 xilinx_zynq_defconfig 以及设定 UIMAGE_LOADADDR为 0x8000 。

coldnew@gentoo ~/Linux-Digilent-Dev $ ARCH=arm CROSS_COMPILE=arm-xilinx-linux-gnueabi- make xilinx_zynq_defconfig

coldnew@gentoo ~/Linux-Digilent-Dev $ ARCH=arm CROSS_COMPILE=arm-xilinx-linux-gnueabi- make

coldnew@gentoo ~/Linux-Digilent-Dev $ ARCH=arm CROSS_COMPILE=arm-xilinx-linux-gnueabi- make UIMAGE_LOADADDR=0x8000 uImage

coldnew@gentoo ~/Linux-Digilent-Dev $ ARCH=arm CROSS_COMPILE=arm-xilinx-linux-gnueabi- make zynq-zybo.dtb

编译完后,我们会需要 arch/arm/boot/uImage 以及 arch/arm/boot/dts/zynq-zybo.dtb 这两个档案,后者就是 device tree 编译出来的数据文件。

由于放入到 SD 卡上的 device tree 文件名为 devicetree.dtb ,因此这边将 zynq-zybo.dtb 改一下名。

coldnew@gentoo ~/Linux-Digilent-Dev $ cp arch/arm/boot/dts/zynq-zybo.dtb devicetree.dtb

如果你想手动修改 Device Tree 并再重新编译的话,也可以这样去产生我们要的 devicetree.dtb 。

coldnew@gentoo ~/Linux-Digilent-Dev $ ./scripts/dtc/dtc -I dts -O dtb -o devicetree.dtb arch/arm/boot/dts/zynq-zybo.dts

编译 BusyBox

Busybox 是一个非常有趣的程序,举凡我们在 Linux 下最常用的命令如 ls、cd 等到 sed、vi 他都具有相对应的简单实现,此外,这些命令实际上都只是一个软连结 (symlink) 连结到名为 busybox 的执行档,也就是说,如果我们将 busybox 进行静态编译 (static link),则制作出来的系统整体大小大约为 2 MB (kernel) + 1.4 MB (busybox),而这个系统却又可以具有许多 UN*X 下的常用命令,也因此 busybox 很常用于空间有限的系统。

我们在这个开发过程中,由于只是验证执行 Linux 系统的功能,因此选用 Busybox 来作为我们的 rootfs。

首先先下载 Busybox 的原始码,这里选用 1_25_stable 这个稳定分支

git clone git://git.busybox.net/busybox -b 1_25_stable

进行我们自己的设定

coldnew@gentoo ~/busybox $ ARCH=arm CROSS_COMPILE=arm-xilinx-linux-gnueabi- make menuconfig

在进行设定时有以下几点要确实注意,我们要将 busybox 编译为静态链接,并且增加 init 功能,主要设定如下:

Busybox Settings --->

Build Options --->

[*] Build BusyBox as a static binary (no shared libs)

Init Utilities --->

[*] init

Login/Password Management Utilities --->

[*] getty

Shells --->

[*] ash

设定完成后开始进行编译

coldnew@gentoo ~/busybox $ ARCH=arm CROSS_COMPILE=arm-xilinx-linux-gnueabi- make

编译完成后透过 make install 命令,会将编译出来的 busybox 与软连结(symlink)产生在 _install 文件夹内

coldnew@Rosia ~/busybox $ ARCH=arm CROSS_COMPILE=arm-xilinx-linux-gnueabi- make install

建立一些缺少的文件夹 (/dev、/sys …etc)

coldnew@gentoo ~/busybox $ cd _install && mkdir -p proc sys dev etc/init.d root

建立 etc/init.d/rcS 作为启动脚本,并添加以下内容

coldnew@gentoo ~/busybox/_install $

vim etc/init.d/rcS

#!/bin/sh

mount -t proc none /proc

mount -t sysfs none /sys

/sbin/mdev -s

将 etc/init.d/rcS 加入可执行权限

coldnew@gentoo ~/busybox/_install $ chmod +x etc/init.d/rcS

建立 etc/inittab ,这会让我们可以透过 UART 登入 zybo board

coldnew@gentoo ~/busybox/_install $

vim etc/inittab

#!/bin/sh

#

Init script

::sysinit:/etc/init.d/rcS

#

Start shell on the serial ports

::respawn:/sbin/getty -L ttyPS0 115200 vt100

#

What to do when restarting the init process

::restart:/sbin/init

#

What to do before rebooting

::shutdown:/bin/umount -a -r

设定默认的 /etc/passwd 档案,我们要让 root 用户登入时不用输入密码

coldnew@gentoo ~/busybox/_install $

vim etc/passwd

root::0:0:root:/root:/bin/sh

建立 /init 并软连结到 /sbin/init ,避免 Linux Kernel 开机时找不到 rootfs 的 init。

coldnew@gentoo ~/busybox/_install $ ln -s /sbin/init init

接下来,由于这次我们只是要开机到 ramdisk 上的 rootfs, 因此将 busybox 做出的 rootfs 打包成 cpio 格式。

coldnew@gentoo ~/busybox/_install $ find . | cpio -H newc -o | gzip -9 > ../uramdisk.cpio.gz

再透过 mkimage 将这个 uramdisk.cpio.gz 档案转成 uboot 用的 uramdisk.image.gz

coldnew@gentoo ~/busybox/_install $ mkimage -A arm -T ramdisk -C gzip -d ../uramdisk.cpio.gz ../uramdisk.image.gz

Image Name:

Created:

Sun Jul 17 19:02:08 2016

Image Type: ARM Linux RAMDisk Image (gzip compressed)

Data Size: 1042106 Bytes = 1017.68 kB = 0.99 MB

Load Address: 00000000

Entry Point: 00000000

在这边的这个 uramdisk.image.gz 就是我们开机会进入到的 rootfs,也是我们等等要放到 SD 卡第一个扇区的档案。

编译比特流 (bitstream)

在 zybo board 开发记录: 升级 Digilent 提供的设计档 一文中,我们提到了怎样升级 Digilent 提供的预先定义好接脚的配置文件 (zybo_base_system) ,这次的项目,我们就直接用这个配置文件案来进行 Linux 开机的动作。

首先你必须根据该篇文章,将你的 Zybo board 配置文件案升级到你用的 Vivado 版本,完成后我们重新建立一个干净的项目。

首先先把先前生成的旧项目清掉:

coldnew@gentoo ~/ZYBO/Projects/linux_bd/proj $ sh cleanup.sh

接下来用 Vivado 2016.2 重新生出新的项目 ~

coldnew@gentoo ~/ZYBO/Projects/linux_bd/proj $ /opt/Xilinx/Vivado/2016.2/bin/vivado -mode batch -source create_project.tcl

完成后,会看到 ZYBO/Projects/linux_bd/proj 目录变成这样:

coldnew@gentoo ~/ZYBO/Projects/linux_bd/proj $

tree -L 1

.

├── cleanup.cmd

├── cleanup.sh

├── create_project.tcl

├── ip_upgrade.log

├── linux_bd.cache

├── linux_bd.hw

├── linux_bd.ip_user_files

├── linux_bd.sim

├── linux_bd.srcs

├── linux_bd.xpr

├── vivado.jou

└── vivado.log

5 directories, 7 files

我们使用 Vivado 打开 linux_bd.xpr 这个专案。

1b21f771c7710cfb7eab5c919055fc03.png

如果你有兴趣看他生出来的 Block Design 是怎样的,也可以切到 Block Design 那页看看

04cc13a2f854d3896886fb4a2efac8f6.png

我们直接点选 Program and Debug -> Generate Bitstream 产生我们要的比特流 (bitstream)

355cdddc9678aa02340891b90460de25.png

建立 FSBL

到此,我们除了 第一阶段开机程序 (First Stage Boot Loader, FSBL) 外,其他的程序都已经编译出执行档了,让我们来处理 FSBL 吧。

首先点选 File -> Export -> Export hardware

c7453d47e9b4763cdfb5e336e980b2f4.png

记得要勾选 Include bitstream

7b9f3d0b9b3f5f2e297e84a89445da6c.png

完成后,执行 Xilinx SDK

0ffb1148967dd5ee5d570a12beb5a0ca.png

透过 File -> New -> Application Project 去建立我们的新项目

22fa20636f1508460a9ad513f3fddae2.png

设定这个项目为 standalone 的项目

fe5c19a5606282bc143cd5ab50278880.png

选择样板为 Zynq FSBL

a52b528ef3fdb251ceef5e067da5b9b3.png

选择我们刚刚建立的 FSBL 项目,按下右键选择 Build Project 进行编译

0873460ef6334c627056db3cfeae6b23.png

建立 BOOT.bin

编译完 FSBL 后,选择 Xilinx Tools -> Create Boot Image 去建立我们的 BOOT.bin

3ed0be18754eb9db521fc0701dfaa572.png

在 Boot image partitions 那边,加入我们的 bitstream 以及 u-boot 档案,记得要按照顺序加入。

完成后,点选 Create Image 就会产生我们要的 BOOT.bin 到指定路径。

fefc149407d371505183a149c95202b6.png

在这个步骤中,如果你是指令控的话,我们也可以在产生 FSBL.elf 后,建立一个名为 boot.bif 的档案,其内容如下

//arch = zynq; split = false; format = BIN

the_ROM_image:

{

[bootloader]/path/to/fsbl-build/fsbl.elf

/path/to/linux_bd/linux_bd.sdk/linux_bd_wrapper.bit

/path/to/u-boot/u-boot.elf

}

接下来透过 bootgen 这个命令去产生 BOOT.bin

coldnew@gentoo ~ $ bootgen -image boot.bif -w on -o i boot.bin

将档案复制到 Micro SD 卡

好了,我们已经完成了所有准备动作,是时候将档案放到 Micro SD 卡并看看结果了,在本文中我们会将以下几个档案放到 第一个分割区 (fat32) 。

coldnew@gentoo /tmp/sdc1 $

tree -L 1

.

├── BOOT.bin

├── devicetree.dtb

├── uImage

└── uramdisk.image.gz

0 directories, 4 files

也就是说我们的 SD 卡有的东西,要像 The Zynq Book p.439 这张图那样

6417ff511ca653311451578f86ad1fa8.png

测试开机与结果

是时候来测试结果了,要注意到你的 Zybo Board 的 JP5 要设定成下面这样,这样给电时,Zynq 才会读取 SD 卡上面的 u-boot 并将比特流 (bitstream) 刻录到 FPGA 中。

a7ec3b7ac645fa2121eee9d7d7703043.png

插入刚刚建立好的 SD 卡,并提供电源后,我们可以使用可以接收 UART 相关的程序,如 gtkterm、teraterm、screen、emacs 等,启动它并开启 /dev/ttyUSB1 后,设定 baudrate 为 115200 ,就可以看到开机到 rootfs 的状态。

b166cb900eb01a3409cf41e1fed7b4eb.png

取得程序代码

本文的范例已经放置于 GitHub 上,你可以到以下的 repo 去寻找,具体项目对应的教学名称,则请参考README.md 档案

延伸阅读

[1] Zynq-7000 All Programmable SoC: Embedded Design Tutorial - A Hands-On Guide to Effective Embedded System Design (UG1165)

[2] ZYBO Zync-7000 Development Board Work - Booting Linux on the ZYBO

[3] The Zynq Book

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值