The Xilinx wiki has some specific instructions on how to properly format an SD card. I don’t know how important it is to follow those instructions, since the ZC7020 and Zedboard seem to boot just fine with any FAT partition, but it can’t hurt to follow them. Here is a script that makes a dual partition SD card.

Insert SD card into PC with reader and type:
sudo ./mkZyqSDCard sdX
where X is the letter that appears in /dev/sdX when you put the disk in the drive.

Example formatting a 2GB SD card:

[nick@CentOS Zynq7020Dev]$ sudo ./mkZynqSDCard sdb
Checking to make sure all partitions are unmounted…
umount: /dev/sdb1: not mounted
umount: /dev/sdb2: not mounted
Beginning format
1024+0 records in
1024+0 records out
1048576 bytes (1.0 MB) copied, 2.0956 s, 500 kB/s
Checking that no-one is using this disk right now ...

Disk /dev/sdb: 243 cylinders, 255 heads, 63 sectors/track
/dev/sdb: unrecognized partition table type
Old situation:
No partitions found
New situation:
Units = sectors of 512 bytes, counting from 0

Device Boot Start End #sectors Id System
/dev/sdb1 * 2048 417689 415642 c W95 FAT32 (LBA)
/dev/sdb2 417690 3887729 3470040 83 Linux
/dev/sdb3 0 – 0 0 Empty
/dev/sdb4 0 – 0 0 Empty
Successfully wrote the new partition table

Re-reading the partition table …

If you created or changed a DOS partition, /dev/foo7, say, then use dd(1)
to zero the first 512 bytes: dd if=/dev/zero of=/dev/foo7 bs=512 count=1
(See fdisk(8).)
mkfs.vfat 3.0.9 (31 Jan 2010)
mke2fs 1.41.12 (17-May-2010)
Filesystem label=root
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
108640 inodes, 433755 blocks
21687 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=444596224
14 block groups
32768 blocks per group, 32768 fragments per group
7760 inodes per group
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912

Writing inode tables: done
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 36 mounts or
180 days, whichever comes first. Use tune2fs -c or -i to override.

Format Complete!
Disk size: 2002780160 Bytes
Heads: 255
Sectors: 63
Cylinders: 243
[nick@CentOS Zynq7020Dev]$

Here is the script:

#This script creates a microSD card with a 200MB FAT32 partition, and the
#rest an ext2 partion, suitable for booting a Xilinx Zynq7000.

#Check for root permissions

if [ $(whoami) != ‘root’ ]; then
echo “Must be root to run “
exit 1;

#Make sure that a drive has been specified
if [ ! -n “$1” ]; then
echo “Please specify a card, for example: # sh formatSDCard sde”
exit 1;

#Make sure that the hard-drive isn’t accidentaly annihilated
if [ $DRIVE = ‘sda’ ]; then
echo “Do not format drive sda!”
exit 1;

#Unmount any partitions on the drive
echo “Checking to make sure all partitions are unmounted…”

while [ ! -z `ls /dev/ | grep ${DRIVE}${i}` ]; do
umount /dev/${DRIVE}${i}
i=$(( $i + 1 ))
sleep 2s

echo “Beginning format”
#Calculate number of cylinders in virtual drive geometry
SIZE=`fdisk -l /dev/${DRIVE} | grep Disk | awk ‘{print $5}’`
CYLINDERS=`echo ${SIZE}/255/63/512 | bc`
declare -i PART2SIZE

#Clean up any existing partition data
dd if=/dev/zero of=/dev/${DRIVE} bs=1024 count=1024

#############Create partition table using sfdisk########################
# The Xilinx wiki at
# says that there needs to be a 2048 sector offset at the beginning of
# the drive, and the boot partition is 200MB. To end partition 1 at a
# cylinder boundary, the size of partition 1 will be 415642 sectors.
# (2048+415642)/255/63 is 26 cylinders.
# Partition 2 will begin at 2048+415642, or cylinder 26, and the end
# will align with the last cylinder on the drive. The PART2SIZE
# variable has the number of sectors needed to end on the last cylinder.

echo “2048,415642,0x0C,*
417690,$PART2SIZE,,-” | sfdisk -uS -D -H 255 -S 63 -C ${CYLINDERS} /dev/${DRIVE}

#Format the two new partitions
#FAT32 is for the bootable partition
#ext4 is for the root filesystem partition
mkfs.vfat -F 32 -n boot /dev/${DRIVE}1
mkfs.ext4 -L root /dev/${DRIVE}2

echo ”
Format Complete!”
#Display size information in case the user cares
echo “Disk size: ” ${SIZE} ” Bytes”
echo “Heads: 255”
echo “Sectors: 63”
echo “Cylinders: ” ${CYLINDERS}


I prefer to develop software on my windows computer. In order to work with the Zynq-7020 evaluation kit, that means I need to cross compile. Here is my method for doing so.

Install whichever development environment you prefer for C++. I use an Eclipse development environment, such as the Xilinx SDK, but Visual Studio and other IDE’s also work.

Install tools needed to cross compile in windows:

install MinGW
install cmake
install linaro

Update path. Go to:
My Computer->properties->Advanced System Settings
Add this to the “path” box:
C:\MinGW\bin;C:\MinGW\MSYS\1.0\local\bin;C:\MinGW\MSYS\1.0\bin;C:\Program Files (x86)\CMake 2.8\bin;C:\Program Files (x86)\Linaro\gcc-linaro-arm-linux-gnueabi-2012.04\bin

To make a cross compile project:

Make a project folder:
mkdir Zynq7020-HelloWorld
cd Zynq7020-HelloWorld\

Make a “Zynq7020.cmake” file with this in it:
SET(CMAKE_C_COMPILER arm-linux-gnueabi-gcc.exe)
SET(CMAKE_CXX_COMPILER arm-linux-gnueabi-g++.exe)
SET(CMAKE_FIND_ROOT_PATH "C:/Program Files (x86)/Linaro/gcc-linaro-arm-linux-gnueabi-2012.04")

Make a “CMakeLists.txt” file like this:
cmake_minimum_required(VERSION 2.6)
FILE(GLOB SRC "src/*.cpp")
FILE(GLOB HDR "src/*.h")
add_executable(Zynq7020-HelloWorld ${SRC} ${HDR})

Make build and src folders
mkdir build\
mkdir src\

Make a “build.bat” file in the Zynq7020-HelloWorld\build\ folder. You can substitute a lot of different IDE’s for “Eclipse CDT4 – Unix Makefiles”:
cmake -D CMAKE_BUILD_TYPE=Debug -D CMAKE_TOOLCHAIN_FILE=..\Zynq7020.cmake -G "Eclipse CDT4 - Unix Makefiles" ..

Add Zynq7020-HelloWorld.cpp source file to Zynq7020-HelloWorld\src\:

int main()
printf(“Zynq7020 says ‘Hello World’\n”);
printf(“Cross-compiled on Windows with Linaro for Zynq-7020\n”);
return 0;

There should be 4 files and 2 subfolders like this:

If you are using eclipse or the Xilinx SDK, you can open import the project (Import existing projects into workspace) that was created by cmake. If you prefer a different environment, you will need to change the build.bat file to create a different set of project files.

Build the project to produce an executable that can run on the Xilinx Petalinux BSP.

Before running the executable, Petalinux must be configured and built under a Linux environment:
petalinux-config -c rootfs
In the ncurses menu, select whichever libraries you need (I used these):

  • Filesystem Packages —>
    • [*]Advanced Package Selection
      • Base —>
        • external-xilinx-toolchain —>
          • [*]gdbserver
          • [*]libc6
          • [*]libcidn1
          • [*]libgcc-s-dev
          • [*]libgcc-s1
          • [*]libmemusage
          • [*]libsegfault
          • [*]libstdc++-staticdev
          • [*]libstdc++6
          • [*]libthread-db1
          • [*]linux-libc-headers

Build petalinux
Then boot the EVM. It is easiest to use FTP to transfer the file to the Zynq. By default, the home FTP folder is /var/ftp.
Run the program:
root@Xilinx-ZC702-2014_2:/var/ftp# chmod 755 Zynq7020-HelloWorld
root@Xilinx-ZC702-2014_2:/var/ftp# ./Zynq7020-HelloWorld
Zynq7020 says 'Hello World'
Cross-compiled on Windows 7 with Linaro

This post covers building the Petalinux BSP for the Zynq-7020 Dev Kit, some basic cusomization so it can run GNU C/C++ code, and a small section about Xilinx file types.

I followed the PetaLinux Getting Started guide, which covers Petalinux installation and BSP getting started guide. The instructions are slightly incomplete, which was very confusing for me as a beginner.

First, make sure to have the right build platform. PetaLinux requires 32 bit libraries, and even if they are installed, there are other issues with linux components (like sed), that will keep it from working. I used CentOS 6.5, which was pretty painless to install and get up and running. My CentOS setup instructions are here.

Remember that if these variables are not in the bash environment, nothing will work
Run the script from the petalinux install folder:
cd ~/Zyn7020Dev/petalinux-v2014.2-final/

Add SDK tools and cross compilers to $PATH variable
export PATH=$PATH:/opt/Xilinx/SDK/2014.2/bin
export PATH=$PATH:/opt/Xilinx/SDK/2014.2/gnu/arm/lin/bin/
export CROSS_COMPILE=arm-xilinx-linux-gnueabi-

Install PetaLinux BSP
The BSP is available from the Xilinx website:

For a Zynq7020 Evaluation kit, click “PetaLinux 2014.2 Board Support Package for Xilinx ZC702 evaluation kit”, and download the Java thing to get the BSP.

That will download “Xilinx-ZC702-v2014.2-final.bsp”. Put it in your development folder (~/Zynq7020Dev) and do:
petalinux-create -t project -s Xilinx-ZC702-v2014.2-final.bsp
This unpacks the BSP into Xilinx-ZC702-v2014.2/. The BSP features a bare-bones pre-built version of Linux in Xilinx-ZC702-v2014.2/pre-built/linux/images.

Boot the Pre-Built PetaLinux BSP
PetaLinux includes a pre-built BSP so you can verify that it works. To boot petalinux:

  1. Format an SD card to FAT32, I used a script to do 2 partitions, 200Mb FAT32 + the rest ext2.
  2. Copy BOOT.BIN and image.ub to the card (I believe they need to go on in that order)
  3. Make sure the EVM usb-serial cable is connected to your PC, the PC sees a serial port
  4. Start putty, or any other serial program and point it to the Silicon Labs USB to UART
  5. Insert the card into the EVM SD card slot
  6. Power on the EVM, and quickly press the [ANY] key to interrupt the boot
  7. At the U-boot prompt type
  8. U-Boot-PetaLinux> setenv bootcmd ‘run sdboot’ ; saveenv
  9. U-Boot-PetaLinux> reset
  10. Then watch the EVM reset and boot.

U-boot saves its environment to the onboard flash, so once the bootcmd is set to ‘run sdboot’, the board will always look for the kernel and rootfs pacakge on the SD card. If this isn’t done, u-boot won’t know where to find the kernel, and the board will not get past the u-boot screen.

Configure and Build PetaLinux BSP
Back in the VM, in the Xilinx-ZC702-v2014.2/ folder, configure the kernel options:
petalinux-config -c kernel

This opens a ncurses-type graphical menu for configuring the kernel. Note that the default config works just fine! I usually add drivers I want compiled into the kernel or extra networking options:

  • [Networking options]
    • [*]TCP/IP networking
    • [*]IP: multicasting
    • [*]IP: advanced router
    • <*>IP: tunneling
    • [*]IP: multicast routing
    • [*]Network packet filtering framework (Netfilter) —>
      • [*]Advanced netfilter configuration
      • Core Netfilter Configuration —>
      • Netfilter Xtables support (required for ip_tables)
    • [*]QoS and/or fail queueing —>

Next configure the root filesystem:
cd ~/Zynq7020Dev/XilinxZC-702-2014.2/
petalinux-config -c rootfs

This opens a ncurses graphical menu for configuring the foor filesystem. I add some packages, mostly so that I can use the linaro cross compiler:

  • Filesystem Packages —>
    • [*]Advanced Package Selection
      • Base —>
        • external-xilinx-toolchain —>
          • [*]gdbserver
          • [*]libc6
          • [*]libcidn1
          • [*]libgcc-s-dev
          • [*]libgcc-s1
          • [*]libmemusage
          • [*]libsegfault
          • [*]libstdc++-staticdev
          • [*]libstdc++6
          • [*]libthread-db1
          • [*]linux-libc-headers
        • i2c-tools —>
          • [*]i2c-tools
      • console/network
        • ethtool —>
          • [*]ethtool
        • netcat —>
          • [*]netcat
        • tcpdump—>
          • [*]tcpdump

And of course you may configure any packages you want. Then:

That should take about 20 minutes. This process builds a bunch of stuff in the images/linux folder. The important files are

  • zynq_fsbl.elf
  • u-boot.elf
  • image.ub

Build a new BOOT.BIN by combining u-boot, zynq_fsbl.elf, and the download.bit file. The download.bit file is in a different folder with the pre-built stuff and not produced by petalinux, so it is convenient to copy it to the images folder first:

cd ~/Zynq7020Dev/Xilinx-ZC702-v2014.2/images/linux/
cp ../../pre-built/linux/implementation/download.bit .

petalinux-package --boot --force --fsbl zynq_fsbl.elf --uboot --fpga download.bit

Then boot using the same process as with the pre-built BSP. It won’t finish booting if you don’t include the download.bit file, so make sure to add that part.

A Quick note on the PetaLinux file types

I found all the bit, bif, bin, elf, hdf, ub, gz and other file types to be very confusing. Here are the important file types in regards to PetaLinux.

  • filename.bit – The Zynq needs a .bit file to tell it how the FGPA is configured. This file is produced/exported from the Vivado program. With a dev kit, you can use a pre-supplied .bit file, or build your own. Either way, it has to be combined with the fsbl and uboot files into a BOOT.BIN for the processor to boot.
  • zynq_fsbl.elf – This file is a common set of bits, known as a “first stage boot loader”, that tells the Zynq how to start up and find the .bit and uboot files. It can be produced by the Xilinx SDK, or you can get it from the Xilinx website or PetaLinux BSP. It is a very simple instruction list, so it has to be combined with the u-boot and .bit files to boot the Zynq.
  • u-boot.elf – the program that finds the linux kernel wherever it may be, and starts it running. This doesn’t just go on the SD card, it has to be combined with the fsbl and .bit files first.
  • BOOT.BIN – This is a combination of the .bit, fsbl, and u-boot files. It can be made with the SDK, using a .BIF file to tell the SDK what files to use and how to combine them, or it can be built with the petalinux-package command. The first few bits of this file (the fsbl) have to be the first thing the Zynq sees for it to boot up.
  • image.ub – This is how petalinux-build combines the kernel, device-tree, and root filesystem in the BSP.
  • filename.hdf – These files are hardware description files, also produced by Vivado. They are used by PetaLinux to create and configure new projects.



mv ~/Downloads/Xilinx-ZC702-v2014.2-final.bsp ~/Zynq7020Dev/
petalinux-create -t project -s Xilinx-ZC702-v2014.2-final.bsp
cd Xilinx-ZC702-v2014.2
petalinux-config -c kernel
petalinux-config -c rootfs
cd /images/linux/
cp ../../pre-built/linux/implementation/download.bit .
petalinux-package --boot --force --fsbl zynq_fsbl.elf --uboot --fpga download.bit
Boot EVM
U-Boot-PetaLinux> setenv bootcmd 'run sdboot' ; saveenv ; reset

I needed a build platform to make a Petalinux OS for a Xilinx Zynq7020 dev kit, so I documented my steps to make it. This is accurate as of 9/2/2014, but probably won’t work much past then. I wasted a bunch of time trying to get PetaLinux to run on a Debian 7 environment, only to see that it works perfectly on the first try using CentOS 6.5.

Reference the petalinux install guide from:
And the petalinux Getting started guide from:

I chose a CentOS 6.5 32-bit VM. Redhat proper costs money now, apparently, which is why they forked CentOS. I installed a VM with Oracle VirtualBox. I made a disk with 40GB of space. I’m not sure what a ‘good’ amount of space is, but its probably at least 20GB.

Setup CentOS VM

Get the VM install iso from
There is a torrent to download the CentOS 6.5 32bit DVD iso’s. Install the basic desktop image.

This part is optional. CentOS 6.5 requires an addition to /etc/sudoers to sudo in order to do sudo things. So, you might choose to add your username to the sudoers file or you can su in and out of root.
chmod 666 /etc/sudoers
gedit /etc/sudoers (vi sudoers)

right under the root ALL=(ALL) ALL, add yourusername ALL=(ALL) ALL
save, then
chmod 644 /etc/sudoers

Make sure to turn on internet access.
sudo ifup eth0

Update the CentOS packages to the latest versions and get the Virtualbox addons working so you can share files and copypaste from host. Open a terminal and:
sudo -s
yum update
yum groupinstall "Development Tools"

Restart the VM.
In virtualbox “Devices” menu, at the bottom, click “Insert Guest Additions CD image”
The GA CD should autorun and install. If it does not run, you will need to change /etc/fstab. Remove the word “noauto” and replace with “exec”.

MAKE SURE IT SUCCESSFULLY INSTALLS. If it shows a failure or an error message, the VirtualBox shared folder and copypaste features won’t work. Shut down the VM and restart it from VirtualBox to get the mouse capture, copypaste function, and shared folders working.

Install petalinux dependencies. Remember to sudo ifup eth0! Then do:
sudo yum install iproute gawk gcc git-core make net-tools flex bison tftp-server ncurses-devel

Setup tftp service under xinetd. This is very helpful for network booting, which speeds up development:
mkdir /tftpboot
chmod 777 tftpboot
vi /etc/xinetd.d/tftp

Make sure disable = no and server args = -s /tftpboot:
service tftp
socket_type = dgram
protocol = udp
wait = yes
user = root
server = /usr/sbin/in.tftpd
server_args = -s /tftpboot
disable = no

then save and close

Install the Xilinx SDK

We only need this the SDK on this platform for the bootgen tools PetaLinux (or a poweruser) needs to build boot images.

Download 32 bit Vivado Xilinx SDK. Go to:
click on:
Linux 32: Vivado 2014.2 Web Install Thin Client
Fill out the ITAR questionaire and agree to load the java based web downloader.

Install Xilinx SDK as root:
sudo ./Xilinx_Vivado_SDK_2014.2_0612_1_Lin32.bin
Click agree through the terms and conditions. Eventually it will open a GUI window.
In the GUI window, select to install the Standalone Software Development Kit (SDK) from the install options. The other tools are for programming the FPGA part of the chip. You can install them also if you want to do everything in one machine.

When the installation completes, it will open a license manager. Unless this is a primary work machine, I would just use the free SDK license, which there is a web link to go generate.
If you already have a license, when the license manager starts, choose load license from the pane on the left side, and
copy the license from wherever it is.

Install Petalinux

Use browser to download the Petalinux toolset. Go to:
click on:
PetaLinux 2014.2 Installation archive for Zynq and MicroBlaze (BSP – 1.13 GB)
MD5 SUM Value: c2f74097ac32f5fda385e0cbf9d8bd00

Fill out the ITAR questionaire and load the java based web downloader.
It should put this in your ~/Downloads folder:

as regular user, install petalinux in a Zynq development folder (~/Zynq7020Dev/ for me)
mv ~/Zynq7020Dev/
cd Zynq7020Dev

You will have to press q and y several times to agree to several sets of terms

Once installed, make this settings script runnable
chmod 755 ~/Zyn7020Dev/petalinux-v2014.2-final/

The next steps setting the environment variables must either be added to the bash environment or
be done EVERY time a new bash window is opened to do petalinux stuff

Run the script:
cd ~/Zyn7020Dev/petalinux-v2014.2-final/

Add SDK tools and cross compilers to $PATH variable
export PATH=$PATH:/opt/Xilinx/SDK/2014.2/bin
export PATH=$PATH:/opt/Xilinx/SDK/2014.2/gnu/arm/lin/bin/
export CROSS_COMPILE=arm-xilinx-linux-gnueabi-

And with that, you are ready to follow the instructions from Xilinx for making a bootable Zynq image and SD card.

My hot tub pump motor was not starting while making a loud "hum" until the overheat relay shut it off. Usually when a motor doesn't start it is either the capacitor (about 25 years old in my tub) or the switch that turns on the capacitor. In this case it was the switch. In the photo you can see that the contacts in the center were scarred and black. After I rubbed them with emery cloth, the motor worked again.

I needed a more convenient way to open my garage door than the radio buttons that came with the garage door opener. I used an Arduino Duemilanova, Ethernet shield, and my android phone (Samsung GS4) to create a better garage door opener. I checked in the program at github:

Here is a screenshot of the app. It’s very simple: just a toggle button and an indicator of the door state.


I installed a roller switch on the door itself to indicate that it is closed. My garage door sometimes does not close after the button is pressed. It gets stuck halfway, and opens back up. This way I can know it had an issue without waiting in the cold to watch it close.Image

Here is the Arduino and a small protoboard with a relay and transistor on it. The door opens with a simple contact pushbutton. The relay simulates that button press. All these parts are from Radio Shack, except the Arduino. There was already Ethernet cabling installed in the attic from years ago when I wired the house with cat5. Since then, the cat 5 has been unused until today. All I had to do was plug it into the Arduino.Image

The phone connects automatically to the house wifi through the wireless router. The App knows the IP address of the Arduino. When the button is pressed, it sends a UDP command to the Arduino, which opens the door. The arduino responds with a message to let the phone know that it received the command. The button flashes to alert the user that the door is moving. Every 20 seconds, the phone sends a status request to the Arduino, which replies with the door state.

Here is the schematic of how I wired the switch and relay.

garage door opener wiring