Snickerdoodle up and running
Description
First, I’m not an expert, I learned a lot by reading and hacking on this so there may be misunderstanding on my part and if you find something that I did wrong please let me know.
These are instructions on how to get custom hardware working with snickerdoodle. I’ll be using Snickerdoodle black but these instructions should work with any board.
Intro
My wife bought me a Nintendo switch. I liked the form factor and it got me thinking about FPGA development boards. The one things I didn’t like about them is that FPGA devboard are for lab benches. I wanted to make a devboard that I could use in experiments.
To make a long story short I found Snickerdoodle from Krtcl and I thought it would be a great fit for my project. I didn’t think it would be that hard to adapt snickerdoodle to my board. This was not the case. This post is the sanatized version of my build.
The Snickerdoodle book was the main resource I used to build the kernel but I also relied heavily on the forums at both Krtcl and Xilinx.
I did all of my work on an Ubuntu box so I won’t describe how to do anything on a Windows box. I also built this for Vivado 2017.4 so if some commands don’t work with your system you might need to change the commands to match up with your installation.
I created a directory where i could work on everything related to this projects. You will see a lot of the information referenced to this directory
I broke this down into steps
Steps
- Download and install the necessary files.
- Build an FPGA Image.
- Generate the First Stage Boot Loader.
- Download and setup kernel scripts.
- Download and setup u-boot scrips.
- Build u-boot.
- Setup the rootfs.
- Build the kernel.
- Configure an SD Card.
- Create a boot image.
- Copy Files to the SD Card
Download and Install the Necessary Files
Krtcl offers Xilinx Board files that are read by Vivado. This simplifies the build process. When starting a project, the user simply selects the board file instead of identifying the correct FPGA and writing up a custom constraint file.
To do this download the vivado files Vivado Board Files
Build an FPGA image
Build an FPGA image. These are the same instructions that can be found in the snickerdoodle book.
I started out with the example designs.
This will ask if you want to “Automatically update to the current version”, say “Okay”
After it has finished converting the project open up the block diagram.
This will load the block diagram but it will probably throw up this dialog box:
press ‘Report IP Status’ and scroll down to the bottom and select ‘Upgrade Selected’
Build the project by pressing ‘Generate Bitstream’
After the bitstream is generated you will see this screen:
Press ‘Cancel’
Generate the First Stage Boot Loader.
The output of this step is the first stage bootloader (FSBL). This is the first thing the Zynq processor sees when it turns on. The job of the FSBL is to initialize the processor and then load u-boot (the second stage boot loader). the job of the second-stage bootloader is to load the Linux Kernel.
Within the Vivado project that you used to build a bitstream go back to the block diagram view. Under the ‘File’ Menu select: ‘File’ -> ‘Export’ -> ‘Export Hardware’ and when the dialog box comes up select ‘Include Bitstream’ and press ‘Okay’.
Start the SDK by going to the ‘File’ menu and select ‘File’ -> ‘Launch SDK’
SDK
Within the SDK under the ‘File’ menu and select ‘File’ -> ‘New’ -> ‘Application Project’
Name the project ‘fsbl’
press the ‘Next’ button at the bottom and select ‘FSBL’ project at the bottom
The project should automatically build. The generated FSBL is located:
<your project>/<your project>.sdk/fsbl/debug/fsbl.elf
We will be using this later when we create the Boot Image.
Download and Setup Kernel Scripts
This step downloads the kernel source code from snickerdoodle’s github page as well as some scripts I wrote to help simplify building the kernel.
First navigate to the snickerdoodle directory
Download the build script
move it to your snickerdoodle base directory and modify it to be an executable
We will eventually be building the kernel but we need to leave this for right now because we must build u-boot first.
Download and Setup U-Boot Scrips
Similar to the steps above we need to get both the u-boot source as well as the u-boot build script.
Download the build script
move it to your snickerdoodle base directory and modify it to be an executable
As noted in the snickerdoodle book there is a strange ‘chicken and the egg’ problem. In order to build uboot you need a tool in the kernel to be built (dtc) while in oder to build the kernel for uboot you need a tool found in u-boot (mkimage).
One of the functions of the ‘build-kernel.sh’ script is to build the scripts that are found within the kernel. To do this execute the following:
Build U-Boot
Now you can build uboot by the following command:
The end of the build will look something like this:
and will be found here: ~/Projects/snickerdoodle/build/uboot/
Specifically u-boot is found at ~/Projects/snickerdoodle/build/uboot/u-boot
This is the arm ‘elf’ file that will be used when generating the initial boot partition of the SD Card.
Note:
If you wish to build uboot again do not use the ‘-r’ flag as this will erase all the build files, just use the following:
This saves a lot of time.
Setup the Rootfs
This is pretty simple. Download the rootfs from the Krtcl Website:
NOTE: We need to use sudo permission because we use the ‘-p’ flag from ‘tar’ this presserves the permissions of the file system. So any file that needs to be owned by root will keep that permission level.
Now the rootfs is setup for us to edit. We will be modifying it when we build the kernel next.
Build the Kernel
Now that u-boot is build we almost have everything we need to build the kernel. There is only one thing missing. The firmware for the WIFI. The WIFI chip is developed by TI and requires the kernel to downlaod an image into it. This can be built from scratch but it is not required to build from scratch. We are going to drop in a previously build binary image for the WIFI driver and the kernel will assume it doesn’t need to build it from scratch.
Get the binary firmware for the kernel found here:
WIFI Config Binary WIFI Firmware
Download the two files and execute the following:
Next we build the kernel. Similar to u-boot the first time we build the kernel it will take a while because we need to start from scratch. After we build the kernel the first time the build will be much faster.
For the first time you build the kernel use the following command:
NOTE: This script does require root privledges because it will create the kernel modules and copy them into a rootfs. It seems strange that we would need rootfs to copy into this local directory but because we copy all files with permission to the snickerdoodle board these modules must have root permission before they are copied.
The end of this script run should look like this:
After this you can use the following command to build the kernel much faster
This does more than just build the kernel. It does the following:
- Builds ‘uImage’ and gives it an address of 0x8000.
- Generates all the external kernel modules that can be loaded into the kernel while the kernel is running.
- Copys the generated modules into the ‘rootfs’ directory where the user’s filesystem should be loaded.
Configure an SD Card
This is taken directly from the krtcl snickerdoodle book. Using the fdisk tool we can create the correct partitions for an SD Card.
The best way to identify what is the SD Card on your Linux Box is to type the command
Then insert your SD Card. When I inserted my SD Card I got the following:
The SD card we will modify is ‘sdc’ WARNING: THIS MAY BE DIFFERENT ON YOUR MACHINE!! If you perform these functions on your hard drive you will format your hard disk!!
Withi the fdisk here’s how I modified my SD Card when I started fdisk
Now that the disk is formatted we need to configure the partition with the correct filesystem.
FAT32 on the first boot partition and EXT4 on the second partition.
Configure the first partition to be FAT32
Configure the second partition to be EXT4
It’s a good idea to eject the SD Card and re-insert it.
Now when you reinsert it you will have an SD Card with two partitions
Create a Boot Image
There are a lot of ways to boot the kernel. One way I perfer is to use ‘sysboot’ within uboot. This method loads the kernel from the ext4 file system in the rootfs parition along with the device tree binary (dtb) file into the memory and then boots the kernel from there. This method is nice because when the user wants to update the kernel all that is required is to copy the new kernel to /boot/image and the dtb to /boot/devicetree.dtb
the Sysboot will do all the rest of the work.
To accomplish this we will need to rebuild uboot with the ‘DISTRO_DEFAULTS’ option enabled. To do this build uboot with the ‘-m’ option which will start the ‘menu’ configuration tool.
You will see this screen
Type the following
You will see a search result with one output. Press ‘1’ and then space to enable ‘distro_defaults’
Your screen should look like this
Press the right arrow button to get over ‘Exit’ and keep selecting ‘Exit’ until it asks you to save the configuration file. Say ‘Yes’
Before we build uboot we need to adjust the internal build environment within uboot. In it’s current state sysboot is not called when uboot first starts up. We can do this one of two ways. We can write a script and use the ‘mkimage’ tool so that the script is loaded into uboot or we can modify the default uboot environment by modify the file:
You can copy and paste the ‘zynq_snickerdoodle_black.h’ file I have written to that location
Download this and copy to the correct location
Now build uboot
Creating the BOOT.bin file
To generate the BOOT.bin we will need to get the FSBL, uboot output, device tree blob and the kernel.
To simplify things for me I created a new folder called ‘boot_builder’ from the base snickerdoodle directory.
We can copy all of the generated output files into this directory, specifically we will copy the following (Note the input and output names may be different)
- fsbl.efl -> boot_builder/fsbl.elf
-
/ .runs/impl\_1/ .bit -> boot\_builder/bitstream.bit - build/uboot/u-boot boot_builder/u-boot.elf
- build/uboot/dts/dt.dtb boot_builder/devicetree.dtb
Now that we have all the files we can create our ‘BOOT.bif’ file:
Open up the file with a text editor and enter the following text:
Now run the following command to generate the BOOT.bin file
Copy Files to The SD Card
Copy the boot.bin file to the SD Card by inserting the SD Card and running the following commands:
Copy the rootfile system onto the SD Card Parition 2