Build PYNQ OS for ZCU102 with Yocto

You can still use meta-xilinx-pynq to get the python3-pynq recipe. What I mean is you shouldn’t need to modify it for your board.

Ah okay thanks. When I stopped trying to include pynq-overlays I then got an error complaining that the XRT environment isn’t set up. I see on the PYNQ gitlab that " For Alveo cards, PYNQ currently requires a Xilinx Runtime (XRT) version above or equal to 2.3 to be installed in the system," but is XRT also required for Zynq devices?

You shouldn’t need XRT. If the pynq-overlay recipe isn’t working you may need manually add the xlnk entry to your device-tree - specifically lines 5-7 of this fragment. They can got either under the amba node or directly in the root node.

Peter

After adding the xlnk device tree entry I now get the following (sorry for the long error output):

 >>> import pynq
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.7/site-packages/pynq/__init__.py", line 33, in <module>
from .pl import PL
  File "/usr/lib/python3.7/site-packages/pynq/pl.py", line 39, in <module>
from .ps import CPU_ARCH_IS_SUPPORTED, CPU_ARCH, ZYNQ_ARCH, ZU_ARCH
  File "/usr/lib/python3.7/site-packages/pynq/ps.py", line 322, in <module>
class _ClocksUltrascale(_ClocksMeta):
  File "/usr/lib/python3.7/site-packages/pynq/ps.py", line 382, in _ClocksUltrascale
IOPLL_CTRL = Register(CRL_APB_ADDRESS + IOPLL_CTRL_OFFSET)
  File "/usr/lib/python3.7/site-packages/pynq/registers.py", line 115, in __init__
array = MMIO(address, np.dtype(register_type).itemsize).array
  File "/usr/lib/python3.7/site-packages/pynq/mmio.py", line 82, in __init__
device = Device.active_device
  File "/usr/lib/python3.7/site-packages/pynq/pl_server/device.py", line 95, in active_device
raise RuntimeError("No Devices Found")
RuntimeError: No Devices Found

I took a look at device.py but I’m not sure why the device isn’t being found. What types of devices are expected here?

It’s looking for /dev/xlnk which is the main device used by PYNQ for allocating memory. Can you make sure that CONFIG_XILINX_APF is enabled in your kernel? That and the device-tree fragments should be the only things needed to enable it.

Peter

Hi Peter I think that worked, thanks! It seems like to use the DMA code, you have to load an overlay. In examples it seems like the overlay is a bitfile, but when I tried to load a bitfile I got an error. Is there more code I need to write to define an overlay that I can use with my board? Sorry for the basic questions again.

An Overlay instance also needs the an hwh file to go alongside it. You can find it inside the Vivado project. The hwh file should be named the same as the bitstream - e.g. my_overlay.bit and my_overlay.hwh. If you don’t want to use the hwh file lyou can instead create a Bitstream object but then you won’t have access to any of the PYNQ drivers/discovery as we can’t determine what’s inside the file.

Peter

Hi we did actually include the .hwh file as there was an error asking for it, but we see a problem with the fpga manager, so we will have to keep trying to debug. Thanks again for your help!

[ 659.777637] fpga_manager fpga0: writing AXI_DMA.bin to Xilinx ZynqMP FPGA Manager
[ 659.796087] fpga_manager fpga0: Error while writing image data to FPGA
OSError: [Errno 22] Invalid argument

Have a look in dmesg and you might find more info on what’s gone wrong. The most common reason I’ve seen is a part mismatch so it’s worth double checking the revision of the board being used.

Peter

Hello, we were able to generate a binfile that works with the fpga manager using the vivado shell environment instead of the gui. Is there a way to pass pynq a binfile or does it need the header in the bitfile? At the moment if we just give the binfile we get an error which I think is related to the lack of header:

overlay = Overlay('/home/root/AXI_DMA.bit.bin')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.7/site-packages/pynq/overlay.py", line 344, in __init__
    self.download()
  File "/usr/lib/python3.7/site-packages/pynq/overlay.py", line 403, in download
    super().download(self.parser)
  File "/usr/lib/python3.7/site-packages/pynq/bitstream.py", line 154, in download
    self.device.download(self, parser)
  File "/usr/lib/python3.7/site-packages/pynq/pl_server/device.py", line 617, in download
    _preload_binfile(bitstream)
  File "/usr/lib/python3.7/site-packages/pynq/pl_server/device.py", line 547, in _preload_binfile
    bit_dict = parse_bit_header(bitstream.bitfile_name)
  File "/usr/lib/python3.7/site-packages/pynq/pl_server/device.py", line 513, in parse_bit_header
    contents[offset:offset + length])[0]
struct.error: bad char in struct format

We don’t have a defined way to pass a .bin file to PYNQ. You might be able to hack around it by doing something like

overlay = Overlay('...', download=False)
overlay.binfile_name = "Name of bin file in /lib/firmware"
overlay.download()

One thing you could do is compare the bin file you have that works with the one PYNQ creates in /lib/firmware/ and see what’s different. It’s possible we’re not doing the conversion properly so it would be good to have a test case.

Peter

Hi @PeterOgden with the workaround we were able to load the overlay, but now get an error associated with interrupts:

dma = overlay.axi_dma_0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.7/site-packages/pynq/overlay.py", line 356, in __getattr__
    return getattr(self._ip_map, key)
  File "/usr/lib/python3.7/site-packages/pynq/overlay.py", line 861, in __getattr__
    driver = ipdescription['driver'](ipdescription)
  File "/usr/lib/python3.7/site-packages/pynq/lib/dma.py", line 190, in __init__
    super().__init__(description=description)
  File "/usr/lib/python3.7/site-packages/pynq/overlay.py", line 649, in __init__
    setattr(self, interrupt, Interrupt(details['fullpath']))
  File "/usr/lib/python3.7/site-packages/pynq/interrupt.py", line 98, in __init__
    _InterruptController.get_controller(parentname))
  File "/usr/lib/python3.7/site-packages/pynq/interrupt.py", line 159, in get_controller
    ret = _InterruptController(name)
  File "/usr/lib/python3.7/site-packages/pynq/interrupt.py", line 191, in __init__
    'for IRQ number {}'.format(number))
ValueError: Could not find UIO device for interrupt pin for IRQ number 0

I found this post: ValueError: Could not find UIO device for interrupt pin for IRQ number 0 which is very similar to our problem. I do have the proper entry in the device tree, but is there a way to check if the interrupt is binding to another entry first, or that I have the correct UIO device drivers compiled into the kernel? Thanks!

To clarify, the device tree has this fragment included, but nothing like the one here:

uio_0: uio_int0@0{
            compatible="generic-uio";
            status="okay";
            interrupt-controller;
            interrupt-parent=<&intc>;
            interrupts=<0x0 0x1d 0x4>;
};

Does the UIO device appear in /proc/interrupts?

Hi @PeterOgden it looks like no it does not

This most like means that the UIO driver isn’t configured to bind to the device. There are a couple of ways to do this. Easiest way is to add uio_pdrv_genirq.of_id=generic-uio to the kernel command line. If the UIO device is compiled as a module you can also add a file containing options uio_pdrv_genirq of_id=generic-uio to /etc/modprobe.d and then modprobe uio_pdrv_genirq.

Peter

Hmm ok it seems we have a weird situation. From this recipe the proper file is being added to /etc/modprobe.d and we can go look at it, but modprobe complains about no file found in /lib/modules/5.4.0-xilinx-v2020.2 when we try to run modprobe uio_pdrv_genirq

Is CONFIG_UIO_PDRV_GENIRQ=m in you kernel config?

Hi @PeterOgden sorry for the long delay. There was something in my build that was overriding my settings and it took be awhile to figure out what the problem was, and to try another test on the board.
After getting the UIO module squared away, we also had to modify our firmware to use an Interrupt Controller as discussed here: Zynq PS7 Interrupts - #5 by PeterOgden but now unfortunately we get a parse error when just defining the overlay. Do you have any ideas on why that might be? I’ve attached our block design also if that’s helpful. Thanks!

AXI_DMA.pdf (189.7 KB)

>>> overlay = Overlay('/home/root/AXI_DMA.bit', download=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.7/site-packages/pynq/overlay.py", line 330, in __init__
    self.parser = self.device.get_bitfile_metadata(self.bitfile_name)
  File "/usr/lib/python3.7/site-packages/pynq/pl_server/device.py", line 637, in get_bitfile_metadata
    return HWH(hwh_path)
  File "/usr/lib/python3.7/site-packages/pynq/pl_server/hwh_parser.py", line 149, in __init__
    tree = ElementTree.parse(hwh_name)
  File "/usr/lib/python3.7/xml/etree/ElementTree.py", line 1197, in parse
    tree.parse(source, parser)
  File "/usr/lib/python3.7/xml/etree/ElementTree.py", line 598, in parse
    self._root = parser._parse_whole(source)
xml.etree.ElementTree.ParseError: not well-formed (invalid token): line 1, column 0

Hi @PeterOgden @easmith5 ,
I am trying to run my program only with yocto and I am very new to it. I have added meta-xilinx-pynq layer to the yocto image. It started on the board. Whenever I try to import pynq it shows the no device found error as stated by Emily.

CONFIG_XILINX_APF is enabled in your kernel?

For enabling, where to add it?