Xilinx有个工具叫PetaLinux,它可以一键生成uboot、Linux、根文件系统。但是按照惯例我们还是自己敲命令一个个来吧。

Xilinx有个wiki讲述如何一步步做Linux from scratch。有些步骤是多余的,比如编译设备树的工具链。鉴于我们的EBAZ4205是块野生的板子,需要稍微做一些配置。

安装vivado、SDK时候顺便安装了arm-linux-gnueabihf-以及其他Xilinx自家的工具链,不妨将其export到PATH:

# gcc
export PATH=/某某某/SDK/2017.4/gnu/aarch32/lin/gcc-arm-linux-gnueabi/bin/:$PATH
# bootgen etc.
export PATH=/某某某/SDK/2017.4/bin:$PATH

所有工作开始之前,还要export ARCHCROSS_COMPILE两个环境变量:

export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-

uboot

uboot只需要极少量的配置,就基本上works out of the box了。现在我们先用tftp来启动内核。各部分的地址如下:

文件名 启动地址
设备树 zynq-zc702.dtb 0
内核 uImage 0x8000
文件系统 uramdisk.image.gz 0x01000000

https://github.com/Xilinx/u-boot-xlnx上下载Xilinx家的uboot,当然也可以选择去下载release版本的。

改改配置

arch/arm/dts/zynq-zc702.dtsmemory节点,内存大小改为256MB

@@ -21,7 +21,7 @@

     memory@0 {
         device_type = "memory";
-        reg = <0x0 0x40000000>;
+        reg = <0x0 0x10000000>;
     };

     chosen {

直接用zynq_zc702_defconfig

make zynq_zc702_defconfig
  • 关闭CONFIG_ENV_IS_IN_SPI_FLASH,不然启动时候会卡死在SPI flash初始化部分。这时候就用默认的环境变量。
  • 开启CONFIG_NANDCONFIG_NAND_ZYNQ,以开启nand命令。

定制环境变量,改include/configs/zynq-common.h,主要是来配置启动参数。

  • tftp之前得显式地设置serverip
  • 要tftp内核、设备树、根文件系统
set serverip xxx.xxx.xxx.xxx
dhcp
tftpboot 0 zynq-zc702.dtb
tftpboot 8000 uImage
tftpboot 1000000 uramdisk.image.gz
bootm 8000 1000000 0

然后make,生成了u-boot可执行文件。

生成BOOT.bin

我们写一个boot.bif,引用之前建的helloworld工程中的FSBLbitstream

the_ROM_image:
{
    [bootloader]/某某某/fsbl.elf
    /某某某/ebaz4205_wrapper.bit
    /某某某/u-boot.elf
}

利用vivado安装的工具bootgen,通过上述配置文件来生成BOOT.binu-boot需要重命名为u-boot.elf,不然bootgen不认为它是ELF文件,就当它是bin文件来处理了。。。

mv u-boot u-boot.elf
bootgen -image boot.bif -o i BOOT.bin -w

Linux内核

内核很大程度上也是work out of the box了,改改设备树就好。

https://github.com/Xilinx/linux-xlnx上下载Xilinx家的内核。目前版本是4.19.0,还是挺新的。

设备树

首先还是得将内存大小改对:

        memory@0 {
                device_type = "memory";
-               reg = <0x0 0x40000000>;
+               reg = <0x0 0x10000000>;
        };

因为我们的野生板子外设很少,必须将不用的外设disabled掉,不然引脚配置会打架。

 &can0 {
-       status = "okay";
+       status = "disabled";

...

 &i2c0 {
-       status = "okay";
+       status = "disabled";

 &qspi {
        u-boot,dm-pre-reloc;
-       status = "okay";
+       status = "disabled";

 &usb0 {
-       status = "okay";
+       status = "disabled";

串口的引脚要改对:

@@ -368,12 +382,12 @@
         };

         conf-rx {
-            pins = "MIO49";
+            pins = "MIO25";
             bias-high-impedance;
         };

         conf-tx {
-            pins = "MIO48";
+            pins = "MIO24";
             bias-disable;
         };
     };

网口通过EMIO引出,因此gem0的引脚声明应该删掉,否则会跟串口引脚打架,导致启动到一半串口没输出了。。并且ethernet_phy节点的reg参数应改为0,不然会枚举不到那个网卡:

&gem0 {
    status = "okay";
    phy-mode = "rgmii-id";
    phy-handle = <&ethernet_phy>;
-    pinctrl-names = "default";
-    pinctrl-0 = <&pinctrl_gem0_default>;
-    phy-reset-gpio = <&gpio0 11 0>;
-    phy-reset-active-low;

-    ethernet_phy: ethernet-phy@7 {
-        reg = <7>;
+    ethernet_phy: ethernet-phy@0 {
+        reg = <0>;
         device_type = "ethernet-phy";
     };
};

SDIO接口也在fsbl初始化完成了,所以它的引脚声明也要删掉:

 &sdhci0 {
     u-boot,dm-pre-reloc;
     status = "okay";
-    pinctrl-names = "default";
-    pinctrl-0 = <&pinctrl_sdhci0_default>;
 };

为了用nand flash,需要添加nand节点。在阿莫论坛有个帖子,62楼列举了原板子启动的log,可以看到它有9个分区:

Creating 9 MTD partitions on "pl35x-nand":
0x000000000000-0x000000300000 : "nand-fsbl-uboot"
0x000000300000-0x000000800000 : "nand-linux"
0x000000800000-0x000000820000 : "nand-device-tree"
0x000000820000-0x000001220000 : "nand-rootfs"
0x000001220000-0x000002220000 : "nand-jffs2"
0x000002220000-0x000002a20000 : "nand-bitstream"
0x000002a20000-0x000006a20000 : "nand-allrootfs"
0x000006a20000-0x000007e00000 : "nand-release"
0x000007e00000-0x000008000000 : "nand-reserve"

所以我们这样设置nand0节点:

&nand0 {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_nand0_default>;
    partition@0 {
        label = "nand-fsbl-uboot";
        reg = <0x0 0x300000>;
    };
    partition@1 {
        label = "nand-linux";
        reg = <0x300000 0x500000>;
    };
    partition@2 {
        label = "nand-device-tree";
        reg = <0x800000 0x20000>;
    };
    partition@3 {
        label = "nand-rootfs";
        reg = <0x820000 0xa00000>;
    };
    partition@4 {
        label = "nand-jffs2";
        reg = <0x1220000 0x1000000>;
    };
    partition@5 {
        label = "nand-bitstream";
        reg = <0x2220000 0x800000>;
    };
    partition@6 {
        label = "nand-allrootfs";
        reg = <0x2a20000 0x4000000>;
    };
    partition@7 {
        label = "nand-release";
        reg = <0x6a20000 0x13e0000>;
    };
    partition@8 {
        label = "nand-reserve";
        reg = <0x7e00000 0x200000>;
    };
};

它的引脚配置pinctrl_nand0_default如下:

    pinctrl_nand0_default: nand0-default {
        mux {
            groups = "smc0_nand8_grp";
            function = "smc0_nand";
        };

        conf {
            groups = "smc0_nand8_grp";
            bias-pull-up;
        };
    };

groups的名字是在pinctrl-zynq.c第715行找到的。

由于在zynq-7000.dtsi里,nand0smcc的子节点,所以还要使能smcc节点:

&smcc {
    status = "okay";
};

为了避免pinctrl_gpio0_defaultpinctrl_nand0_default引脚打架,前者的引脚都应该删掉:

     pinctrl_gpio0_default: gpio0-default {
         mux {
             function = "gpio0";
-            groups = "gpio0_7_grp", "gpio0_8_grp", "gpio0_9_grp",
-                 "gpio0_10_grp", "gpio0_11_grp", "gpio0_12_grp",
-                 "gpio0_13_grp", "gpio0_14_grp";
+            groups = "";
         };

         conf {
-            groups = "gpio0_7_grp", "gpio0_8_grp", "gpio0_9_grp",
-                 "gpio0_10_grp", "gpio0_11_grp", "gpio0_12_grp",
-                 "gpio0_13_grp", "gpio0_14_grp";
+            groups = "";
             slew-rate = <0>;
             io-standard = <1>;
         };

         conf-pull-up {
-            pins = "MIO9", "MIO10", "MIO11", "MIO12", "MIO13", "MIO14";
+            pins = "";
             bias-pull-up;
         };

         conf-pull-none {
-            pins = "MIO7", "MIO8";
+            pins = "";
             bias-disable;
         };
     };

其他节点该删的都要删掉,比如gpio-keysledsusb_phy0等。还有一些pinctrl的节点,看着碍事也不妨删掉,比如pinctrl_gem0_default等。。

编译

其实用xilinx_zynq_defconfig已经足够,不过如果想要更多的功能,比如ZRAM压缩内存之类的比较骚的设施,也可以稍微配置一下。。

记得我们uboot会将内核放在32K开始的内存地址处。然后编译设备树。

make xilinx_zynq_defconfig
make uImage UIMAGE_LOADADDR=0x8000
make dtbs

rootfs

Build and Modify a Rootfs上下载人家编译好的busybox做的文件系统arm_ramdisk.image.gz,然后将它打包为uboot能识别的格式:

mkimage -A arm -T ramdisk -C gzip -d arm_ramdisk.image.gz uramdisk.image.gz

启动!

装好tftp server,将uImagezynq-zc702.dtburamdisk.image.gz放进去。将BOOT.bin丢进格式化为fatfs的SD卡的根目录里面,然后就可以等它启动了。

## Booting kernel from Legacy Image at 00008000 ...
  Image Name:   Linux-4.19.0-xilinx
  Image Type:   ARM Linux Kernel Image (uncompressed)
  Data Size:    4322424 Bytes = 4.1 MiB
  Load Address: 00008000
  Entry Point:  00008000
  Verifying Checksum ... OK
## Loading init Ramdisk from Legacy Image at 01000000 ...
  Image Name:
  Image Type:   ARM Linux RAMDisk Image (gzip compressed)
  Data Size:    5309954 Bytes = 5.1 MiB
  Load Address: 00000000
  Entry Point:  00000000
  Verifying Checksum ... OK
## Flattened Device Tree blob at 00000000
  Booting using the fdt blob at 0x000000
  Loading Kernel Image ... OK
  Loading Ramdisk to 0e5f3000, end 0eb03602 ... OK
  Loading Device Tree to 0e5ec000, end 0e5f27a6 ... OK

Starting kernel ...

Booting Linux on physical CPU 0x0
Linux version 4.19.0-xilinx (hyq@ict) (gcc version 6.2.1 20161114 (Linaro GCC Snapshot 6.2-2016.11))
#19 SMP PREEMPT Wed Apr 24 21:55:25 CST 2019
CPU: ARMv7 Processor [413fc090] revision 0 (ARMv7), cr=18c5387d

....

VFS: Mounted root (ext4 filesystem) on device 1:0.
Starting rcS...
++ Mounting filesystem
mount: mounting /dev/mmcblk0p1 on /mnt failed: No such file or directory
mount: mounting /dev/mmcblk0 on /mnt failed: No such file or directory
++ Setting up mdev
++ Starting telnet daemon
++ Starting http daemon
++ Starting ftp daemon
++ Starting ssh daemon
random: sshd: uninitialized urandom read (32 bytes read)
rcS Complete
zynq>
zynq> 
zynq> 
zynq> uname -a
Linux (none) 4.19.0-xilinx #19 SMP PREEMPT Wed Apr 24 21:55:25 CST 2019 armv7l GNU/Linux
zynq>