# Deploying PYNQ and Jupyter with Petalinux

**URL:** https://discuss.pynq.io/t/deploying-pynq-and-jupyter-with-petalinux/677
**Category:** Learn
**Created:** [November 18, 2019, 10:24am UTC](https://discuss.pynq.io/t/deploying-pynq-and-jupyter-with-petalinux/677 "2019-11-18T10:24:12Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![PeterOgden](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.pynq.io/peterogden/32/55_2.png) [@PeterOgden](https://discuss.pynq.io/u/PeterOgden)
#### Post date: [November 18, 2019, 10:24am UTC](https://discuss.pynq.io/t/deploying-pynq-and-jupyter-with-petalinux/677/1 "2019-11-18T10:24:12Z")

</div>

![petalinux_blog_header](https://us1.discourse-cdn.com/flex019/uploads/pynq1/original/1X/4f6b5bd145967078fe02bf4680c0efdbeb4c0745.png)

The PYNQ Ubuntu-based Linux system is designed for development but we have been getting an increasing number of questions about how PYNQ can be used in a more traditional embedded context where an 8 GB filesystem is not practical. At its heart PYNQ is a Python library with a set of drivers and overlays that do not need a fully-fledge desktop Linux system to run. To this end we have been working to include PYNQ as part of Petalinux with the 2019.2 release now including PYNQ version 2.4.

In this post I’ll run through creating a new Petalinux project targeting the ZCU104, configuring it to work with PYNQ and finally adding a design that uses PYNQ as a new recipe. For this walkthrough I will assume that you already have Petalinux installed and on the PATH but no additional tools will be required.

## Creating the initial image

Fortunately the ZCU104 already has a publically available BSP available for [download](https://www.xilinx.com/member/forms/download/xef.html?filename=xilinx-zcu104-v2019.2-final.bsp). With this file we can start by creating the reference project

```bash
> petalinux-create -t project -s xilinx-zcu104-v2019.2-final.bsp

```

Once the project is created we can enter the project directory to continue setting it up for PYNQ

```bash
> cd xilinx-zcu104-2019.2

```

One change we need to make to the project configuration is enabling the FPGA manager. This will prevent the default bitstream from being loaded at boot and loading all of the Linux kernel drivers for the pre-packaged design. Without this option reprogramming the bitstream after boot has the potential to crash the kernel as devices that Linux expects to see are no longer in the prgorammable logic.

To do this we us the `petalinux-config` command and look for the desired option.

```bash
> petalinux-config

```

 ![set_fpga_manager](https://us1.discourse-cdn.com/flex019/uploads/pynq1/original/1X/ce1a3d2d1677dfad8f70acc1b8693a082a5526c9.gif)

We also need to add the required kernel driver (`CONFIG_XILINX_APF`) into the kernel. Again we can use the petalinux-config tool to perform the configuration

```bash
> petalinux-config -c kernel

```

 ![set_apf](https://us1.discourse-cdn.com/flex019/uploads/pynq1/original/1X/774041439e52d3fee3db201aad0dda60cb7968d4.gif)

## Creating a recipe for PYNQ-Helloworld

Next we need to create a recipe for the design we want to add. I’m going use the PYNQ-HelloWorld example as it supports the ZCU104 and is the recommended starting point for other PYNQ projects providing an image-resizer hardware design and accompanying Python code.

Petalinux is based on the Yocto Project which is a system for creating embedded Linux distributions. It uses the _bitbake_ build system for building _recipes_. Recipes are organised into _layers_. You can see that the Petalinux project that has been created contains two layers in the `project_spec` folder – namely `meta-user` where we should put new recipes and `meta-plnx-generated` which is where Petalinux will place any recipes it generates as part of its configuration process.

To create our recipe first we need to create a new directory to contain all of the files we need – `project-spec/meta-user/recipes-apps` seems tailor made for this.

```bash
> mkdir project-spec/meta-user/recipes-apps/python3-pynq-helloworld
> cd project-spec/meta-user/recipes-apps/python3-pynq-helloworld

```

The name of project is import as having the `python3-` prefix will help the build system use the correct version of Python when building the package.

Next we need a `.bb` file which contains the main recipe for the package. This should be named in accordance with the folder we’ve just created.

```bash
> vim python3-pynq-helloworld.bb

```

A recipe contains several sections that required. First we need to specify the license of the package and where the license is specified in the tarball along with the user-visible summary of the package.

```bitbake
SUMMARY = "PYNQ Helloworld"
LICENSE = "BSD"

LIC_FILES_CHKSUM = "file://LICENSE;md5=f9990fcc34ccf1f82ccf1bc5a1cc3bfc"

```

Next we have where the package can be obtained. In this case we are going to pull directly from the Xilinx github repository. We also need to tell bitbake where the root of the project is in the `S` variable. For anything fetched with git this will be the `git` subdirectory. Note that Yocto will check the checksums of the package files to ensure that nothing has changed since we created the recipe. This is part of its strategy for ensuring that builds are repeatable.

```make
SRC_URI = "git://github.com/Xilinx/PYNQ-HelloWorld.git;protocol=https"

SRC_URI[md5sum] = "ac1bfe94a18301b26ae5110ea26ca596"
SRC_URI[sha256sum] = "f522c54c9418d1b1fdb6098cd7139439d47b041900000812c51200482d423460"

SRCREV = "0e10a7ee06c3e7d873f4468e06e523e2d58d07f8"
S = "${WORKDIR}/git"

```

Next we have the actual build portion. Luckily for us there are already bitbake recipes for projects that use setuptools and PYNQ so all we need to is inherit from the correct recipes.

```make
inherit xilinx-pynq setuptools3

```

The `xilinx-pynq` class will create a `PYNQ_NOTEBOOK_DIR` variable that will be packaged up into the `notebooks` sub-package but we are still required to ensure that the environment is correct for the recipe to run correctly. In this case we need to set the `PYNQ_JUPYTER_NOTEBOOKS` and `BOARD` environment variables. setup.py also expects that the notebook directory exists so we need to create it. For this we can _prepend_ instructions to the various steps of the build

```make
do_compile_prepend() {
  export BOARD=ZCU104
  export PYNQ_JUPYTER_NOTEBOOKS=${D}${PYNQ_NOTEBOOK_DIR}
}

do_install_prepend() {
  export BOARD=ZCU104
  export PYNQ_JUPYTER_NOTEBOOKS=${D}${PYNQ_NOTEBOOK_DIR}
  install -d ${PYNQ_JUPYTER_NOTEBOOKS}
}

do_configure_prepend() {
  export BOARD=ZCU104
  export PYNQ_JUPYTER_NOTEBOOKS=${D}${PYNQ_NOTEBOOK_DIR}
  install -d ${PYNQ_JUPYTER_NOTEBOOKS}
}

```

Finally we need to specify our dependencies. We’ll make the core package only depend on PYNQ and the other core libraries we need and the notebooks package also depend on Jupyter. Note the `${PN}` in these recipes is a short-hand for the current package name and `RDEPENDS` means _runtime_ dependencies. Note that we include need to include the `python3-audio` and `pynq-overlay` dependencies to ensure that all of the feature of PYNQ used by the helloworld application work correctly.

```make
RDEPENDS_${PN} += "\
        python3-pynq \
        python3-audio \
        python3-pillow \
        pynq-overlay \
        libstdc++ \
        "

RDEPENDS_${PN}-notebooks += "\
        python3-jupyter \
"

```

Now we have our completed recipe we can try and build it

```bash
> petalinux-build -c python3-pynq-helloworld

```

Which produces an error:

 ![build_error](https://us1.discourse-cdn.com/flex019/uploads/pynq1/original/1X/921aadd4d146aa903d16c807314cbbe0096e380b.png)

Which appears to be caused by a format string (`f''`) in the package’s `setup.py` which isn’t supported in the version of Python being used to perform the installation. To fix this we need to create a patch that replaces the format string with a plain addition. Looking more thoroughly at the notebooks we also see that the locations that the notebooks are installed will also need to change. Fixing both of those results in the following patch

```diff
diff --git a/setup.py b/setup.py
index 708dc25..21595f1 100644
--- a/setup.py
+++ b/setup.py
@@ -34,13 +34,13 @@ import shutil

 # global variables
 board = os.environ['BOARD']
-repo_board_folder = f'boards/{board}/resizer'
+repo_board_folder = 'boards/'+board+'/resizer'
 board_notebooks_dir = os.environ['PYNQ_JUPYTER_NOTEBOOKS']
 hw_data_files = []

 # check whether board is supported
 def check_env():
     if not os.path.isdir(repo_board_folder):
         raise ValueError("Board {} is not supported.".format(board))
     if not os.path.isdir(board_notebooks_dir):
-- 
diff --git a/boards/ZCU104/resizer/notebooks/resizer_PL.ipynb b/boards/ZCU104/resizer/notebooks/resizer_PL.ipynb
index 1658d78..cd04d93 100644
--- a/boards/ZCU104/resizer/notebooks/resizer_PL.ipynb
+++ b/boards/ZCU104/resizer/notebooks/resizer_PL.ipynb
@@ -78,7 +78,7 @@
    "outputs": [],
    "source": [
     "resize_design = Overlay(\n",
- " \"/usr/local/lib/python3.6/dist-packages/helloworld/bitstream/resizer.bit\")"
+ " \"/usr/lib/python3.5/site-packages/helloworld/bitstream/resizer.bit\")"
    ]
   },
   {
--

```

For Yocto to find the patch we need to place it another sub-folder also named according to the recipe name

```bash
> mkdir python3-pynq-helloworld
> cp $patch_file python3-pynq-helloworld/build-fixes.patch

```

We also need to update the `SRC_URI` entry in the .bb file to include our new patch

```make
SRC_URI = "git://github.com/Xilinx/PYNQ-HelloWorld.git;protocol=https \
    file://build-fixes.patch \
"

```

Now our build completes succesfully

## Adding the image to the filesystem

To add our new packages to the root filesystem we need to let Petalinux know of their existance. One way to do this is to add them to the user-rootfsconfig

```bash
> cd ../../
> vim conf/user-rootfsconfig

```

and add a line for each new package – the core and notebooks package for our new recipe in this case.

```make
CONFIG_python3-pynq-helloworld
CONFIG_python3-pynq-helloworld-notebooks

```

Now we can run the Petalinux root filesystem configuration and select our two new packages

```bash
> petalinux-config -c rootfs

```

 ![add_packages](https://us1.discourse-cdn.com/flex019/uploads/pynq1/original/1X/6c2b5549e6be54758a288b1b206d3b4be2966b74.gif)

## Building and testing

With everything set up we can now build the complete image

```bash
> petalinux-build

```

This will take a while and once it has completed our Linux image will be in `images/linux`. For this example we will just use the `image.ub` file which contains the kernel and root filesystem all packaged together. We will also need to generate a `BOOT.BIN` file to perform the initial board set-up. In order for Linux to run our BOOT.BIN needs to contain u-boot, the arm trusted firmware and the platform management firmware in addition to the main bootloader

```bash
> petalinux-package --boot --u-boot --atf --pmufw

```

To test on the board we copy the `BOOT.bin` and `image.ub` files from `images/linux` directory and boot the board.

Once the board is booted and Ethernet is configured you can go into the notebooks directory and start Jupyter

```bash
> cd /usr/share/notebooks
> jupyter notebook --ip=0.0.0.0 --no-browser --allow-root

```

Jupyter will start and give you an address to access the server in the terminal

 ![jupyter_terminal](https://us1.discourse-cdn.com/flex019/uploads/pynq1/original/1X/5f9299fc9a559c9567dfde38e134a7079e3085e5.png)

Jupyter can now be interacted with the same as with the off-the-shelf PYNQ image.

 ![jupyter](https://us1.discourse-cdn.com/flex019/uploads/pynq1/original/1X/14b55629b140c0a83b27115f752889a59c84df4b.gif)

## Further reading

This has only been a very brief introduction to Petalinux and the creation of Yocto recipes. For a more in-depth exploration I recommend looking through the Yocto user-guide which contains much more detail on the steps that are invoked when running a bitbake recipe. The Petalinux documentation provides more details on how to build and run embedded Linux images. If you want to look through the code behind this have a look at:

- [meta-xilinx](https://github.com/Xilinx/meta-xilinx/tree/rel-v2019.2) which contains the PYNQ recipes
- [meta-jupyter](https://github.com/Xilinx/meta-jupyter/tree/rel-v2019.2) which is a Xilinx fork containing updated Jupyter recipes for Jupyter
- The example shown here is available as a [GIST](https://gist.github.com/PeterOgden/5a02912a2d1b997ba46df8fd8fd5b23e)

If you have more questions or want to discuss further feel free to comment below or elsewhere in our forum.

---

<div class="post-metadata">

### Author: ![ggillett](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.pynq.io/ggillett/32/953_2.png) [@ggillett](https://discuss.pynq.io/u/ggillett)
#### Post date: [September 9, 2020, 7:37pm UTC](https://discuss.pynq.io/t/deploying-pynq-and-jupyter-with-petalinux/677/2 "2020-09-09T19:37:05Z")

</div>

Hi,

I found this post really useful, thanks Peter. I’ve used the information here to create a PetaLinux (2019.2) image for a custom board. But it appears that PYNQ is not installed correctly.

I can bring up the jupyter notebook server but there is a problem with pynq.lib

```
In[1]: from pynq import Overlay

---------------------------------------------------------------------------
ImportError Traceback (most recent call last)
<ipython-input-1-1b95ad83cc55> in <module>
----> 1 from pynq import Overlay

/usr/lib/python3.5/site-packages/pynq/ __init__.py in <module>
     45 from .pmbus import get_rails
     46 from .pmbus import DataRecorder
---> 47 from . import lib
     48 
     49 

/usr/lib/python3.5/site-packages/pynq/lib/ __init__.py in <module>
     72 from .logictools import FSMGenerator
     73 
---> 74 from . import video
     75 from . import audio
     76 from . import dma

/usr/lib/python3.5/site-packages/pynq/lib/video/ __init__.py in <module>
     39 
     40 if pynq.ps.CPU_ARCH == pynq.ps.ZYNQ_ARCH:
---> 41 from . import dvi
     42 elif pynq.ps.CPU_ARCH == pynq.ps.ZU_ARCH:
     43 from . import xilinx_hdmi

/usr/lib/python3.5/site-packages/pynq/lib/video/dvi.py in <module>
     39 
     40 if CPU_ARCH == ZYNQ_ARCH:
---> 41 import pynq.lib._video
     42 else:
     43 warnings.warn("DVI/HDMI subsystem only supported on Zynq-7000",

ImportError: No module named 'pynq.lib._video'

```

What have I missed? I don’t have a bitfile loaded, but the board has no video in any case.  
Any advice appreciated.

---

<div class="post-metadata">

### Author: ![bartokon](https://avatars.discourse-cdn.com/v4/letter/b/8edcca/32.png) [@bartokon](https://discuss.pynq.io/u/bartokon)
#### Post date: [September 9, 2020, 9:49pm UTC](https://discuss.pynq.io/t/deploying-pynq-and-jupyter-with-petalinux/677/3 "2020-09-09T21:49:42Z")

</div>

I had the same issue

> [@Installing pynq via petalinux](https://discuss.pynq.io/t/installing-pynq-via-petalinux/1565/6):
>
> The start\_pl\_server.py script is designed to run forever - hence why we aim to start it at boot. If you run it in the background with start\_pl\_server.py & Does that make the core PYNQ library function correctly?

You could just remove this part from the library.

---

<div class="post-metadata">

### Author: ![ggillett](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.pynq.io/ggillett/32/953_2.png) [@ggillett](https://discuss.pynq.io/u/ggillett)
#### Post date: [September 10, 2020, 1:15pm UTC](https://discuss.pynq.io/t/deploying-pynq-and-jupyter-with-petalinux/677/4 "2020-09-10T13:15:45Z")

</div>

Thanks bartoken,

The result of launching that is basically the same

```
root@pynqpitaya:~# Traceback (most recent call last):
  File "/usr/bin/start_pl_server.py", line 11, in <module>
    load_entry_point('pynq==2.4', 'console_scripts', 'start_pl_server.py')()
  File "/usr/lib/python3.5/site-packages/pkg_resources/ __init__.py", line 479, in load_entry_point
    return get_distribution(dist).load_entry_point(group, name)
  File "/usr/lib/python3.5/site-packages/pkg_resources/ __init__.py", line 2703, in load_entry_point
    return ep.load()
  File "/usr/lib/python3.5/site-packages/pkg_resources/ __init__.py", line 2321, in load
    return self.resolve()
  File "/usr/lib/python3.5/site-packages/pkg_resources/ __init__.py", line 2327, in resolve
    module = __import__ (self.module_name, fromlist=[' __name__'], level=0)
  File "/usr/lib/python3.5/site-packages/pynq/ __init__.py", line 47, in <module>
    from . import lib
  File "/usr/lib/python3.5/site-packages/pynq/lib/ __init__.py", line 74, in <module>
    from . import video
  File "/usr/lib/python3.5/site-packages/pynq/lib/video/ __init__.py", line 41, in <module>
    from . import dvi
  File "/usr/lib/python3.5/site-packages/pynq/lib/video/dvi.py", line 41, in <module>
    import pynq.lib._video
ImportError: No module named 'pynq.lib._video'

```

Thanks I may remove that from the library but I’d prefer a less intrusive fix where I don’t have to maintain a patch as PYNQ evolves. Presumably my problem is with pynq.lib, video is just the first in the import list.

Any other advice?

---

<div class="post-metadata">

### Author: ![PeterOgden](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.pynq.io/peterogden/32/55_2.png) [@PeterOgden](https://discuss.pynq.io/u/PeterOgden)
#### Post date: [September 10, 2020, 1:39pm UTC](https://discuss.pynq.io/t/deploying-pynq-and-jupyter-with-petalinux/677/5 "2020-09-10T13:39:29Z")

</div>

Is your board Zynq-7000 or Zynq Ultrascale+ based? Judging by the libraries it’s loading I’m guessing Zynq-7000.

There was an omission in the recipe for PYNQ on that architecture which we’ve fixed in 2020.1. Easiest thing to do is to add `do_compile_prepend` and `do_install_prepend` scripts to the recipe to set `PYNQ_BUILD_ARCH=armv7l`. We’ve done this in the pynq bbclass for 2020.1 [here](https://github.com/Xilinx/meta-xilinx/blob/rel-v2020.1/meta-xilinx-pynq/classes/xilinx-pynq.bbclass) along with some steps in this post which had to be done manually in the past.

Peter

---

<div class="post-metadata">

### Author: ![ggillett](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.pynq.io/ggillett/32/953_2.png) [@ggillett](https://discuss.pynq.io/u/ggillett)
#### Post date: [September 10, 2020, 2:28pm UTC](https://discuss.pynq.io/t/deploying-pynq-and-jupyter-with-petalinux/677/6 "2020-09-10T14:28:49Z")

</div>

Yes it’s zynq-7000, Thanks that all makes sense, any eta on 2020.1 release?

---

<div class="post-metadata">

### Author: ![ggillett](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.pynq.io/ggillett/32/953_2.png) [@ggillett](https://discuss.pynq.io/u/ggillett)
#### Post date: [September 10, 2020, 2:47pm UTC](https://discuss.pynq.io/t/deploying-pynq-and-jupyter-with-petalinux/677/7 "2020-09-10T14:47:13Z")

</div>

Or does this petalinux flow already work with 2020.1?

---

<div class="post-metadata">

### Author: ![PeterOgden](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.pynq.io/peterogden/32/55_2.png) [@PeterOgden](https://discuss.pynq.io/u/PeterOgden)
#### Post date: [September 10, 2020, 3:08pm UTC](https://discuss.pynq.io/t/deploying-pynq-and-jupyter-with-petalinux/677/8 "2020-09-10T15:08:49Z")

</div>

This flow should work with Petalinux 2020.1 with the execption that the various `prepend` parts of the recipe should not be needed any longer. I’ll update the guide when I get some free time.

Peter

---

<div class="post-metadata">

### Author: ![ggillett](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.pynq.io/ggillett/32/953_2.png) [@ggillett](https://discuss.pynq.io/u/ggillett)
#### Post date: [September 11, 2020, 12:48pm UTC](https://discuss.pynq.io/t/deploying-pynq-and-jupyter-with-petalinux/677/9 "2020-09-11T12:48:43Z")

</div>

Thanks Peter, I have PYNQ up now using 2020.1

---

<div class="post-metadata">

### Author: ![bartokon](https://avatars.discourse-cdn.com/v4/letter/b/8edcca/32.png) [@bartokon](https://discuss.pynq.io/u/bartokon)
#### Post date: [September 12, 2020, 9:01am UTC](https://discuss.pynq.io/t/deploying-pynq-and-jupyter-with-petalinux/677/10 "2020-09-12T09:01:08Z")

</div>

Hey, I just have creted PYNQ with petalinux 2020.1, but I have one question.  
I’m using  
ol = Overlay(“something.xclbin”), but then ![Screenshot from 2020-09-12 10-58-45](https://us1.discourse-cdn.com/flex019/uploads/pynq1/original/2X/c/c886596210da5109445bd3a583227c9c4c92aa79.png)  
I know this problem. The BOOT.bin programs old FPGA bitstream without accelerator, xrt tries to program non-existing accelerator and system freezes.  
The question is why PYNQ isn’t reprogramming FPGA, if I’m creating new overlay? Shouldn’t it program vaad.bit or something and then program accelerator?

---

<div class="post-metadata">

### Author: ![windofage](https://avatars.discourse-cdn.com/v4/letter/w/c6cbf5/32.png) [@windofage](https://discuss.pynq.io/u/windofage)
#### Post date: [October 31, 2022, 3:06am UTC](https://discuss.pynq.io/t/deploying-pynq-and-jupyter-with-petalinux/677/11 "2022-10-31T03:06:19Z")

</div>

Hi, I’m trying to build a petalinux 2020.2 project with PYNQ targeting ZCU102. I have successfully built PYNQ image for ZCU102 by modifying the .spec file. But I can’t find the .spec file in the petalinux project.

It seems that simply modifying the .bb file (ZCU104-\>ZCU102) is not working. “ValueError: Board is not supported.” error message appears when compiling the pynq3-pynq-helloworld app. Please give me some advice.

---

<div class="post-metadata">

### Author: ![windofage](https://avatars.discourse-cdn.com/v4/letter/w/c6cbf5/32.png) [@windofage](https://discuss.pynq.io/u/windofage)
#### Post date: [February 10, 2023, 7:59am UTC](https://discuss.pynq.io/t/deploying-pynq-and-jupyter-with-petalinux/677/12 "2023-02-10T07:59:11Z")

</div>

I followed this flow with petalinux 2020.2, and it works. But it failed in 2022.2. Does anyone have successful experience in building it on 2022.2?

---

<div class="post-metadata">

### Author: ![heche](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.pynq.io/heche/32/5743_2.png) [@heche](https://discuss.pynq.io/u/heche)
#### Post date: [March 21, 2024, 3:01pm UTC](https://discuss.pynq.io/t/deploying-pynq-and-jupyter-with-petalinux/677/14 "2024-03-21T15:01:44Z")

</div>

hi, do you solve your problem?
