- PetaLinux provides a kernel, device tree, and rootfs ready for customization on Zynq/ZynqMP.
- The actual workflow combines Vivado (XSA), PetaLinux (image) and Vitis/SDK (app).
- The Device Tree reflects the address and interrupt map defined in Vivado.
- UIO/drivers facilitate access to IP; FPGA Manager streamlines PL iterations.

If you're struggling with PetaLinux, don't worry: you're not alone. steep learning curveBut there's a clear path to understanding how Vivado, PetaLinux, and Vitis work together, and what role each component plays. Here you'll find a practical and organized explanation to help you go from a Vivado design to running your first application in Vitis. Linux over Zynq or Zynq UltraScale+ without dying in the attempt.
Many people wonder if it is possible to "live" alone inside Vitis. You need PetaLinux for kernel, device tree, and rootfs.The typical workflow you'll see on real-world systems is: generate the .xsa file in Vivado, create and configure the PetaLinux project (sometimes from a BSP), compile and package the image (WIC for SD), and then export the sysroot to develop the app in Vitis or with an external toolchain. Later, I'll explain alternatives, tips for avoiding endless rebuilds, and what to do with things like FPGA Manager or TCF Agent.
What is PetaLinux and what does it include by default?
PetaLinux is an AMD reference distribution designed for its SoCs and MPSoCs, providing you with a Linux environment ready for customization. chargers of Boot and optimized kernelIt includes libraries and utilities, C/C++ support, and debugging tools. Additionally, it comes with threading options, FPU support, and a web-based administration server for easy network and firmware configuration.
Official BSPs usually come with pre-made boot and configuration images. deploy and initialize the binaries in hardware real or in QEMUThe complete system emulator that comes with PetaLinux speeds up the initial testing and is ideal for verifying that the project starts up before you delve into the details. apps o drivers.
Recommended hardware-software workflows
In professional environments, two flavors of the Linux workflow are used: one focused on the line of commands from PetaLinux, and another that integrates Vitis for application development. generating the .xsa file and, if applicable, the bitstream.
Can I do everything in Vitis? For Linux, no. Vitis is great for creating platforms When you need a custom kernel, device tree, and rootfs, the usual approach is: PetaLinux to build the system and export the SDK/sysroot; Vitis or an external toolchain to compile and debug your application.
From XSA to the boot system
The minimum viable itinerary usually looks like this: You generate the .xsa file in Vivado.You create the project with petalinux-create (or starting from a BSP), update the hardware in PetaLinux with that .xsa file, and adjust the configuration (kernel, device tree, and rootfs). Then you compile, package it to .wic format, and flash the SD card.
With the system starting up, it's time for the application. export the sysroot/SDK from PetaLinux And in Vitis, you create a platform from the .xsa file. From there, you generate your C/C++ application project pointing to the sysroot to properly link with the rootfs libraries, and you run the app on the target with tcf-agent, gdbserver, or your preferred method.
A little real-life warning: Vivado/Vitis/PetaLinux versions They have their quirks. For example, a problem has been reported in Vitis Unified 2023.2 that prevents connecting to tcf-agent, and the quick fix was to upgrade to 2024.1. Always check the release notes and, if possible, freeze the tool stack during a project.
Hardware design in Vivado (Zynq-7000 and Zynq UltraScale+)
Your technological foundation is in Vivado's Block Design. Add the “ZYNQ7 Processing System” block (or its ZynqMP equivalent) and launch Run Block Automation to wire DRAM and clock. From there, adjust what you need.
- Enable external interrupts: In PS customization, activate PS-PL Interrupts and Shared Interrupts if you plan to share IRQ lines between PL peripherals.
- Synchronize clocks: a common practice is to connect FCLK_CLK0 to the M_AXI_GP0_ACLK port so that the AXI bus clock is consistent with the PS clock.
With PL IPs, rely on automation. Run Connection Automation It provides AXI interconnections and arbitration, but note: it doesn't connect interrupts or all clock trees. For IRQs, it uses a concat block and routes its output to the PS.
- Connect each IRQ line of your peripheral IPs to the Concat block.
- Connect the Concat output to the PS interrupt input.
If you need fast memory in the PL, add BRAM. Inserts BRAM Controller and Block Memory Generator, defines the number of ports, width and capacity and, very importantly, checks its mapping in Address Editor.
- Check and adjust the address map: there cannot be any range overlaps; if there are, Vivado colors the conflict in red.
- Consider other masters (for example, a coprocessor in the PL). Assigning addresses is mandatory to prevent synthesis from failing.
To finalize the design, create the HDL wrapper for the .bd file, synthesize it, and implement it. Bitstream generation It may take quite a while, and when finished it exports the hardware including the bit if you want to program the PL from startup.
Some useful clarifications: Expose PS signals to PL with EMIO For GPIO or I2C, this is very practical if, for example, you're going to use a PYNQ shield. Be careful with integrated peripherals: they're usually wired to fixed pins on the device, and it's not always possible to replace them with fabric IPs without changing connections. If the implementation fails, check restrictions (XDC) and assignments.
Device tree and hardware mapping
The million-dollar question: how far does Linux abstract you? Device Tree This describes device addresses, IRQs, and compatibilities. This mapping is not "dynamic" at boot unless you use overlays; it is normally static and derives from Vivado's Address Editor and the DTS generated by PetaLinux.
The control part (registries) and the data part (e.g., DMA accesses) should be separated conceptually and physically. “reg” ranges and interrupt-linesThe driver (or UIO) will use this information to map memory and interrupt logic. The size and alignment of the ranges must match what you defined in Vivado.
If you compile with PetaLinux, the DTS fragments are usually auto-generated from the .xsa file. update the .xsa When you change the hardware (new IPs or addresses), you must rebuild at least the device tree and kernel. The rootfs file doesn't always need changes, and therefore the sysroot file can still be used if the user libraries haven't been modified.
Options for accessing hardware from C/C++
There is no single way; choose according to the state of your project and the effort you want to dedicate to drivers. / dev / mem for MMIO mapping, but it is not recommended in production due to security, portability, and interruptions.
Intermediate alternative: UIO (Userspace I/O) It allows you to map IP regions in user space and manage interrupts with select/poll. It requires adding the UIO nodes to the Device Tree, but avoids writing a complete driver.
The professional option is to create a character driver or a platform driver for your IP. character driver You gain fine-grained control over DMA, IRQ, power, and a stable interface in /dev, along with improved integration with the kernel ecosystem. If your IP uses AXI-DMA or standard frameworks, rely on existing drivers.
Regarding the toolchain: you can use Vitis or compile with the SDK exported by PetaLinux. petalinux-build –sdk and link your project to that sysroot to ensure you're linking to the same libraries as the target's rootfs. Vitis simplifies building the rig from the .xsa file and launching remote debugging.
Debugging and remote execution
To run the app on the target, you have several options. tcf-agent It works well for launching and debugging from Vitis, provided the agent is installed in the rootfs (add it from petalinux-config -c rootfs) and you don't have a version conflict.
Alternatively, gdbserver It's simple and robust. You copy your binary to the target, run `gdbserver :port ./yourapp`, and connect from the host using the multi-architecture gdb. Many teams combine gdbserver with VS Code Remote or with scripts from Python.
As a way to go beyond printf, check out kernel profiling and tracing techniques. kernel profiling and traces The Zynq community has shared best practices for efficient debugging that will save you time when bugs aren't obvious.
Upgrade hardware without rebuilding everything
It's normal to think that a change in the PL forces us to "remake the world," but there is room for maneuver. interfaces visible to the kernel (addresses, IRQs, compatibility), rootfs and sysroot usually remain active. In that case, you can reprogram the PL and you're good to go.
To load bitstreams hot, Linux offers the FPGA Manager framework. fpgautil or the sysfs/configfs interface to program the PL from user space. This avoids regenerating entire images and speeds up logic iterations.
If the hardware change introduces new IPs or modifies ranges/IRQs, then yes: rebuilds the device tree and regenerates BOOT.BIN/image. Even so, it takes advantage of the sstate cache so that the compilation does not repeat tasks already completed.
Tips to speed up builds and gain stability
The best medicine against "rebuild everything" is cachet and order. State mirror and a directory of downloads Shared for Yocto/PetaLinux; this avoids recompiling packages that haven't changed. This makes a big difference on large systems and in-house environments.
Ensure reproducibility: anchor versions of Vivado/Vitis/PetaLinux And document the patches. If possible, don't change versions mid-project unless it's for a confirmed critical bug. And before jumping to a new version, test it on a branch.
QEMU is your ally. QEMU Boot the image in QEMU to verify that the rootfs and kernel are functioning correctly without flashing the SD card. This doesn't replace the actual hardware, but it saves boot cycles.
After all of the above, the picture no longer seems like a puzzle. complete reference distro (bootloader, kernel, rootfs and tools)Vivado defines the physical map, and Vitis accelerates the app and debugging cycle. From there, leveraging Device Tree, UIO, or drivers makes the difference between a "Hello World" and a robust application that seamlessly utilizes your hardware.
Passionate writer about the world of bytes and technology in general. I love sharing my knowledge through writing, and that's what I'll do on this blog, show you all the most interesting things about gadgets, software, hardware, tech trends, and more. My goal is to help you navigate the digital world in a simple and entertaining way.