Zedboard – Setting up a ARM development environment in Linux

Well now that you have your Zedboard up and running with Petalinux installed, and your network is configured to talk to the outside world, let’s get some code running on this thing!

First some environmental comments. I am a big fan of Xubuntu. I like it’s feel and it’s ease of use when it comes to installing packages using the apt-get command. I will be writing just about all of these blog posts using Xubuntu as my host OS.

I have installed on a development box Xubuntu 16.04 LTS. The only thing I selected during the install was to install OpenSSH so I could actually interface to the thing. We are going to install just a single additional package to allow us to compile ARM code, and it’s going to be really really simple to do!

Open up a command terminal on the local machine

In the event that you do not have SSH installed and would like it installed then here is the command:
# sudo apt-get install update
# sudo apt-get install openssh-server openssh-client

Now that you are at the prompt either on your local machine or via SSH, we can install the arm gcc tools:

$ sudo apt-get install gcc-arm-linux-gnueabi

Once the package is installed, you now have the ability to compile applications for your Zedboard!

That simple!!!

I am going to go to my home directory and create a folder to do some development in, and then compile a hello world application:

mmphego@4n0m4ly:~$ cd
mmphego@4n0m4ly:~$ mkdir arm-devel
mmphego@4n0m4ly:~$ cd arm-devel/
mmphego@4n0m4ly:~/arm-devel$ touch helloworld.c
mmphego@4n0m4ly:~/arm-devel$ cat > helloworld.c
int main(){
printf("Hello World!\n");
return 0;

So we have our source file, now we need to compile it. The application we will use is arm-linux-gnueabi-gcc.

$ arm-linux-gnueabi-gcc -o helloworld helloworld.c

Ok, so now we have our application written and compiled. But now what? We can’t run it on our development box because it isn’t ARM based. So we need to get it over to our Zedboard. The Zedboard conveniently ships with a SCP running on it! So all we need to do is connect to our Zedboard and drop our file there.

$ scp helloworld root@

On Zedboard:

Cool. So now our our Zedboard in the /home directory we have a file called helloworld. We need to change it’s properties so our shell knows it can be executed. To do this we will use chmod:
$ ssh root@
$ root@avnet-digilent-zedboard-2017_2:~# chmod +x SMV_Pub_Zedboard

You will notice that the helloworld app now has the ability to be executed. Well, what are you waiting for!? let’s do it!

root@avnet-digilent-zedboard-2017_2:~# ./helloworld
Hello World!

Woohoo! How cool is that!?. So now, you are well on your way to application development for the ARM cores running within the Zynq-7000 on you Zedboard.


How to mount remote SSHFS via SSH Tunneling!

sshfs is very handy for mounting remote directories on your local filesystem. Recently I needed to mount the / directory off a remote server so I can remotely work from home without complicating everything by ssh’ng then vim my code – Painful exercise.

All that is needed is to copy the code below to a file and chmod +x it.

if [ -z "$*" ];
    USERNAME: Default to local username
    HOST: Hostname or IP of server to connect to.
    REMOTEHOST: Host to tunnel via
    REMOTEPORT: Host port to tunnel via (Default: 2222)
    MOUNTPOINT: Local mounting point"
    exit 1;

export PATH="${HOME}/bin:$PATH"

# Assumptions: ssh keys have been generated and successfully copied over to remotehost, vice versa
# if necessary, openssh-client, openssh-server and sshfs packages installed
# The first we need to pre-establish a forwarded port over SSH.
ssh -v -f -N -L 1233:"${HOST}":22 -p "${REMOTEPORT}" "${REMOTEHOST}"
sshfs -p 1233 "${USERNAME}"@localhost:/ "${MOUNTPOINT}" -o reconnect,ServerAliveInterval=15,ServerAliveCountMax=3

Automagically execute a bash function/cmd upon entering a directory.

After growing tired of sourcing Petalinux/Yocto-project settings, I decided to compile a script/code that resides under my ~/.bashrc , the only thing the code/script does it automagically source my settings upon entering the directory else it will just list the contents of that directory.

source $HOME/.opt/Xilinx/Vivado/2017.2/
export YOCTODIR=$HOME/Documents/Xilinx/EmbeddedLinux/Yocto/poky
export PETADIR=$HOME/Documents/Xilinx/EmbeddedLinux/Petalinux
function cd {
    # The 'builtin' keyword allows you to redefine a Bash builtin without
    # creating a recursion. Quoting the parameter makes it work in case there are spaces in
    # directory names.
    builtin cd "$@"
    if [ "$PWD" == "$YOCTODIR" ] ;
            bash $YOCTODIR/.source_yocto
    elif [ "$PWD" == "$PETADIR" ] ;
            bash $PETADIR/.source_petalinux
        ls -lhF;

The content of source_petalinux listed above.

$ cat $PETADIR/.source_petalinux
. ~/.opt/petalinux/

as well as .source_yocto

$ cat $YOCTODIR/.source_yocto

. $HOME/Documents/Xilinx/EmbeddedLinux/Yocto/poky/oe-init-build-env

Xilinx PetaLinux 2017.2 installation on Ubuntu 16.04.3

Firstly, we will to the Xilinx Downloads page to obtain the installer. Select version 2017.2 on the left sidebar. Choose “PetaLinux 2017.2 Installer”. It is a single-file executable that is 7.54GB large.

Note: you have to be a registered user to download it.


Firstly we need enable i386 architecture (if running Ubuntu x64):

sudo dpkg --add-architecture i386

Before you proceed, make sure all the prerequisites are satisfied:

sudo apt install chrpath socat texinfo gcc-multilib libsdl1.2-dev xinetd tofrodos iproute \
gawk gcc git-core make net-tools ncurses-dev libncurses5-dev zlib1g-dev flex bison lib32z1 \
lib32ncurses5 lib32stdc++6 libselinux1 xvfb autoconf libtool libbz2-1.0 xinetd tftpd tftp \
lib32stdc++6 libgtk2.0-0:i386 libfontconfig1:i386 libx11-6:i386 libxext6:i386 libxrender1:i386 libsm6:i386 libssl-dev \

for a successful installation, we need to configure tftp

sudo nano /etc/xinetd.d/tftp

service tftp
protocol = udp
port = 69
socket_type = dgram
wait = yes
user = nobody
server = /usr/sbin/in.tftpd
server_args = /tftpboot
disable = no

Create a directory /tftpboot(this should match whatever you gave in server_args.)

sudo mkdir /tftpboot
sudo chmod -R 777 /tftpboot
sudo chown -R nobody /tftpboot

Restart tftp service

sudo /etc/init.d/xinetd stop
sudo /etc/init.d/xinetd start

/bin/sh to bash

sudo dpkg-reconfigure dash
# --> Select Yes

Now install PetaLinux into the directory/opt/petaLinux. The installer is a shell script that runs in the terminal.

chmod a+x
export PETADIR=$HOME/.opt/petalinux
sudo mkdir -p $PETADIR
sudo chown $USER:$USER -R $PETADIR

Press ‘ENTER' to see the licenses, q to quit reading the licenses, and y + ENTER to accept the licenses. The installation should last for about 15-30 mins.

Every time you want to use PetaLinux tools, remember to source the “settings” script to have the right environment variables:

source $HOME/.opt/petalinux/

Creating your first project [Board Support Package]

The following is a super simple walk-through of how to use PetaLinux tools.

  1. To create a PetaLinux project with a specific BSP, In my case Zedboard

Once you have the BSP of your choosing downloaded (and extracted if it was a zip file), go to your terminal and change directory to where you would like to create your new PetaLinux project directory and enter the following command.
In my case it would be:

$ cd $HOME/Documents/Xilinx/EmbeddedLinux/Petalinux/Projects
Then run the petalinux-create command on terminal:

$ petalinux-create -t project -s avnet-digilent-zedboard-v2017.2-final.bsp

Rebuilding the reference design system

In order to rebuild the system run petalinux-build

$ petalinux-build -v

This step usually takes 15-30min depending on the performance of your system, the step generated a device tree ‘DTB’ file, the FSBL(First Stage Bootloader), U-Boot, Linux Kernel and the root file-system images

After the build is complete you can test it in a simulated environment.

Pre-built Petalinux image test with QEMU

Petalinux provide QEMU support to enable testing the image-built in a simulated environment.

$ petalinux-boot --qemu --prebuilt 3
# The --qemu option test petalinux-boot to boot in QEMU instead of real hardware,
# and --prebuilt 3 boots the pre-built <span 				data-mce-type="bookmark" 				id="mce_SELREST_start" 				data-mce-style="overflow:hidden;line-height:0" 				style="overflow:hidden;line-height:0" 			></span>linux kernel

Diagnosing LAN Speeds

After having network issues/degradation while trying to access a work server, I had to diagnose the network the server is connected to. I had to set myself on a mission – and after realising that the seems to be very limited tools for such things, I stumbled upon ‘iperf‘.

Iperf is a command-line tool used in the diagnostics of network speed issues, it measures the maximum network throughput a server can handle. It is particularly useful when experiencing network speed issues, as you can use Iperf to determine which server is unable to reach maximum throughput.

Iperf installation

Iperf must be installed on both computers you are testing the connection between.

sudo apt-get install -y iperf

TCP Clients & Servers

Iperf requires two systems because one system must act as a server, while the other acts as a client. The client connects to the server you’re testing the speed of.

  1. On the node you wish to test, launch Iperf in server mode:
iperf -s

You should see output similar to:


2. On your second Linode, connect to the first. Replace dbelab04 with the first node’s IP address in my case i’m using the hostname

iperf -c dbelab04

You should see output similar to:

3. You will also see the connection and results on your Iperf server. This will look similar to:


4. To stop the Iperf server process, press CTRL + c.


You can do pretty much the same thing with plain old nc (netcat) if you’re that way inclined. On the server machine:

nc -vvlnp 12345 >/dev/null

You should see something similar to:


And the client can pipe a 10Gb of zeros through dd over the nc tunnel.

dd if=/dev/zero bs=10M count=1K status=progress | nc -vvn 12345

You should see something similar to:


The timing there is given by dd but it should be accurate enough as it can only output as fast the pipe will take it. If you’re unhappy with that you could wrap the whole thing up in a time call.

Remember that the result is in megabytes so multiply it by 8 to get a megabits-per-second speed. The demo above is running at 11.8mbps due to my laptops network limitation and number of hops…

Python’s Virtualenv working with Jenkins

If you use virtualenv to isolate your python project’s environment, and want your code tested automatically — read on, else ignore.

virtualenv isolates your project’s python environment

virtualenv makes sure you lock down your project’s main directory and all subdirectories of it. This ‘lockdown’ means that you never touches your global python binary, or any globally installed libraries (like “sudo pip install ipython” ).

Once locked down, you install all packages again, even those you have globally installed. This enables you to have one version of flask globally installed, but another version in your project. All dependencies can be listed in a separate file and validate a precise environment for you to work with. Tightly controlled dependencies is key to a deployment without surprises.

Jenkins checks the health of your project for each change

Jenkins is a CI server which means it does a lot of repeating stuff so you can focus on doing more important stuff. More specifically, it listens for changes to your project’s version control system (like git).

When changes are detected, the project is built and the test suite is executed. If any step fails, the CI server tells you that it did.

Setup Jenkins, and make it use virtualenv

Jenkins needs some massaging before it handles the hijacked environment of virtualenv. This is how I did it for my local git repository:

  • Download and install Jenkins
  • Start it, it should be up on http://localhost:8080
  • Install the Git Plugin
  • Setup a new project with these properties:
    • Source Code Management: add the URI to your local repository,
    • /Users/you/Sites/asdf in my case. Make sure the jenkins user can read this directory, otherwise the Jenkins GUI will tell you something random about invalid git repo, without a hint about a permissions error.
    • Build Triggers: Poll SCM (with an interval like 0 * * * *). This is needed because
      you’re too lazy to build manually; and
      you can not trigger builds with a git post-commit hook otherwise
    • Build > Execute shell. I’ve used two steps, one for setting up the environment and one for the actual tests:

# Setup a proper path, I call my virtualenv dir "venv" and
# I've got the virtualenv command installed in /usr/local/bin
if [ ! -d "venv" ]; then
        virtualenv venv
. venv/bin/activate
pip install -r requirements.txt --download-cache=/tmp/$JOB_NAME


. venv/bin/activate
which python

# reply should be
Back to top