CycloneV: Programming FPGA from U-Boot

I have been using this guide to build an SD Card image to boot Linux on CycloneV.

One of the shortcomings of the guide appears to be that it does not include instructions on how to program the FPGA from u-boot in the CycloneV workflow. I have gotten around this using a boot script and modifying u-boot to run the script before booting the kernel.

echo --- Programming FPGA ---
echo -----Loading image------
# load rbf from FAT partition into memory
fatload mmc 0:1 ${fpgadata} socfpga.rbf;
# program FPGA
echo -----Print filesize-----
printenv filesize;
echo -----Program FPGA-------
fpga load 0 ${fpgadata} ${filesize};
# enable HPS-to-FPGA, FPGA-to-HPS, LWHPS-to-FPGA bridges
echo -----Enabling IFs--------
bridge enable;

I receive the following output during uboot operation before the kernel begins uncompressing and booting

Hit any key to stop autoboot: 0
449 bytes read in 3 ms (145.5 KiB/s)
Executing script at 02000000
— Programming FPGA —
-----Loading image------
7007204 bytes read in 366 ms (18.3 MiB/s)
-----Print filesize-----
filesize=6aebe4
-----Program FPGA-------
Command ‘load’ failed: Error -6
-----Enabling IFs--------
switch to partitions #0, OK
mmc0 is current device

After boot, I look at the fpga manager sysfs utility and see

root@cyclone5:~# cat /sys/class/fpga_manager/fpga0/state
write init

I was wondering if anyone has worked with CycloneV u-boot and might be able to tell what this error means and how to get around it.

Hello @jackfrye11,
Yours script looks right, it has the form that it should have.
The error could happen due to many reasons:

  1. The RBF file is generated in a form which does not corresponde with setting of Your hardware. The switches of the board need to be set in a proper positions. E.g. I use standard non-compressed RBF files, so I have to use FPGA MSEL switches “101011”.

  2. Some U-boot variables used at Your script has got wrong value. Try to get to the U-boot command line and print variables with printenv command.

  3. I have to use

    run bridge_enable_handoff;

    instead of Yours

    bridge enable;

    but it could depends on version of U-boot.

I just recommend to create new U-boot variable with name of target RBF file, e.g.

setenv RBF socfpga_test.rbf

and replace with it static RBF filename at boot script

fatload mmc 0:1 $fpgadata> $RBF

so You will not need to recompile and replace boot-script each time to change content of FPGA. Just change value of the variable. It is very fajn soution :sunny:.
Hope it could help You a bit.
Best wishes,
Yours Jan Konečný.

@JanKonecny

I wanted to address each of your possibilities. I believe only possibility two can be the cause.

  1. The RBF file is generated in a form which does not corresponde with setting of Your hardware. The switches of the board need to be set in a proper positions. E.g. I use standard non-compressed RBF files, so I have to use FPGA MSEL switches “101011”.

I am using a DE1-SoC board from Terasic. According to their user guide

 A brief view on FPGA manager
The FPGA manager in HPS configures the FPGA fabric from HPS. It also monitors the state of
FPGA and drives or samples signals to or from the FPGA fabric. The application software is
provided to configure FPGA through the FPGA manager. The FPGA configuration data is stored in
the file with .rbf extension. The MSEL[4:0] must be set to 01010 or 01110 before executing the
application software on HPS.

I do have a correct configuration, which is MSEL[4:0]=01010. Unless I am misreading this doc or my switches, I think this is not a concern. Perhaps there is a compression vs. non-compression of RBF issue. I do not know how to check whether the RBF is compressed or where to find out whether or not it should be, but this seems like a stretch.

  1. Some U-boot variables used at Your script has got wrong value. Try to get to the U-boot command line and print variables with printenv command.

Well, I tried a printenv on the size of the rbf file and it matches the size listed for the file in Nautilus file view in Ubuntu. What other variables could I print to check?

  1. I have to use

run bridge_enable_handoff;

instead of Yours

bridge enable;

but it could depends on version of U-boot.

Maybe, but that part comes after the FPGA fails to load. I may end up seeing another bug with the interfaces that this will fix, but I am focused on getting that error to go away on FPGA load first.

Any thoughts on debugging steps? How can I check compression of RBF?

I am sorry, but I suppose there is no tool to find out parameters of already generated RBF file at Quartus Prime. One could compare filesizes only but this not give You all the information.
However, the size of Your RBF file is exatly the same as non-compresed RBF file for Cyclone V. So, this variable should be right.
Could You also confirm that FAT partition is really the 1st partition, it contains the file and that $fpgadata is 0x2000000?
I am not sure about it but using curly-brackets should be used at U-boot within variables that are executed with run command, not within parameters of commands, aren’t they?

According to fdisk, this is the way my sdcard is partitioned

Command (m for help): p
Disk /dev/mmcblk0: 14.5 GiB, 15590227968 bytes, 30449664 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xe8c97bd9

Device Boot Start End Sectors Size Id Type
/dev/mmcblk0p1 2048 206848 204801 100M b W95 FAT32
/dev/mmcblk0p2 206849 821249 614401 300M 83 Linux
/dev/mmcblk0p3 821250 841730 20481 10M a2 unknown

I am not sure if this is right. I used the Python script mentioned in the guide in my first post to load the files onto the sd card and format it. In actuality, I had to find an updated script compatible with a newer Python version. That script can be found here.

https://raw.githubusercontent.com/rsarwar87/altera-soc-rootfs/master/make_sdimage2.py

Perhaps the script is improperly formatting the partitions. I appear to have run this command
$ sudo ./make_sdimage.py -f -P u-boot-with-spl.sfp,num=3,format=raw,size=10M,type=A2 -P sdfs/*,num=1,format=vfat,size=100M -P rootfs/*,num=2,format=ext3,size=300M -s 512M -n sdcard_cv.img
but I am not sure how the rbf got onto the sdcard.

Does the partitioning format look right or are there issues there?

Hello @jackfrye11,
well FAT partition is the 1st one, it is OK.
The script make_sdimage.py is usefull but to comperhand what it does I recommend You to create SD card manuály accroding to this great tutorial:


As far as You do not know, how RBF file got onto SD card, are You really really sure that it is placed there? Just insert SD card into Your desktop or notebook and look at the FAT partition (i.e. that disk which is 100 MB).
I am sorry, I still could not find where the error codes of U-Boot commands are placed.

@JanKonecny
I tried reformatting my SD Card according to the guide you posted. Instead of putting preloader-mkpimage.bin on the A2 then u-boot.img on the VFAT partition, I simply placed u-boot-with-spl.sfp on A2. ( u-boot-with-spl.sfp contains both preloader and uboot per this guide) Building Bootloader for Stratix 10 and Agilex | Documentation | RocketBoards.org

I only went up to step 7 and had a couple differences based on the files I generated from the first guide.

I got the following output when I booted.

U-Boot SPL 2019.04-00246-g0c3e6f623d-dirty (Dec 27 2019 - 13:35:52 -0500)
Trying to boot from MMC1

U-Boot 2019.04-00246-g0c3e6f623d-dirty (Dec 27 2019 - 13:35:52 -0500)

CPU: Altera SoCFPGA Platform
FPGA: Altera Cyclone V, SE/A5 or SX/C5 or ST/D5, version 0x0
BOOT: SD/MMC Internal Transceiver (3.0V)
Watchdog enabled
DRAM: 1 GiB
MMC: dwmmc0@ff704000: 0
Loading Environment from MMC… *** Warning - bad CRC, using default environment

In: serial
Out: serial
Err: serial
Model: Altera SOCFPGA Cyclone V SoC Development Kit
Net:
Warning: ethernet@ff702000 (eth0) using random MAC address - a2:77:81:44:49:7a
eth0: ethernet@ff702000
Hit any key to stop autoboot: 0
309 bytes read in 4 ms (75.2 KiB/s)

Executing script at 02000000

— Programming FPGA —
7007204 bytes read in 363 ms (18.4 MiB/s)
Command ‘load’ failed: Error -6
switch to partitions #0, OK
mmc0 is current device
Scanning mmc 0:1…
28016 bytes read in 6 ms (4.5 MiB/s)
starting USB…
USB0: scanning bus 0 for devices… 2 USB Device(s) found
scanning usb for storage devices… 0 Storage Device(s) found
ethernet@ff702000 Waiting for PHY auto negotiation to complete… TIMEOUT !
Could not initialize PHY ethernet@ff702000
missing environment variable: pxeuuid
missing environment variable: bootfile
Retrieving file: pxelinux.cfg/00000000
ethernet@ff702000 Waiting for PHY auto negotiation to complete… TIMEOUT !

The issue is clearly not how the SD Card is formatted. I would think the issue has to do with either

  1. The format of the RBF
  2. How U-Boot is attempting to load the RBF into the Cyclone V FPGA portion
  3. Differences between u-boot-with-spl.sfp and u-boot.img/preloader-mkpimage.bin

Do you agree? What could be my next step for debug? If you find the u-boot source with the error codes, please let me know. I tried surfing the github, but could not find it with searches.

Well, I think that I have found it. The list of error codes is at file

{Quartus Project folder}/software/spl_bsp/uboot-socfpga/include/asm-generic/errno.h

Error -6 means “No such device or address”.

One more note: Preloader and U-Boot should be compiled and placed at SD card together (preloader compiled as the first one, U-boot as the second one). Mixing versions (means different hardware configurations) of preloader and U-Boot could cause very strange problems such as Yours.
I am sorry I could not help You in a better way.

@JanKonecny
I will try various hardware images and see what happens. I wonder if it is a compatibility issue with some combination of

  1. Quartus
  2. SOC EDS (generates the preloader)
  3. uboot-socfpga

Is there somewhere (or some combination of versions/branches) you have used with Cyclone V with success?

It is highly recommended to use only the same versions together - i.e. use Intel SoC EDS of the same version as Intel Quartus Prime. Source code of U-Boot is a part of the Intel SoC EDS. Mixing them is not a good idea while looking for a source of problems!
I use version 17.1 due to the license of standard version which I purchased.

Hello @jackfrye11,
You could try to start with Golden Hardware Reference Design (GHRD) and Golden Software Reference Design (GSRD) and try to change their parts step by step, one by one according to Your target design. You would be able to identify the source of problem in this way.
Golden reference designes could be found at RocketBoards.org for Your board, e.g. for Altera Cyclone V SoC Board here:

I have no other idea how to help You now, I am sorry.
Best wishes.
Yours Jan Konecny.

@JanKonecny
Where in the install is the uboot source code?
I had used uboot-socfpga latest branch at

I am using the free lite version of the Quartus software and standard version of SOCEDS.

My Quartus version.txt

Version=19.1.0.670
[ACDS]
Version=19.1.0.670
Edition=lite

My SOCEDS version.txt

Version: 19.1, Build: 670

@JanKonecny
I also read the “official” Intel documentation here.
https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_soc_eds.pdf
This pointed me to here for directions on the Cyclone V boot flow

This appears to be an updated workflow from the link I posted earlier in this thread.
If you look at the boot logs for CycloneV vs Arria10, the Arria10 uboot log contains this line

FPGA: Start to program core bitstream …

While that from the CycloneV does not. Perhaps the CycloneV is not meant to be able to be programmed from u-boot in the new “official” flow?

Hello @jackfrye11,
well, the source code of U-Boot is part of Intel SoC EDS in a form of archive here:
“C:\intelFPGA\18.0\embedded\host_tools\altera\bootloaders\u-boot\uboot-socfpga.tar.gz” (of course, the path depends on Yours host OS, EDS version etc.).
However, the archive is of version 2013 (but this is not important) and is not meant to be extracted by You directly. It should be extracted with a tool called bsp-editor. This tool also adjusts the source code of U-Boot according to the hardware specialities of Your Quartus Prime project. You have to execute the bsp-editor tool from SoC EDS commad Shell.
I am sorry, I could not find the documents, where this is described.
Just do:

  1. Open SoC EDS Commnad Shell
  2. Type ‘bsp-editor &’
  3. Follow the instruction of 4th Chapter of Embedded Linux Beginners Guide
  4. Post generating source code with bsp-editor type ‘cd {folder of Yours Quartus Prime project}/software/spl_bsp/’
  5. Type ‘make’. The preloader will be compiled (it takes some tens of seconds), so a file preloader-mkpimage.bin will appear at the folder.
  6. Copy the preloader somewhere, e.g. to the root directory of the Quartus Prime project
  7. Type ‘make uboot’. The U-Boot wil be compiled (it takes some minutes), so a file ‘uboot.img’ will appear at the folder.
  8. Copy the U-Boot somewhere, too.
  9. The Preloader an U-Boot could be copied onto Your SD card now. You could use tool called alt-boot-disk-util form SoC EDS Command Shell. If You do not know ,how to use it, type ‘alt-boot-disk-util --help’.
    Hope this will help You a bit.
    Yours sincerelly Jan Konečný.

I guess I can use the v18.0 version of the tools. In the 19.1 version of the tools, when I follow your instructions and I get to step 5, after running $: make, I get

jfrye@jfrye-Inspiron-5547:~/Documents/FPGA/Intel/de1-soc_ref/Demonstrations/SOC_FPGA/hps_dma/software/spl_bsp$ make
Please visit Building Bootloader for Stratix 10 and Agilex | Documentation | RocketBoards.org for instructions on how to build the bootloader.

Hi @jackfrye11,

Did you manage to program the fpga?

I’m having the same issue using a cycloneV soc.

@RicardoSilva
Sorry, I haven’t had any luck. Perhaps next weekend I will perform a hardware build from scratch in Quartus 19.1 with HPS connected to GPIO in the FPGA then try to build the software around that and see if it works.

My current setup was to take the Terasic example designs ( https://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=205&No=836&PartNo=4
Under CD-ROM ) from the older versions of the tools, upgrade the IP, and rebuild. Perhaps there is some dependency that is broken in that process.

@RicardoSilva
Just did a Quartus 19.1 build from scratch following the HPS setup in this guide.

Section 9.3 SYSTEM DESIGN WITH QSYS – HPS
Rebuilt all software as from before. Same error.

Will try using Bitbake to build everything. The maintainer of this layer assures me that everything should work

Will let you know if I have any luck

I am neck deep in this issue right now. I really got stuck with the .dtb not working. I spent a day thinking there was something wrong with the kernel… but sopc2dtb does not work at all for me, not with a recent (5.4.x) kernel and 19.1 versions of Quartus standard.

I finally figured out I have to use the .dtsi files from the Kernel, and manually add in the information from my system --kind of a pain, would sure like to have a ‘process’.

I’m going to dig into the docs on DTS, and build myself a working .dtb. The final thing will be to try and load the fpga in u-boot.

I’ve seen 2 sets of code for u-boot. One seems to be an older version, and includes a boot.script file, that you compile into u-boot.scr. This file looks like this (example only)

echo -- Programming FPGA --
fatload mmc 0:1 $fpgadata soc_system.rbf;
fpga load 0 $fpgadata $filesize;
run bridge_enable_handoff;

echo -- Setting Env Variables --
setenv fdtimage soc_system.dtb;
setenv mmcroot /dev/mmcblk0p2;
setenv mmcload 'mmc rescan;${mmcloadcmd} mmc 0:${mmcloadpart} ${loadaddr} ${bootimage};${mmcloadcmd} mmc 0:${mmcloadpart} ${fdtaddr} ${fdtimage};';
setenv mmcboot 'setenv bootargs console=ttyS0,115200 root=${mmcroot} rw rootwait; bootz ${loadaddr} - ${fdtaddr}';

run mmcload;
run mmcboot;

After some digging into older (2013 ish) versions of u-boot source code, I found some code that creates environment variables in u-boot enviroment like fpgadata, and also a script for the bridge. Newer versions of u-boot source (git checkout a newer branch) do not populate those values, i.e. $fpgadata, and others. So, it seems as if it isn’t possible to do this programming.

I’ve tried to manually set fpgadagta to 0x0200000, and some other values (just guessing there), and I’ll get fpga load to “work”, but the fpga won’t actually program, so not really working.

Anyway, I’m still looking for a way to do this, and maybe the newer versions of u-boot have a different technique? If so, I’d like to find the (any) documentation on it.

Hey @sharpertool . I was stuck on this for months. Take a look at some of the stuff here.

(I reopened this question like 3 times when the problem ended up being misconfigured dip switches on my board.) This post has a lot of the elements/details I used to get my system working.

My recommended plan of action would be the following:

  1. Replicate what I have done. Get the thing to boot with
    linux-socfpga/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts at socfpga-5.5 · altera-opensource/linux-socfpga · GitHub

  2. Only once that is complete would I start playing with their device tree generator. I would compare to make sure that what it is generating has all the important hard stuff (MAC, etc) in the reference device tree. I also would not rely on it recognizing all of its own (proprietary Altera/Intel IP) peripherals. Even if it does, there is still the matter of ensuring that there is built-in kernel support and that you actually enable it when you build the kernel (I have not done this).

At this point, you will have to deal with your own peripherals. Are you doing custom IP in this design? I do not know if you are able to somehow integrate the Quartus IP development flow into their device tree generator tool. (Maybe you could fill me in on this one).

Obviously the tradeoff is

  1. How complicated the IP you are using is + driver support - how good the drivers actually are
    vs
  2. How quickly you can get something up and running.

For example I do not know if they have a PIO driver in their kernel, but I was trying to light some LEDs on my board. In that case, rather than going through device tree madness and driver kernel build config/platform device driver registration and figuring out how to use their software, I simply used /dev/mem and hit the registers manually. If it is something monstrously complicated like a soft MAC, maybe you go with their driver.

As you probably know, the benefit of loading at u-boot stage is that such kernel drivers can probe during kernel boot and set up/configure devices in the fabric.