Kernel and devicetrees
This section provides a concise guide on building the Linux kernel and devicetrees for different platforms on different hosts.
Jump to your platform and preferred method:
Building the Zynq Linux kernel and devicetrees from source
Using a script
We provide a script that does automates the build for Zynq using the Linaro toolchain.
The script takes up to 3 parameters, but if left blank, it uses defaults:
<local_kernel_dir> - default is linux-adi if left blank ; use this, if you want to use an already cloned kernel repo
<devicetree_file> - which device tree should be exported/copied from the build. Default is
zynq-zc702-adv7511-ad9361-fmcomms2-3.dtb
for Zynq<path_to_other_toolchain> - in case you have your own preferred toolchain (other than Linaro’s or Xilinx’s) you can use override it with this 3rd param
The script will:
Clone the ADI kernel tree
Download the Linaro GCC toolchain (if no other is specified)
Build the ADI kernel tree
Export/copy the Image file and device tree file out of the kernel build folder
Running the script in one line, with defaults:
~$
wget https://raw.githubusercontent.com/analogdevicesinc/wiki-scripts/main/linux/build_zynq_kernel_image.sh && \
chmod +x build_zynq_kernel_image.sh && \
./build_zynq_kernel_image.sh
Building with Petalinux
Please see here: Building with Petalinux.
On the development host
Make sure you have u-boot-tools
installed, to have the mkimage
utility
available. You can install it via your distro’s package manager.
Then
~$
git clone https://github.com/analogdevicesinc/linux.git \
--no-single-branch --depth=10 \
-- linux
or do a git pull in a existing cloned repository.
The depth
and no-single-branch
options are included to speed up the
cloning by fetching only near the head of each branch/release, you may remove
them to fetch all history, but bear in mind it will go from around 800MB to
around 3.4GB and growing.
Checkout the Release branch
Tip
Use the latest release, if not required otherwise!
Release names and Branches |
---|
2014_R2 |
2015_R2 |
2016_R1 |
2016_R2 |
2017_R1 |
2018_R1 |
2018_R2 |
2019_R1 |
2019_R2 |
2021_R1 |
~$
git checkout origin/2021_R1 -b 2021_R1
Branch 2021_R1 set up to track remote branch 2021_R1 from origin.
Switched to a new branch '2021_R1'
Setup cross compile environment variables
There are a few toolchains that can be used. The Xilinx toolchain is recommended, but the Linaro toolchain can also be used.
Other toolchains/compilers for ARM may work as well, but the ones described here have been tested and found to work.
Using the Xilinx toolchain
Release names and Branches |
Required Vivado/Vitis versions |
---|---|
2014_R2 |
Vivado 2014.2 |
2015_R2 |
Vivado 2015.2 |
2016_R1 |
Vivado 2015.4.2 |
2016_R2 |
Vivado 2016.2 |
2017_R1 |
Vivado 2016.4 |
2018_R1 |
Vivado 2017.4 |
2018_R2 |
Vivado 2018.2 |
2019_R1 |
Vivado 2018.3 |
2019_R2 |
Vivado 2019.1 |
2021_R1 |
Vivado 2021.1 |
~$
source $PATH_TO_XILINX/Vitis/$VITIS_VERSION/settings64.sh
~$
which which arm-linux-gnueabihf-gcc
$PATH_TO_XILINX/Vitis/$VITIS_VERSION/gnu/aarch32/lin/gcc-arm-linux-gnueabi/bin/arm-linux-gnueabihf-gcc
Important
Find the path to the Xilinx installation folder, and then use it to replace this string: $PATH_TO_XILINX that is written above. Same goes for the $VITIS_VERSION, where you choose the Vitis version.
~$
export ARCH=arm
~$
export CROSS_COMPILE="arm-linux-gnueabihf-"
Using the Linaro toolchain
Alternatively, the Linaro toolchain/compiler can be used to compile to kernel. Linaro compilers (that work with Zynq) can be downloaded from here. Always use the latest release just in case.
~$
wget https://releases.linaro.org/components/toolchain/binaries/latest-7/arm-linux-gnueabi/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabi.tar.xz
~$
tar -xvf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabi.tar.xz
~$
export ARCH=arm
~$
export CROSS_COMPILE=$(pwd)/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabi/bin/arm-linux-gnueabi-
Configure the kernel
Inside the repository, generate the configuration file before building the kernel tree. The command shown below is generic and is not project specific. As long as the board is a ZYNQ FPGA, use the configuration below.
~$
make zynq_xcomm_adv7511_defconfig
#
# configuration written to .config
#
Build the kernel
Build the kernel via ‘make’. This is the same for all Xilinx ZYNQ FPGAs.
~$
make -j5 UIMAGE_LOADADDR=0x8000 uImage
scripts/kconfig/conf --silentoldconfig Kconfig
CHK include/config/kernel.release
CHK include/generated/uapi/linux/version.h
UPD include/config/kernel.release
CHK include/generated/utsrelease.h
[ -- snip --]
AS arch/arm/boot/compressed/bswapsdi2.o
AS arch/arm/boot/compressed/piggy.gzip.o
LD arch/arm/boot/compressed/vmlinux
OBJCOPY arch/arm/boot/zImage
Kernel: arch/arm/boot/zImage is ready
UIMAGE arch/arm/boot/uImage
Image Name: Linux-3.17.0-126697-g611e217-dir
Created: Fri Nov 28 10:20:40 2014
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 3195872 Bytes = 3120.97 kB = 3.05 MB
Load Address: 00008000
Entry Point: 00008000
Build the devicetree FCMOMMS2/3/4/5
Build the one that fits your FPGA carrier and FMC card
device tree |
board |
chip |
---|---|---|
zynq-adrv9361-z7035-bob |
||
zynq-adrv9361-z7035-bob-cmos |
||
zynq-adrv9361-z7035-packrf |
||
zynq-adrv9361-z7035-fmc |
||
zynq-adrv9361-z7035-fmc-rfcard-tdd |
||
zynq-adrv9364-z7020-bob |
||
zynq-adrv9364-z7020-bob-cmos |
||
zynq-adrv9364-z7020-packrf |
||
zynq-coraz7s |
||
zynq-mini-itx-adv7511 |
ADV7511 (on-board)
|
|
zynq-mini-itx-adv7511-ad9361-fmcomms2-3 |
||
zynq-mini-itx-adv7511-ad9364-fmcomms4 |
ADV7511 (on-board) and the
AD-FMCOMMS4-EBZ board
|
|
zynq-zc702-adv7511 |
ADV7511 (on-board)
|
|
zynq-zc702-adv7511-ad9361-fmcomms2-3 |
||
zynq-zc702-adv7511-ad9361-fmcomms5 |
ADV7511 (on-board) and the
|
|
zynq-zc702-adv7511-ad9364-fmcomms4 |
ADV7511 (on-board) and the
AD-FMCOMMS4-EBZ board
|
|
zynq-zc706-adv7511 |
ADV7511 (on-board)
|
|
zynq-zc706-adv7511-ad6676-fmc |
ADV7511 (on-board) and the
AD6676-FMC-EBZ board
|
|
zynq-zc706-adv7511-ad9265-fmc-125ebz |
ADV7511 (on-board) and the
AD9265-FMC-125EBZ board
|
|
zynq-zc706-adv7511-ad9361-fmcomms2-3 |
||
zynq-zc706-adv7511-ad9361-fmcomms5 |
ADV7511 (on-board) and the
AD-FMCOMMS5-EBZ board
|
|
zynq-zc706-adv7511-ad9361-fmcomms5-ext-lo-adf5355 |
ADV7511 (on-board) and the
AD-FMCOMMS5-EBZ board
|
|
zynq-zc706-adv7511-ad9364-fmcomms4 |
ADV7511 (on-board) and the
AD-FMCOMMS4-EBZ board
|
|
zynq-zc706-adv7511-ad9434-fmc-500ebz |
ADV7511 (on-board) and the
AD9434-FMC-500EBZ board
|
|
zynq-zc706-adv7511-ad9625-fmcadc2 |
ADV7511 (on-board) and the
AD-FMCADC2-EBZ board
|
|
zynq-zc706-adv7511-ad9739a-fmc |
ADV7511 (on-board) and the
|
|
zynq-zc706-adv7511-adrv9371 |
||
zynq-zc706-adv7511-adrv9375 |
||
zynq-zc706-adv7511-fmcadc4 |
ADV7511 (on-board) and the
AD-FMCADC4-EBZ board
|
|
zynq-zc706-adv7511-fmcdaq2 |
ADV7511 (on-board) and the
AD-FMCDAQ2-EBZ board
|
|
zynq-zc706-adv7511-fmcdaq3 |
ADV7511 (on-board) and the
AD-FMCDAQ3-EBZ board
|
|
zynq-zc706-adv7511-fmcjesdadc1 |
ADV7511 (on-board) and the
AD-FMCJESDADC1-EBZ board
|
|
zynq-zc706-imageon |
FMC-IMAGEON
|
|
zynq-zed-adv7511 |
ADV7511 (on-board) |
|
zynq-zed-adv7511-ad9361-fmcomms2-3 |
||
zynq-zed-adv7511-ad9364-fmcomms4 |
ADV7511 (on-board) and the
AD-FMCOMMS4-EBZ board
|
|
zynq-zed-adv7511-ad9467-fmc-250ebz |
ADV7511 (on-board) and the
AD9467-FMC-250EBZ board
|
|
zynq-zed-adv7511-cn0363 |
ADV7511 (on-board) and the
EVAL-CN0363-PMDZ board
|
|
zynq-zed-imageon |
FMC-IMAGEON
|
Building the device tree uses ‘make’ by turning the .dts file to a .dtb. The command is simply ‘make’ plus the device tree name with a .dtb file extension.
~$
make zynq-zc702-adv7511-ad9361.dtb
DTC arch/arm/boot/dts/zynq-zc702-adv7511-ad9361.dtb
Copy the generated files to your SD Card
The output files for building the kernel and device tree are uImage and <device_tree_name>.dtb. Refer to the code below to find their respective output directories. Take note that the device tree file needs to be renamed to devicetree.dtb. See SD Card flashing for more information in configuring the SD card.
~$
cp arch/arm/boot/uImage /media/BOOT/uImage
~$
cp arch/arm/boot/dts/zynq-zc702-adv7511-ad9361.dtb /media/BOOT/devicetree.dtb
On the target platform (devicetrees)
To modify devicetrees on the target platform:
Make sure the boot partition is mounted. On new images, this can be done by right-clicking the boot icon on the desktop and selecting the “Mount Volume” option. The partition will then be mounted at /media/analog/boot.
Convert the compiled devicetree related to the target back into an editable format.
~$
cd /media/analog/boot/zynq-zc702-adv7511
/media/analog/boot/zynq-zc702-adv7511$
dtc -I dtb -O dts -o devicetree.dts devicetree.dtb
Modify the devicetree.dts file as required.
Recompile the devicetree file. Note that this will overwrite the original dtb file, copy or rename the original file if you want to keep it before running this step.
~$
cd /media/analog/boot/zynq-zc702-adv7511
/media/analog/boot/zynq-zc702-adv7511$
dtc -I dts -O dtb -o devicetree.dtb devicetree.dts
Building the ZynqMP / MPSoC Linux kernel and devicetrees from source
Using a script
We provide a script that does automates the build for Zynq using the Linaro toolchain.
Attention
This script differs from the one for Zynq.
The script takes up to 3 parameters, but if left blank, it uses defaults:
<local_kernel_dir> - default is linux-adi if left blank ; use this, if you want to use an already cloned kernel repo
<devicetree_file> - which device tree should be exported/copied from the build. Default is
xilinx/zynqmp-zcu102-rev10-ad9361-fmcomms2-3.dtb
for ZynqMP<path_to_other_toolchain> - in case you have your own preferred toolchain (other than Linaro’s or Xilinx’s) you can use override it with this 3rd param
The script will:
Clone the ADI kernel tree
Download the Linaro GCC toolchain (if no other is specified)
Build the ADI kernel tree
Export/copy the Image file and device tree file out of the kernel build folder
Running the script in one line, with defaults:
~$
wget https://raw.githubusercontent.com/analogdevicesinc/wiki-scripts/main/linux/build_zynqmp_kernel_image.sh && \
chmod +x build_zynqmp_kernel_image.sh && \
./build_zynqmp_kernel_image.sh
Building with Petalinux
Please see here: Building with Petalinux.
On the development host
Make sure you have u-boot-tools
installed, to have the mkimage
utility
available. You can install it via your distro’s package manager.
Then
~$
git clone https://github.com/analogdevicesinc/linux.git \
--no-single-branch --depth=10 \
-- linux
or do a git pull in a existing cloned repository.
The depth
and no-single-branch
options are included to speed up the
cloning by fetching only near the head of each branch/release, you may remove
them to fetch all history, but bear in mind it will go from around 800MB to
around 3.4GB and growing.
Checkout the main development
~$
git checkout main
Already on 'main'
Your branch is up-to-date with 'origin/main'.
Add aarch64-linux-gnu-gcc to PATH
Using the Xilinx toolchain
~$
source $PATH_TO_XILINX/Vitis/$VITIS_VERSION/settings64.sh
~$
which aarch64-linux-gnu-gcc
$PATH_TO_XILINX/Vitis/$VITIS_VERSION/gnu/aarch64/lin/aarch64-linux/bin/aarch64-linux-gnu-gcc
Important
Find the path to the Xilinx installation folder, and then use it to replace this string: $PATH_TO_XILINX that is written above. Same goes for the $VITIS_VERSION, where you choose the Vitis version.
~$
export ARCH=arm64
~$
export CROSS_COMPILE="aarch64-linux-gnu-"
Using the Linaro toolchain
Alternatively, the Linaro toolchain/compiler can be used to compile to kernel. Linaro compilers (that work with ZYNQMP) can be downloaded from here. Always use the latest release just in case.
~$
wget https://releases.linaro.org/components/toolchain/binaries/latest-7/aarch64-linux-gnu/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz
~$
tar -xvf gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz
~$
export ARCH=arm64
~$
export CROSS_COMPILE=$(pwd)/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
Configure the kernel
Inside the repository, generate the configuration file before building the kernel tree.
~$
make adi_zynqmp_defconfig
#
# configuration written to .config
#
Build the kernel via ‘make’. This is the same for all Xlinx ZYNQMP MPSoC FPGAs.
~$
make -j5 Image UIMAGE_LOADADDR=0x8000
CHK include/config/kernel.release
CHK include/generated/uapi/linux/version.h
HOSTCC scripts/basic/fixdep
HOSTCC scripts/basic/bin2c
[ -- snip --]
CC init/version.o
LD init/built-in.o
KSYM .tmp_kallsyms1.o
KSYM .tmp_kallsyms2.o
LD vmlinux
SORTEX vmlinux
SYSMAP System.map
OBJCOPY arch/arm64/boot/Image
Build the devicetree FCMOMMS2/3
Build the one that fits your FPGA carrier and FMC card
device tree |
board |
chip |
---|---|---|
zynqmp-zcu102-rev10-ad9361-fmcomms2-3.dts |
ZCU102 Rev. 1.0 |
AD-FMCOMMS3-EBZ board
|
zynqmp-zcu102-rev10-ad9364-fmcomms4.dts |
ZCU102 Rev. 1.0 |
AD-FMCOMMS4-EBZ board
|
zynqmp-zcu102-revB-ad9361-fmcomms2-3.dts |
ZCU102 Rev.B |
AD-FMCOMMS3-EBZ board
|
zynqmp-zcu102-revB-ad9364-fmcomms4.dts |
ZCU102 Rev.B |
AD-FMCOMMS4-EBZ board
|
The device tree zynqmp-zcu102-revA.dts can also be used for any ZCU102 FPGA that uses an SD card for boot up. Building the device tree uses ‘make’ by turning the .dts file to a .dtb. The command is simply ‘make’ plus the device tree name with a .dtb file extension.
~$
make xilinx/zynqmp-zcu102-rev10-ad9361-fmcomms2-3.dtb
DTC arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev10-ad9361-fmcomms2-3.dtb
Copy the generated files to your SD Card
The output files for building the kernel and device tree are uImage and <device_tree_name>.dtb. Refer to the code below to find their respective output directories. Take note that the device tree file needs to be renamed to devicetree.dtb. See SD Card flashing for more information in configuring the SD card.
~$
cp arch/arm64/boot/Image /media/michael/BOOT/
~$
cp arch/arm64/boot/dts/xilinx/zynqmp-zcu102-revB-ad9361-fmcomms2-3.dtb /media/michael/BOOT/system.dtb
Common Issues
This sections goes through common issues related to the Linux Kernel on the ZynqMP.
DisplayPort - no picture?
The default configuration for most of the projects is to use the HDMI output, and that is what the configuration is set up for.
For DisplayPort projects, you may need to add a custom xorg.conf
file.
printf 'Section "Device"
Identifier "myfb"
Driver "fbdev"
Option "fbdev" "/dev/fb0"
EndSection' > /etc/X11/xorg.conf
After following that, the board should be rebooted.
You can find a list with tested monitors here. Resolution or image problems may appear if there is used a monitor that was not tested.