In the previous post we were able to execute Linux over our synthesized system configuring manually the FPGA, loading through Microblaze the Linux image to the DDR3 memory and launching the execution of that image.
This is a good way to test if all the configuration was correct, but as soon as we power off the system, all the process needs to be done again and we want a system which runs Linux when powered, as we are used to.
To achieve that, we need to store the three things from the title: The FPGA configuration, Linux image and a Bootloader which copies that image to RAM and launches it.
The first thing we will do is to program the FPGA config file to the quad SPI flash device included in the Arty. It is a Micron N25Q128 powered at 3.3 V.
Previously (as default) the binary generated file was a .bit file which is to be programmed through JTAG. Now we will create a .bin file:
- On Vivado, open the synthesis view, clicking over "Open Synthesized Design", then go to Tools > Edit Device Properties... and select these settings:
- General > Enable Bitstream compression: YES
In order to use less size
- Configuration > Configuration Rate (MHz): 33
To improve the speed. The flash memory can manage up to 108 MHz so we have margin to avoid errors
- Configuration Modes > Select Master SPI x4 option
This is the way that our Flash is connected.
- Now click on BitStream Settings and Select .bin file option
At this time you can regenerate the Bitstream. Open the Hardware Manager, it is our tool to program our devices, either FPGA or Flash. In order to recognize our Flash through the configuration interface of the Artix 7 FPGA:
- Right click over our xc7a35t part and select Add Configuration Memory Device...
- Search for the Micron N25Q128-3.3V* and select it. You will be asked to program the configuration memory device. Accept it or go later to that option right clicking over the appeared device on the Hardware list and select Program Configuration Memory Device...
- Search for your .bin image and click over Program with these options
Great!! Now we know how to program the FPGA configuration file to the Flash memory. It is time to do the same with the Linux image, but the FPGA will not execute the Linux image by its own, this is the task of the Bootloader.
The bootloader is a little standalone code which access to the Quad SPI Flash memory, copies desired code to the RAM and jumps into this code to execute it.
In Vivado SDK, in the same way that we have a 'Hello World' predefined example, Xilinx provides a SREC image format example bootloader. Unfortunately I converted the .bin image that we previously created to .srec and it becomes excessively large (about 17MB). In this way, I had to modify it to make the boot process with a .bin image.
My first idea was to post all needed steps to modify the Xilinx example to get the .bin bootloader but finally it took more changes than I expected so I am posting the bootloader.c file and I will explain the main keystones to use it and adapt to your requirements.
You can download it from here
It is not fully optimized so please do not blame me if you see unused variables or something like that.
- Go to Vivado > File > Launch SDK
- In the SDK, create a new project going to File > New > Application Project
- Input your project name (for example "Arty_boot") and click Next. Then select the "SREC SPI Bootloader" template.
- Now you can overwrite your bootloader.c file with mine
There are only three things to take into account when using the bootloader.
- In the SDK open the the generated *_bsp folder, right click over it and select Board Support Package Settings. At Overview > Standalone > xilisf settings, set the serial_flash_family value to 5. This defines that we have a Micron Quad SPI flash device.
- Now in the bootloader project source folder, open the blconfig.h file and set the FLASH_IMAGE_BASEADDR define value. In my case I set 0x00501000, because my Flash memory map looks in this way:
|.bit FPGA config file
.elf bootlader file
||0x004FFFFF (5 MB)
|.bin with Linux image
||0x00DFFFFF (9 MB)
||0x00FFFFFF (2 MB)
The reason why the Linux image starts from 0x00501000 instead of 0x00500000 is because the .bin file first data is the own file metadata and the process to upload the .bin file to the Flash memory does not delete it.
- Define the FLASH_IMAGE_SIZE in the bootloader.c source, in this case is 0x00900000 (9 MB) (In the file I uploaded its size is configured for 8 MB)
Generating ".mcs" file containing FPGA configuration, Bootloader and Linux Image
At this time we have these three parts, it is time to merge them into a single file.
- In Vivado, open the Project Manager view and go to Tools > Associate ELF Files...
For both, Design and Simulation Sources, search for the generated bootloader .elf file and regenerate the Bitstream sources. From this point the .bit file will contain the bootloader too and Microblaze will execute it on start.
- Once it ends and you have your .bit file, go to Hardware Manager view and then go to Tools > Generate Memory Configuration File. This is an screenshot of my configuration.
The FullImage.mcs is our key file :)
It only remains to put it into flash memory. Follow the same steps of the beginning of this post and select the FullImage.mcs file. The process will last a little as Flash image is not too quick writting, but after some minutes you will end.
Now open a terminal on the Arty Serial COM port and click on the Prog button (near the micro USB) to reload the FPGA config. The bootloader process will appear and after few seconds the Linux image will be booting :)