Posted on 30 Apr 2019 By Noah Hütter
In this post I will show you how to compile and install a vanilla Linux kernel and root file system on Zynq SoC.
Disclaimer: This code is largely copied from https://github.com/pavel-demin/red-pitaya-notes, licensed under MIT license.
DO NOT WORK ON A SHARED FOLDER INSIDE VIRTUALBOX It will get messy, because the Linux kernel build uses a case sensitive file system, which Mac does not provide.
Clone my zynq-sandbox repository from github if you have not done so already.
git clone https://github.com/noah95/zynq-sandbox
Fix gmake:
sudo ln -s /usr/bin/make /usr/bin/gmake
Install some tools:
sudo apt install curl u-boot-tools libncurses-dev
Change to the Linux directory.
cd sw/linux
For educational build purposes, the Makefile was extended to build each component seperately. This guide will go through all components and briefly explain what they are needed for.
Requires:
Generates:
build/name.fsbl/executable.elfThis generates the source code and binary for the first level bootloader that is executed after power on. After project creation, the fsbl is compiled and the binary written.
rm -r build/*.fsbl
make fsbl
Requires:
Generates:
dtsThe devicetree files from Xilinx are downloaded and a device tree project created from the hardware definition files.
From these two sources, a set of dts (device tree sources) files are generated.
Finally the makefile applies a patch to some output files.
The patch file is generates by this command:
diff -rupN pcw.dtsi pcw.dtsi.new > devicetree.patch
rm -r build/*.tree
make dts
Requires:
Generates:
uImageNow it is time to pull a vanilla Linux kernel, uncompress the sources, apply some patches, copy some config and finally build the kernel. Issue the following command and go for a walk:
rm -r build/linux*
make uimage
or if the sources are already downloaded and you don’t want to clean before build:
make -C build/linux-4.14 ARCH=arm xilinx_zynq_defconfig
make -C build/linux-4.14 ARCH=arm CFLAGS="-O2 -march=armv7-a \
-mcpu=cortex-a9 -mtune=cortex-a9 -mfpu=neon -mfloat-abi=hard" \
-j 4 \
CROSS_COMPILE=arm-linux-gnueabihf- UIMAGE_LOADADDR=0x8000 uImage modules
Requires:
Generates:
u-boot.elfThe bootloader is build from source pulled from Xilinxed repositoriers. Before build, some config files are copied and patches applied.
rm -r build/u-boot*
make uboot
Requires:
uImageGenerates:
devicetree.dtbUsing the device tree sources generated previously, the devicetree compiler is used to generate the devicetree blob.
rm -r build/devicetree*
make dtb
Requires:
Generates:
boot.binNow the three binaries can be tied to a single binary image.
rm -r build/boot.bin
make bootbin
Requires:
Generates:
For u-boot to know what linux version to load we have to generate a uEnv.txt file. This is done by running the following command:
rm -r build/uEnv.txt
make uenv
Create two partitions on a SD-Card:
label:BOOT flags:bootlabel:rootCopy the following files on the boot partition:
Connect a serial console and power up the board. Hit a key to interrupt u-boot automatic boot process. To check if the uImage and devicetree are correct issue the following commands:
mmcinfo
fatload mmc 0 0x2080000 uImage
fatload mmc 0 0x2000000 devicetree.dtb
iminfo 0x2000000
iminfo 0x2080000
setenv bootargs console=ttyPS0,115200 root=/dev/mmcblk0p2 ro rootfstype=ext4 earlyprintk rootwait
bootm 0x2080000 - 0x2000000
At this point the kernel should start but fail with a kernel panic because no init was found.
For that we next generate the rootfs.
First we try the smallest rootf available: Busybox. To download, untar and build, run:
make busybox
To modify busybox and build manually:
cd build/busybox-*
make -j4 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
make -j4 ARCH=arm INSTALL_PATH=build/ install
Now copy the installed busybox and some install scripts to the root partition of the SD-card.
./scripts/busybox-sdcard.sh /link/to/sdcard/root/
We should now be able bring up the network!
ifconfig eth0 up
udhcpc -i eth0 -p /var/run/dhcpClient-eth0.pid
ifconfig eth0 192.168.0.87 netmask 255.255.255.0
route add default gw 192.168.0.1
ping 8.8.8.8