I've been using PYNQ on the PYNQ-Z2 and Ultra96v2 boards and I thought that it could prove useful for evaluating and prototyping with the UZ7EV. Unfortunately there isn't a prebuilt PYNQ image for this board yet. The good news is that Peter Ogden of Xilinx made a couple of posts that document how to get PYNQ working with unsupported boards.
There are two approaches described:
- Port PYNQ using a board agnostic rootfs image combined with the correct BSP for your board: quick-porting-of-pynq-using-pre-built-images
- Install the PYNQ Python libraries in the PetaLinux rootfs: deploying-pynq-and-jupyter-with-petalinux
There are tradeoffs between the two approaches.
Port PYNQ
This approach provides the PYNQ environment that I'm familiar with - an Ubuntu based Linux system. On the PYNQ development site PYNQ - Python productivity for Zynq - Board , I only see aarch64 and arm rootfs images for v2.5. That seems to suggest that I should use the 2019.1 XIlinx tools.
Steps to try out this method:
- Find an appropriate BSP for the UZ7EV SOM + Carrier Card
- Download the PYNQ rootfs aarch64 v2.5 image
- Build and package a bootable image using PetaLinux
- Test it on the UZ7EV
- Build a BSP that includes the VCU (the available BSPs are pretty minimal in terms of the IP used)
- Add VCU drivers and software in the PetaLinux config
- Redo steps 2-4
Install the PYNQ Python libraries
This approach uses the PetaLinux rootfs and has a smaller footprint but I'm not currently concerned with that. The one advantage that it may provide is I might be able to use it with the 2019.2 tools as the post suggests. I'll need to check if the PetaLinux recipe has been updated to use PYNQ v2.5. One of my development options is to use Vitis which will require me to move to the 2019.2 tools. I don't have a clear idea what the limitations of this approach would be relative to the Ubuntu rootfs. My concern would be that some tools may not function properly or function differently. I presume that the overlay bitfiles would want to be generated using Vivado 2019.2. I know there was some issue with PYNQ version compatibility with tool versions but maybe that was a function of something in the rootfs or has been fixed.
Steps to try out this method: (there is a lot more detail in Peter's post - setting up to create and build the recipe is somewhat involved)
- Find an appropriate BSP for the UZ7EV SOM + Carrier Card
- Create a recipe for the design to be added
- Configure the kernel and roofs
- Build and package a bootable image using PetaLinux
- Test it on the UZ7EV
I've decided to try doing the port first as it seems more robust and I'm familiar with that environment. I may try this second method if I decide that I want/need to use Vitis.
Porting PYNQ to UZ7EV
- Download PetaLinux BSP (uz7ev_evcc_2019_1.bsp): UZEVEVCC_PLNX_BSP
- Download PYNQ rootfs aarch64 v2.5 image (bionic.aarch64.2.5.img): http://bit.ly/2IwiiWO
- Clone Xilinx/PYNQ respository from github: git clone https://github.com/Xilinx/PYNQ.git
- Run script to create image from prebuilt
- cd PYNQ/sdbuild
- bash scripts/image_from_prebuilt.sh UZ7EV uz7ev_evcc_2019_1.bsp aarch64 bionic.aarch64.2.5.img
- error - /bin/bash: mkimage: command not found
- apt-get install u-boot-tools
- cd PYNQ/sdbuild/output/boot/UZ7EV && mkimage -f PYNQ/sdbuild/build/UZ7EV/image.its PYNQ/sdbuild/output/boot/UZ7EV/image.ub
- error - sh: dtc: command not found
- apt-get install device-tree-compiler
- Write image to SD card using Win32DiskImager
- Image - PYNQ/sdbuild/output/UZ7EV-2.5.img
So, the build process was straightforward other than having to install the mkimage and dtc tools.
However, when I went to boot I experienced a "kernel panic".
It turns out that the kernel is trying to locate the rootfs on /dev/mmcblk0p2, but the root partition on my SD card is /dev/mmcblk1p2.
To verify this was my problem:
- I stopped the boot process at the point that U-Boot says "Hit any key to stop autoboot"
- Changed bootargs in the terminal - setenv bootargs 'earlycon clk_ignore_unused root=/dev/mmcblk1p2 rw rootwait'
- Continued U-Boot - boot
- Now booting completed successfully
I thought that this would be an easy fix - In my PetaLinux project I modified the device tree file "system-user.dtsi" to set the correct root partition.
I rebuilt the image, wrote the SD card and booted -> boot still FAILED the same way.
I was perplexed but luckily Peter Ogden was able to help me. PYNQ has a meta-layer that can override PetaLinux settings. This located at PYNQ/sdbuild/boot/meta-pynq.
I edited the device tree file "pynq_bootargs.dtsi" and now my boot problem is fixed. I would never have thought to look in the boot directory for that PYNQ meta layer.
But nothing is easy when you don't have a proven process.
I now booted successfully but the jupyter service would load but would intermittently fail to start. I quickly realized that my root partition was almost full and it was causing all kinds of system issues. I would need to resize the root partition.
It turns out that I needed to customize the image to add ethernet (second part of Peter's post) and I discovered that there was a resizefs package that I could add at the same time to fix my root partition size issue.
Customize the image
To build a custom image requires four steps:
- Create a board repository - "test_repo"
- Create a board subdirectory - "UZ7EV"
- Create a board spec file that describes the base board and the packages being added - "UZ7EV.spec"
- Execute the build - make BOARDDIR=test_repo PREBUILT=bionic.aarch64.2.5.img nocheck_images
Here's the contents of UZ7EV.spec:
ARCH_UZ7EV = aarch64
BSP_UZ7EV = uz7ev_evcc_2019_1.bsp
STAGE4_PACKAGES_UZ7EV = ethernet resizefs
The image shows up in the "output" folder as previously.
Now PYNQ boots and jupyter starts consistently and I can connect over the network.
Testing PYNQ with the uz7ev_evcc_oob design
Avnet has an hdl repository that provides the TCL scripts that are needed to build the OOB and reference designs for their boards. Tom Curran wrote a blog post describing it: Avnet HDL git HOWTO (Vivado 2020.1 and earlier)
I am using the uz7ev_evcc_oob design to build an overlay to test the PYNQ installation.
The design is pretty basic:
Just some AXI GPIO configured to interface with the user push buttons, dip switches, and LEDs. The only modification I made to the design was renaming the AXI GPIO to make them easier to reference.
I haven't figured out why, but the board definition apparently has only 3 push button switches even though the carrier board actually has 4. For some reason SW1 is missing.
I used the .bit, .hwh, and .tcl files that Vivado generated and created an overlay that I named "uz7ev_oob".
Installed the overlay in the pynq/overlays directory on the UZ7EV board. And created a simple Jupyter notebook.
Unfortunately, I got a null key error when trying to access the GPIO. The error seems to be associated with the Interrupt Controller.
Interestingly enough, the design does not have an interrupt controller but routes the interrupts back to the PS through an xlconcat element.
Seemed that the only quick thing to try is to add an interrupt controller so that interrupt.py can find it (I didn't want to mess with the pynq code).
Here is the modified design:
And now everything is happy.
A quick demo (setting LEDs and reading push buttons - the dip switches are hard to set for the video - I have tested them):
Next post I will port and test the VCU TRD with PYNQ. I will need to migrate the 2018.3 design to 2019.1 and I'll need to figure out how to add the required software and drivers to the PetaLinux config.
Links to previous posts for this roadtest: