To build a custom Linux Operating System (OS) tailored specifically for the hardware system we designed in Vivado.
In Step 2, we created the “body” (Hardware). Now we must create the “soul” (Software). We will generate the bootloader (FSBL/U-Boot), the Linux Kernel, and the Root Filesystem, all configured to recognize our custom math_accelerator IP.
This step requires a Linux environment. You cannot do this directly on Windows.
If you have not installed PetaLinux yet, follow these instructions. PetaLinux is notoriously strict about dependencies.
sudo apt update && sudo apt upgrade -y
sudo apt install -y iproute2 gawk python3 python3-pip gcc git tar gzip unzip make net-tools \
libncurses-dev tftpd-hpa zlib1g-dev libssl-dev flex bison libselinux1 gnupg wget diffstat \
chrpath socat xterm autoconf libtool texinfo gcc-multilib build-essential libsdl1.2-dev \
libglib2.0-dev screen pax gzip locales libtool-bin cpio lib32z1 lz4 zstd rsync bc
Troubleshooting tftpd-hpa: If the installation fails with tftpd-hpa package post-installation script subprocess returned error exit status 1, you can safely disable the service:
sudo systemctl disable tftpd-hpa
Note for Debian Users: If you encounter locale errors later, run sudo dpkg-reconfigure locales and ensure en_US.UTF-8 is selected and generated.
Install libtinfo5 (Legacy Dependency):
Xilinx tools depend on libtinfo5. Try installing it via apt first. If that fails (on newer Debian/Ubuntu), perform a manual install.
Option A: Standard Install (Ubuntu 20.04/22.04)
sudo apt install libtinfo5
Option B: Manual Install (Debian 12+ / Ubuntu 23.04+)
# Download the package from the Debian archives
wget http://ftp.us.debian.org/debian/pool/main/n/ncurses/libtinfo5_6.4-4_amd64.deb
# Install it using dpkg
sudo dpkg -i libtinfo5_6.4-4_amd64.deb
# Force /bin/sh to point to bash
sudo ln -sf /bin/bash /bin/sh
# Verify the change (should say /bin/sh -> /bin/bash)
ls -l /bin/sh
sudo mkdir -p /tools/Xilinx/PetaLinux/2025.1
sudo chown -R $USER:$USER /tools/Xilinx
chmod +x ./petalinux-v2025.1-final-installer.run
./petalinux-v2025.1-final-installer.run --dir /tools/Xilinx/PetaLinux/2025.1 --log plnx_install.log
source /tools/Xilinx/PetaLinux/2025.1/settings.sh
(Note: Adjust version number in path if you are using 2024.1)
Check: Run echo $PETALINUX. It should print the installation path.
mkdir -p ~/projects
cd ~/projects
petalinux-create --type project --template zynq --name loopback_os
cd loopback_os
This is the magic step where PetaLinux reads your XSA file and automatically writes the Device Tree (.dts) files for you.
Import XSA:
(Replace ~/Downloads with wherever you saved your XSA file, you can also read this directly from the Windows file system with /mnt/c/ or /mnt/d/ etc.)
petalinux-config --get-hw-description ~/Downloads/system_design_wrapper.xsa
By default, PetaLinux attempts to auto-detect your custom IP. Let’s verify it or manually add it to ensure our C code can find it later.
components/plnx_workspace directory is often empty until the build process starts. Run this specific command to generate the device tree files without waiting for the full OS build:
petalinux-build -c device-tree
components/plnx_workspace/device-tree/device-tree/pl.dtsi.math_accelerator.reg = <0x43c00000 ...>. This confirms PetaLinux knows your IP exists and where it lives.Now we compile the world.
petalinux-build
Troubleshooting: The “ildcard” Makefile Error
If the build fails with syntax error near unexpected token ‘(‘ pointing to ($wildcard *.c) or (ildcard *.c), you have a typo in your custom IP’s Makefile. The term ildcard appears because Make expands $w (which is empty) leaving ildcard.
The Fix:
ip_repo/math_accelerator_1.0/drivers/math_accelerator_v1_0/src/Makefile.LIBSOURCES and OUTS lines (often lines 11-12).LIBSOURCES=$(wildcard *.c)
OUTS = *.o
Critical check: Ensure the $ is outside the parenthesis $(…), not inside ($…).
Troubleshooting: QEMU “struct sched_attr” Error
If the build fails with redefinition of ‘struct sched_attr’, your Debian host headers are conflicting with QEMU’s internal code. This happens on newer Linux distributions.
The Fix:
<PROJECT_DIR> with your path):
nano <PROJECT_DIR>/build/tmp/work/x86_64-linux/qemu-xilinx-native/8.2.7+git/git/linux-user/syscall.c
/usr/include/linux/sched/types.h already defines this, so QEMU doesn’t need to redefine it.The Zynq needs a single file (BOOT.BIN) to start up. This file packages three things:
petalinux-package --boot --fsbl images/linux/zynq_fsbl.elf --fpga images/linux/system.bit --u-boot --force
--fpga flag is critical. Without it, your custom logic won’t be loaded on boot.Since you are running WSL2, you cannot easily format an SD card directly from Linux. We will generate a complete disk image file instead.
petalinux-package --wic --bootfiles "BOOT.BIN image.ub boot.scr" --rootfs-file images/linux/rootfs.tar.gz
ls -lh images/linux/petalinux-sdimage.wic
cp images/linux/petalinux-sdimage.wic /mnt/c/Users/YOUR_USER_NAME/Downloads/
Option B: Direct Access (No Copy Needed): You can access the file directly from Windows using the WSL network path.
\\wsl.localhost\Ubuntu-20.04\home\YOUR_USER\projects\loopback_os\images\linux in the address bar (adjust for your distro/user)..wic file directly from here into BalenaEtcher.ls /sys/bus/platform/devices/
43c00000.math_accelerator (or similar, matching your address). This confirms the hardware and software are talking!Next Step: The final step! We will write a C program on the Zynq to poke address 0x43C00000 and see if our hardware adds 1 to our input.
We have a custom OS running on custom hardware. Now let’s prove we can talk to it.