Yeah, nah, aye

Main categories:

Porting Poky to Altera Cyclone V SoCFPGA

(A work in progress)


I purchased a Terasic DE10-Nano board, which is a minimal development platform for the Altera Cyclone V SoCFPGA - a dual core 800 MHz ARM Cortex-A9 SoC stuck on the same die as a low-end (but huge LUTs) FPGA. Terasic provide an SD card with Ångström Linux pre-loaded onto it, and this distribution boots fine, letting you play with this cool little platform. But, being an engineer, I'd rather "take it apart" than turn it on first. After making the first boot to check that the board didn't arrive faulty, I set to building my own distribution for the board, trying to stick to standard Yocto packages, rather than using custom packages like linux-altera and u-boot-socfpga. It's always more fun for me to steer away from potentially-stale vendor forks of open source components, and use the real upstreams themselves. Besides, These SoCs have been out long enough that decent support should already exist in the stock packages.


I found the original meta-de10-nano layer online, hosted by the usual suspect. I set the layer and its prerequisites up, changed the kernel and bootloader over to stock rather than vendor, and set to work stripping a bunch of (for now) unneeded packages such as LXDE and so on. Let's just get basic Linux with networking, FPGA interaction working first.

Within a couple of hours, I ironed many of the kinks, and had a rootfs produced by Yocto suitable for NFS booting. I next switched the init system over to systemd, and introduced some more problems that will need solving later. For now, my goal was getting the legacy SD card image upgraded to wic/wks images, so that I can boot the U-Boot produced by Yocto rather than the vendor one still on the SD card. I'd rather boot the current 2019.07 rather than the vendor version of the bootloader, even though it already works. It's one small part in the machine that is still "locked" into being vendor-supplied, and hopefully shouldn't be too much work to upgrade.

U-Boot saga

As established, the vendor U-Boot works fine. 2019.07 doesn't. The vendor U-Boot is actually some old thing from late 2017 with 6 patches applied on top of it, most of which seem to be hot fixes for getting the environment set up correctly, and for getting HDMI display working. Checking the patches against the commits in 2019.07, most of them have been included in mainline now. The only things missing are the HDMI setup patches, but I'm not interested in getting HDMI out of this board in U-Boot yet anyway.

So what doesn't work?

A kernel that boots fine under the vendor U-Boot doesn't boot under a stock 2019.07 U-Boot. Symptoms? Immediate freeze:

Speed: 1000, full duplex
Using ethernet@ff702000 device
TFTP from server; our IP address is
Filename 'socfpga_cyclone5_de10_nano.dtb'.
Load address: 0x2000000
Loading: ######
         4.8 MiB/s
Bytes transferred = 29940 (74f4 hex)
## Flattened Device Tree blob at 02000000
   Booting using the fdt blob at 0x2000000
   Loading Device Tree to 09ff5000, end 09fff4f3 ... OK

Starting kernel ...

Not good. Нехорошо. No output, no nothing. Not a sausage.

This implies something very, very early is failing. The way to open the window into the kernel's head in times like these is to recompile with CONFIG_LL_DEBUG, and enable at least earlyprintk (maybe even debug and then debug_initcall eventually) on the kernel command line. When we enable those, we get little more information:

[FIXME add boot freeze snippet]

By this point, it was time to get OpenOCD to drive the on-board JTAG blaster in order to have a look-see. Unfortunately, I wasn't able to get it to reliably halt the board, so it was more or less useless. Getting it working started to look like it would take longer than adding some debug prints to the kernel and recompiling a few times.

Eventually, with enough debug prints put into the suspect places, I narrowed the place of the lockup down to a series of readl calls that the kernel makes in amba_device_try_add. This function is called as part of the of_platform_default_populate_init initcall. initcalls are all executed very early in the kernel, so no wonder we needed CONFIG_LL_DEBUG.

With the cause of the lock-up being a readl, my sights turn away from the Linux kernel, and back to U-Boot. This is probably a hardware setup problem -the vendor U-Boot must be setting something up that the stock one isn't.

More to follow.