Init authored by Renaud Pacalet's avatar Renaud Pacalet
# A minimal GNU/Linux distribution for the ZedBoard
This page explains how to create a minimal GNU/Linux distribution for the ZedBoard (Linux kernel, U-Boot, device tree, root file system).
## Create a directory for all downloads and builds
Example with `/opt/build`:
```bash
export BUILDDIR=/opt/build
rm -rf $BUILDDIR
mkdir -p $BUILDDIR
```
## Get all git repositories
```bash
cd $BUILDDIR
git clone https://github.com/Xilinx/device-tree-xlnx.git
git clone http://github.com/Xilinx/u-boot-xlnx.git
git clone https://github.com/Xilinx/linux-xlnx.git
git clone http://git.buildroot.net/git/buildroot.git
```
## Set environment variables
```bash
export CROSS_COMPILE=arm-xilinx-linux-gnueabi-
export PATH=$PATH:path-to-Xilinx-tools/SDK/<version>/gnu/arm/lin/bin
${CROSS_COMPILE}gcc --version
```
Note the result of the last command, we will need it later.
## Compile the Linux kernel
```bash
cd $BUILDDIR/linux-xlnx
make mrproper
make ARCH=arm O=build xilinx_zynq_defconfig
make ARCH=arm O=build
export PATH=$PATH:$BUILDDIR/linux-xlnx/build/scripts/dtc
```
## Compile U-Boot
```bash
cd $BUILDDIR/u-boot-xlnx
make mrproper
make O=build zynq_zed_config
make O=build
cp build/u-boot $BUILDDIR/u-boot.elf
export PATH=$PATH:$BUILDDIR/u-boot-xlnx/build/tools
```
## Generate the U-Boot image of the Linux kernel
```bash
cd $BUILDDIR
mkimage -A arm -O linux -C none -T kernel -a 0x8000 -e 0x8000 -d linux-xlnx/build/arch/arm/boot/zImage uImage
```
Adapt the load address (`-a 0x8000`) and entry point (`-e 0x8000`) to your memory configuration.
## Configure and build a root file system
Use `buildroot` to configure your root file system, starting from the default. We will first configure `busybox`:
```bash
cd $BUILDDIR/buildroot
make O=$BUILDDIR/initramfs zedboard_defconfig
make O=$BUILDDIR/initramfs busybox-menuconfig
```
In the `busybox` configuration menu you may want to change:
```
Busybox Settings -> General Configuration -> Enable options for full-blown desktop systems -> no
Busybox Settings -> General Configuration -> Enable locale support (system needs locale for this to work) -> yes
Busybox Settings -> General Configuration -> Support Unicode -> yes
Busybox Settings -> General Configuration -> Use libc routines for Unicode (else uses internal ones) -> yes
Busybox Settings -> General Configuration -> Runtime SUID/SGID configuration via /etc/busybox.conf -> yes
```
Quit with saving and start configuring `buildroot`:
```bash
make O=$BUILDDIR/initramfs menuconfig
```
In the `buildroot` configuration menus you may want to change a few things:
```
Build options -> Location to save buildroot config -> <BUILDDIR>/buildroot.config
Build options -> Enable compiler cache -> yes (faster build)
Build options -> gcc optimization level -> 3 (optimize for speed)
Toolchain -> Toolchain type -> External toolchain
Toolchain -> Toolchain -> Custom toolchain
Toolchain -> Toolchain path -> <path-to-Xilinx-tools>/SDK/<version>/gnu/arm/lin
Toolchain -> Toolchain prefix -> arm-xilinx-linux-gnueabi (no "-" at the end)
Toolchain -> External toolchain gcc version -> <the-toolchain-version-you-noted>
Toolchain -> External toolchain C library -> glibc/eglibc
Toolchain -> Toolchain has RPC support? -> yes
Toolchain -> Toolchain has C++ support? -> yes
Toolchain -> Purge unwanted locales -> yes
Toolchain -> Locales to keep -> C en_US
Toolchain -> Generate locale data -> en_US.UTF-8
System configuration -> System hostname -> secbus
System configuration -> System banner -> Welcome to SecBus (c) Telecom ParisTech. Root password: secbus
System configuration -> Root password -> secbus
Kernel -> Linux Kernel -> no
Target packages -> BusyBox configuration file to use? -> <BUILDDIR>/busybox.config
Bootloaders -> U-Boot -> no
```
Note: do not use the `$BUILDDIR` environment variable. Replace <BUILDDIR> by the absolute path (`/opt/build` in our example) in the examples above. Quit with saving. We are almost done. Save the `buildroot` and `busybox` configurations and build the root file system:
```bash
make O=$BUILDDIR/initramfs savedefconfig
make O=$BUILDDIR/initramfs busybox-update-config
make O=$BUILDDIR/initramfs
```
If you get an error:
```
Incorrect selection of kernel headers: expected x.x.x, got y.y.y
```
note the `y.y.y` run again the `buildroot` configuration:
```bash
make O=$BUILDDIR/initramfs menuconfig
```
change:
```
Toolchain -> External toolchain kernel headers series -> the-kernel-version-you-noted
```
quit with saving, save again the configuration and build:
```bash
make O=$BUILDDIR/initramfs savedefconfig
make O=$BUILDDIR/initramfs
```
## Generate the U-Boot image of the root file system image
```bash
cd $BUILDDIR
mkimage -A arm -T ramdisk -C gzip -d initramfs/images/rootfs.cpio.gz rootfs.cpio.uboot
```
## Generate the Device Tree Sources (DTS) for your system
We assume that you used Vivado to create a Zynq design and that you synthesized it. You should find its Hardware Description File (HDF) in the Vivado output results. Its name is something like `xxx.sysdef`. We also assume that you have the Xilinx tools in your `PATH`. Download the provided [dts.hsi.tcl](zedboard-linux-uboot-dtb-buildroot/dts.hsi.tcl) TCL script and save it in `$BUILDDIR`. Use it to generate the DTS using the `hsi` utility from the Xilinx SDK:
```bash
mkdir $BUILDDIR/hw
cd $BUILDDIR/hw
hsi -mode batch -quiet -notrace -source ../dts.hsi.tcl -tclargs <some-path>/xxx.sysdef $BUILDDIR/device-tree-xlnx ../dts
```
The Device Tree Sources are in `$BUILDDIR/dts`.
## Edit the Device Tree Sources (DTS)
Edit the DTS files if needed. Examples of things you may want to change:
In `$BUILDDIR/dts/system.dts` (top level) you may want to change the definition of the physical memory base address and size:
```
memory {
device_type = "memory";
reg = <0x0 0x20000000>;
};
```
For instance, if you want to use the `[0x4800_0000...0x6000_0000[` range instead, replace the above lines by:
```
memory {
device_type = "memory";
linux,usable-memory = <0x48000000 0x18000000>;
};
```
In the same `$BUILDDIR/dts/system.dts` you may want to enable some of the 4 PS-to-PL clocks. To enable clocks FPGA1 and FPGA3, for instance, replace:
```
&clkc {
fclk-enable = <some-value>;
ps-clk-frequency = <33333333>;
};
```
by:
```
&clkc {
fclk-enable = <0xa>;
ps-clk-frequency = <33333333>;
};
```
If you decided to disable the CPU caches, in the`$BUILDDIR/dts/zynq-7000.dtsi` included DTS file, you may want to comment out the L2 cache controller:
```
/*
L2: cache-controller@f8f02000 {
compatible = "arm,pl310-cache";
...
};
*/
```
## Compile the Device Tree Blob (DTB)
Once your DTS files are adapted to your needs, compile the device tree blob:
```bash
cd $BUILDDIR
dtc -I dts -O dtb -o devicetree.dtb dts/system.dts
```
## Generate the First Stage Boot Loader (FSBL) for your system
Download the provided [fsbl.hsi.tcl](zedboard-linux-uboot-dtb-buildroot/fsbl.hsi.tcl) TCL script and save it in `$BUILDDIR`. Use it to generate the FSBL using the `hsi` utility from the Xilinx SDK:
```bash
cd $BUILDDIR/hw
hsi -mode batch -quiet -notrace -source ../fsbl.hsi.tcl -tclargs <some-path>/xxx.sysdef ../fsbl
```
The FSBL ELF is `$BUILDDIR/fsbl/executable.elf`.
## Generate the boot image
Pack the FSBL ELF, the bitstream (if any) for the programmable logic and the U-Boot ELF. First Download the provided [boot.bif](zedboard-linux-uboot-dtb-buildroot/boot.bif) boot image specification file and save it in `$BUILDDIR`. If you do not have a bitstream for the programmable logic edit `boot.bif` and comment out the line corresponding to the bitstream:
```
// bitstream.bit
```
Else, copy the bitstream (which should be in the same directory where you found the `xxx.sysdef` Hardware Description File) in `$BUILDDIR`:
```bash
cd $BUILDDIR
cp <some-path>/xxx.bit bitstream.bit
```
Generate the boot image:
```bash
cd $BUILDDIR
bootgen -w -image boot.bif -o boot.bin
```
## Copy on a SD card and boot
Copy all the elements on a SD card:
```bash
cp boot.bin devicetree.dtb rootfs.cpio.uboot uImage /media/SDCard
```
Unmount and eject the SD card, plug it to the ZedBoard, connect the USB UART cable, launch a serial console (minicom, cu, putty, screen...) and finally power up the ZedBoard. The first time you boot, the U-Boot environment variables are probably not what they should be. Stop the U-Boot count-down, restore the default environment variables (print and save the previous configuration if needed):
```
zynq-uboot> env default -a -f
```
Modify the following U-Boot environment variable to reflect the name of our root file system:
```
zynq-uboot> setenv ramdisk_image rootfs.cpio.uboot
```
This should be sufficient to boot our GNU/Linux distribution. To avoid typing this each time, save the variable definition on the on-board flash:
```
zynq-uboot> saveenv
```
<!-- vim: set tabstop=4 softtabstop=4 shiftwidth=4 noexpandtab textwidth=0: -->