Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save fm4dd/854532c1feaf22e07c8fa43c8fa487f1 to your computer and use it in GitHub Desktop.
Save fm4dd/854532c1feaf22e07c8fa43c8fa487f1 to your computer and use it in GitHub Desktop.
Converting the Terasic DE0-SoC FPGA development board from Yocto Linux to full Ubuntu 16.04

1. Introduction

The goal is to upgrade the Linux on Altera's DE0-Nano-SOC FPGA development board. To challenge us even further, the board confusingly also branded as the Atlas SoC board. The boards provided Linux version is from 2013, woefully outdated, and a stripped-down version. It comes with busybox instead of full commands, lacks all local development tools, and is requiring off-system cross-compiling.

root@socfpga:~# cat /etc/version
201309272205

root@socfpga:~# cat /etc/issue
Poky 8.0 (Yocto Project 1.3 Reference Distro) 1.3
 \l

root@socfpga:~# uname -r
3.13.0-00298-g3c7cbb9-dirty

On the bright side, the minimal linux image coming with Altera's DE0-Nano-SOC FPGA development board uses only 189MB.

root@socfpga:~# df -h /
Filesystem                Size      Used Available Use% Mounted on
/dev/root               975.9M    188.7M    736.0M  20% /

With the hardware being somewhat comparable to popular Raspberry Pi or Beagleboard platforms, DE0-SoC boards are missing the platform support convenience that comes with a adopted Linux distribution for the specific Altera platform.

Original SD card partioning:

root@socfpga:~# fdisk -l /dev/mmcblk0

Disk /dev/mmcblk0: 64.0 GB, 64021856256 bytes
4 heads, 16 sectors/track, 1953792 cylinders, total 125042688 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
Disk identifier: 0xd68e23ba

        Device Boot      Start         End      Blocks   Id  System
/dev/mmcblk0p1         2121728     3799447      838860    b  W95 FAT32
/dev/mmcblk0p2           14336     2111487     1048576   83  Linux
/dev/mmcblk0p3            2048        4095        1024   a2  Unknown 

Partition table entries are not in disk order

2. Online upgrade information

http://eewiki.net/display/linuxonarm/DE0-Nano-SoC+Kit, courtesy of Robert Nelson.

This approach requires approx 8-10 GB disk space.

3. Get prerequisite packages

First we need a ARM cross-compiler. Linaro provides one that is frequently used:

wget https://releases.linaro.org/components/toolchain/binaries/latest/arm-linux-gnueabihf/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf.tar.xz

tar xf gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf.tar.xz

export CC=`pwd`/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-

fm@lts1604:/srv/app/bc/ubuntu$ ${CC}gcc --version
arm-linux-gnueabihf-gcc (Linaro GCC 6.2-2016.11) 6.2.1 20161016
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Next we need a Boot loader that can jump-start the OS.

git clone https://github.com/u-boot/u-boot

fm@lts1604:/srv/app/bc/ubuntu$ cd u-boot/
fm@lts1604:/srv/app/bc/ubuntu/u-boot$ ls
api   board  common     configs  doc      dts       fs       Kbuild   lib       MAINTAINERS  net   README   snapshot.commit  tools
arch  cmd    config.mk  disk     drivers  examples  include  Kconfig  Licenses  Makefile     post  scripts  test
fm@lts1604:/srv/app/bc/ubuntu/u-boot$ git checkout v2017.01 -b tmp
Switched to a new branch 'tmp'

Now we patch it for the DE0-Nano-SoC board:

wget -c https://rcn-ee.com/repos/git/u-boot-patches/v2017.01/0001-de0_nano-fixes.patch

fm@lts1604:/srv/app/bc/ubuntu/u-boot$ patch -p1 < 0001-de0_nano-fixes.patch
patching file include/configs/socfpga_de0_nano_soc.h

Finally we compile the Boot Loader:

fm@lts1604:/srv/app/bc/ubuntu/u-boot$ make ARCH=arm CROSS_COMPILE=${CC} distclean
fm@lts1604:/srv/app/bc/ubuntu/u-boot$

fm@lts1604:/srv/app/bc/ubuntu/u-boot$ make ARCH=arm CROSS_COMPILE=${CC} socfpga_de0_nano_soc_defconfig
  HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/kconfig/conf.o
  SHIPPED scripts/kconfig/zconf.tab.c
  SHIPPED scripts/kconfig/zconf.lex.c
  SHIPPED scripts/kconfig/zconf.hash.c
  HOSTCC  scripts/kconfig/zconf.tab.o
  HOSTLD  scripts/kconfig/conf
#
# configuration written to .config
#
fm@lts1604:/srv/app/bc/ubuntu/u-boot$

fm@lts1604:/srv/app/bc/ubuntu/u-boot$ make ARCH=arm CROSS_COMPILE=${CC} u-boot-with-spl.sfp
scripts/kconfig/conf  --silentoldconfig Kconfig
  CHK     include/config.h
  UPD     include/config.h
  CFG     u-boot.cfg
  GEN     include/autoconf.mk
  GEN     include/autoconf.mk.dep
  CFG     spl/u-boot.cfg
  GEN     spl/include/autoconf.mk
  CHK     include/config/uboot.release
  UPD     include/config/uboot.release
  ...
  LD      spl/u-boot-spl
  OBJCOPY spl/u-boot-spl-nodtb.bin
  FDTGREP spl/u-boot-spl.dtb
  CAT     spl/u-boot-spl-dtb.bin
  COPY    spl/u-boot-spl.bin
  MKIMAGE spl/u-boot-spl.sfp
  OBJCOPY u-boot-nodtb.bin
  CAT     u-boot-dtb.bin
  COPY    u-boot.bin
  MKIMAGE u-boot.img
  SOCBOOT u-boot-with-spl.sfp

Now we build a Kernel:

fm@lts1604:/srv/app/bc/ubuntu$ git clone https://github.com/RobertCNelson/socfpga-kernel-dev
Cloning into 'socfpga-kernel-dev'...
remote: Counting objects: 283, done.
remote: Total 283 (delta 0), reused 0 (delta 0), pack-reused 283
Receiving objects: 100% (283/283), 804.01 KiB | 348.00 KiB/s, done.
Resolving deltas: 100% (187/187), done.
Checking connectivity... done.
fm@lts1604:/srv/app/bc/ubuntu$ cd socfpga-kernel-dev/
fm@lts1604:/srv/app/bc/ubuntu/socfpga-kernel-dev$ git checkout origin/v4.6.x -b tmp
Branch tmp set up to track remote branch v4.6.x from origin.
Switched to a new branch 'tmp'
fm@lts1604:/srv/app/bc/ubuntu/socfpga-kernel-dev$ vi version.sh
fm@lts1604:/srv/app/bc/ubuntu/socfpga-kernel-dev$ ./build_kernel.sh

Finally we get a pre-arranged minimal filesystem:

wget -c https://rcn-ee.com/rootfs/eewiki/minfs/ubuntu-16.04.1-minimal-armhf-2017-01-14.tar.xz

Write it all to SD card.

Clear out old partition table:

dd if=/dev/zero of=/dev/sdc bs=1M count=64

Write new partition table:

/dev/sdc1 1M Boot Loader /dev/sdc2 remaining space Linux

sfdisk /dev/sdc <<-__EOF__
1M,1M,0xA2,
,,,-
__EOF__

Write boot loader to /dev/sdc1:

dd if=u-boot/u-boot-with-spl.sfp of=/dev/sdc1

Format Linux partition:

mkfs.ext4 -L rootfs /dev/sdc2

Write file system to Linux partition:

tar xfvp ./*-*-*-armhf-*/armhf-rootfs-*.tar -C /media/fm/rootfs

Set uname_r in boot/uEnv.txt:

root@lts1604:/srv/app/bc/ubuntu# export kernel_version=4.6.5-socfpga-r1
root@lts1604:/srv/app/bc/ubuntu# sh -c "echo 'uname_r=${kernel_version}' > /media/fm/rootfs/boot/uEnv.txt"
root@lts1604:/srv/app/bc/ubuntu# cat /media/fm/rootfs/boot/uEnv.txt
uname_r=4.6.5-socfpga-r1

Copy kernel image:

root@lts1604:/srv/app/bc/ubuntu# cp -v ./socfpga-kernel-dev/deploy/${kernel_version}.zImage /media/fm/rootfs/boot/vmlinuz-${kernel_version}
'./socfpga-kernel-dev/deploy/4.6.5-socfpga-r1.zImage' -> '/media/fm/rootfs/boot/vmlinuz-4.6.5-socfpga-r1'

Copy device tree binaries:

root@lts1604:/srv/app/bc/ubuntu# mkdir -p /media/fm/rootfs/boot/dtbs/${kernel_version}/root@lts1604:/srv/app/bc/ubuntu# tar xfv ./socfpga-kernel-dev/deploy/${kernel_version}-dtbs.tar.gz -C /media/fm/rootfs/boot/dtbs/${kernel_version}/
./socfpga_arria10_socdk_nand.dtb
./socfpga_arria10_socdk_qspi.dtb
./socfpga_arria10_socdk_sdmmc.dtb
./socfpga_arria10_swvp.dtb
./socfpga_arria5_socdk.dtb
./socfpga_cyclone5_de0_sockit.dtb
./socfpga_cyclone5_mcvevk.dtb
./socfpga_cyclone5_socdk.dtb
./socfpga_cyclone5_sockit.dtb
./socfpga_cyclone5_socrates.dtb
./socfpga_cyclone5_trcom.dtb
./socfpga_vt.dtb

Copy Kernel modules:

tar xfv ./socfpga-kernel-dev/deploy/${kernel_version}-modules.tar.gz -C /media/rootfs/

Create Filesystem table:

sh -c "echo '/dev/mmcblk0p2  /  auto  errors=remount-ro  0  1' >> /media/rootfs/etc/fstab"

Specify device IP in /etc/network/interfaces:

# /etc/network/interfaces -- configuration file for ifup(8), ifdown(8)

# The loopback interface
auto lo
iface lo inet loopback

# Wireless interfaces
iface wlan0 inet dhcp
        wireless_mode managed
        wireless_essid any
        wpa-driver wext
        wpa-conf /etc/wpa_supplicant.conf

iface atml0 inet dhcp

# Wired or wireless interfaces
auto eth0
iface eth0 inet static
address 192.168.99.3
netmask 255.255.255.0
dns-nameservers 192.168.179.1

iface eth1 inet dhcp

# Ethernet/RNDIS gadget (g_ether)
# ... or on host side, usbnet and random hwaddr
iface usb0 inet static
        address 192.168.7.2
        netmask 255.255.255.0
        network 192.168.7.0
        gateway 192.168.7.1

# Bluetooth networking
iface bnep0 inet dhcp

Sync and umount the sdcard. Its now ready to boot. After boot, the login will prompt for username ubuntu with password temppwd. The remaining work includes setting up DNS, routing, adding Ubuntu repositories to /etc/apt/sources.list. And finally, we are able to run apt-get update / apt-get upgrade / apt-get install.

root@arm:/home/fm# df -h /
Filesystem      Size  Used Avail Use% Mounted on
/dev/root        59G  1.4G   55G   3% /
### 1. Introduction
The goal is to upgrade the Linux on Altera's DE0-Nano-SOC FPGA development board. To challenge us even further, the board confusingly also branded as the Atlas SoC board. The boards provided Linux version is from 2013, woefully outdated, and a stripped-down version. It comes with busybox instead of full commands, lacks all local development tools, and is requiring off-system cross-compiling.
<pre>root@socfpga:~# cat /etc/version
201309272205
root@socfpga:~# cat /etc/issue
Poky 8.0 (Yocto Project 1.3 Reference Distro) 1.3
\l
root@socfpga:~# uname -r
3.13.0-00298-g3c7cbb9-dirty</pre>
On the bright side, the minimal linux image coming with Altera's DE0-Nano-SOC FPGA development board uses only 189MB.
<pre>root@socfpga:~# df -h /
Filesystem Size Used Available Use% Mounted on
/dev/root 975.9M 188.7M 736.0M 20% /</pre>
With the hardware being somewhat comparable to popular Raspberry Pi or Beagleboard platforms, DE0-SoC boards are missing the platform support convenience that comes with a adopted Linux distribution for the specific Altera platform.
Original SD card partioning:
<pre>root@socfpga:~# fdisk -l /dev/mmcblk0
Disk /dev/mmcblk0: 64.0 GB, 64021856256 bytes
4 heads, 16 sectors/track, 1953792 cylinders, total 125042688 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
Disk identifier: 0xd68e23ba
Device Boot Start End Blocks Id System
/dev/mmcblk0p1 2121728 3799447 838860 b W95 FAT32
/dev/mmcblk0p2 14336 2111487 1048576 83 Linux
/dev/mmcblk0p3 2048 4095 1024 a2 Unknown </pre>
Partition table entries are not in disk order
### 2. Online upgrade information
http://eewiki.net/display/linuxonarm/DE0-Nano-SoC+Kit, courtesy of Robert Nelson.
This approach requires approx 8-10 GB disk space.
### 3. Get prerequisite packages
First we need a ARM cross-compiler. Linaro provides one that is frequently used:
<pre>wget https://releases.linaro.org/components/toolchain/binaries/latest/arm-linux-gnueabihf/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf.tar.xz
tar xf gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf.tar.xz
export CC=`pwd`/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
fm@lts1604:/srv/app/bc/ubuntu$ ${CC}gcc --version
arm-linux-gnueabihf-gcc (Linaro GCC 6.2-2016.11) 6.2.1 20161016
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.</pre>
Next we need a Boot loader that can jump-start the OS.
<pre>git clone https://github.com/u-boot/u-boot
fm@lts1604:/srv/app/bc/ubuntu$ cd u-boot/
fm@lts1604:/srv/app/bc/ubuntu/u-boot$ ls
api board common configs doc dts fs Kbuild lib MAINTAINERS net README snapshot.commit tools
arch cmd config.mk disk drivers examples include Kconfig Licenses Makefile post scripts test
fm@lts1604:/srv/app/bc/ubuntu/u-boot$ git checkout v2017.01 -b tmp
Switched to a new branch 'tmp'</pre>
Now we patch it for the DE0-Nano-SoC board:
<pre>wget -c https://rcn-ee.com/repos/git/u-boot-patches/v2017.01/0001-de0_nano-fixes.patch
fm@lts1604:/srv/app/bc/ubuntu/u-boot$ patch -p1 < 0001-de0_nano-fixes.patch
patching file include/configs/socfpga_de0_nano_soc.h</pre>
Here we are going to compile the Boot Loader:
<pre>fm@lts1604:/srv/app/bc/ubuntu/u-boot$ make ARCH=arm CROSS_COMPILE=${CC} distclean
fm@lts1604:/srv/app/bc/ubuntu/u-boot$
fm@lts1604:/srv/app/bc/ubuntu/u-boot$ make ARCH=arm CROSS_COMPILE=${CC} socfpga_de0_nano_soc_defconfig
HOSTCC scripts/basic/fixdep
HOSTCC scripts/kconfig/conf.o
SHIPPED scripts/kconfig/zconf.tab.c
SHIPPED scripts/kconfig/zconf.lex.c
SHIPPED scripts/kconfig/zconf.hash.c
HOSTCC scripts/kconfig/zconf.tab.o
HOSTLD scripts/kconfig/conf
#
# configuration written to .config
#
fm@lts1604:/srv/app/bc/ubuntu/u-boot$
fm@lts1604:/srv/app/bc/ubuntu/u-boot$ make ARCH=arm CROSS_COMPILE=${CC} u-boot-with-spl.sfp
scripts/kconfig/conf --silentoldconfig Kconfig
CHK include/config.h
UPD include/config.h
CFG u-boot.cfg
GEN include/autoconf.mk
GEN include/autoconf.mk.dep
CFG spl/u-boot.cfg
GEN spl/include/autoconf.mk
CHK include/config/uboot.release
UPD include/config/uboot.release
...
LD spl/u-boot-spl
OBJCOPY spl/u-boot-spl-nodtb.bin
FDTGREP spl/u-boot-spl.dtb
CAT spl/u-boot-spl-dtb.bin
COPY spl/u-boot-spl.bin
MKIMAGE spl/u-boot-spl.sfp
OBJCOPY u-boot-nodtb.bin
CAT u-boot-dtb.bin
COPY u-boot.bin
MKIMAGE u-boot.img
SOCBOOT u-boot-with-spl.sfp</pre>
Now we build a Kernel:
<pre>fm@lts1604:/srv/app/bc/ubuntu$ git clone https://github.com/RobertCNelson/socfpga-kernel-dev
Cloning into 'socfpga-kernel-dev'...
remote: Counting objects: 283, done.
remote: Total 283 (delta 0), reused 0 (delta 0), pack-reused 283
Receiving objects: 100% (283/283), 804.01 KiB | 348.00 KiB/s, done.
Resolving deltas: 100% (187/187), done.
Checking connectivity... done.
fm@lts1604:/srv/app/bc/ubuntu$ cd socfpga-kernel-dev/
fm@lts1604:/srv/app/bc/ubuntu/socfpga-kernel-dev$ git checkout origin/v4.6.x -b tmp
Branch tmp set up to track remote branch v4.6.x from origin.
Switched to a new branch 'tmp'
fm@lts1604:/srv/app/bc/ubuntu/socfpga-kernel-dev$ vi version.sh
fm@lts1604:/srv/app/bc/ubuntu/socfpga-kernel-dev$ ./build_kernel.sh</pre>
Lastly we download a pre-arranged minimal Ubuntu filesystem:
<pre>wget -c https://rcn-ee.com/rootfs/eewiki/minfs/ubuntu-16.04.1-minimal-armhf-2017-01-14.tar.xz</pre>
Let's write it all to SD card. First we clear out the SD cards old partition table:
<pre>dd if=/dev/zero of=/dev/sdc bs=1M count=64</pre>
The we write a new partition table using the following layout:
/dev/sdc1 1M Boot Loader
/dev/sdc2 remaining space Linux
I am using a 64GB SD from Samsung, which calculates as follows:
<pre>sfdisk /dev/sdc <<-__EOF__
1M,1M,0xA2,
,,,-
__EOF__</pre>
Ready write our boot loader to SD card on /dev/sdc1:
<pre>dd if=u-boot/u-boot-with-spl.sfp of=/dev/sdc1</pre>
Format the SD cards new partition with a Linux ext4 filesystem:
<pre>mkfs.ext4 -L rootfs /dev/sdc2</pre>
Write the downloaded minimal Ubuntu file system to Linux partition:
<pre>tar xfvp ./*-*-*-armhf-*/armhf-rootfs-*.tar -C /media/fm/rootfs</pre>
Set uname_r in boot/uEnv.txt:
<pre>root@lts1604:/srv/app/bc/ubuntu# export kernel_version=4.6.5-socfpga-r1
root@lts1604:/srv/app/bc/ubuntu# sh -c "echo 'uname_r=${kernel_version}' > /media/fm/rootfs/boot/uEnv.txt"
root@lts1604:/srv/app/bc/ubuntu# cat /media/fm/rootfs/boot/uEnv.txt
uname_r=4.6.5-socfpga-r1</pre>
Copy the newly build kernel image:
<pre>root@lts1604:/srv/app/bc/ubuntu# cp -v ./socfpga-kernel-dev/deploy/${kernel_version}.zImage /media/fm/rootfs/boot/vmlinuz-${kernel_version}
'./socfpga-kernel-dev/deploy/4.6.5-socfpga-r1.zImage' -> '/media/fm/rootfs/boot/vmlinuz-4.6.5-socfpga-r1'</pre>
Copy the device tree binaries:
<pre>root@lts1604:/srv/app/bc/ubuntu# mkdir -p /media/fm/rootfs/boot/dtbs/${kernel_version}/root@lts1604:/srv/app/bc/ubuntu# tar xfv ./socfpga-kernel-dev/deploy/${kernel_version}-dtbs.tar.gz -C /media/fm/rootfs/boot/dtbs/${kernel_version}/
./socfpga_arria10_socdk_nand.dtb
./socfpga_arria10_socdk_qspi.dtb
./socfpga_arria10_socdk_sdmmc.dtb
./socfpga_arria10_swvp.dtb
./socfpga_arria5_socdk.dtb
./socfpga_cyclone5_de0_sockit.dtb
./socfpga_cyclone5_mcvevk.dtb
./socfpga_cyclone5_socdk.dtb
./socfpga_cyclone5_sockit.dtb
./socfpga_cyclone5_socrates.dtb
./socfpga_cyclone5_trcom.dtb
./socfpga_vt.dtb</pre>
Copy the kernel modules:
<pre>tar xfv ./socfpga-kernel-dev/deploy/${kernel_version}-modules.tar.gz -C /media/rootfs/</pre>
Create the systems filesystem table /etc/fstab:
<pre>sh -c "echo '/dev/mmcblk0p2 / auto errors=remount-ro 0 1' >> /media/rootfs/etc/fstab"</pre>
Specify the device IP in /etc/network/interfaces:
<pre># /etc/network/interfaces -- configuration file for ifup(8), ifdown(8)
# The loopback interface
auto lo
iface lo inet loopback
# Wireless interfaces
iface wlan0 inet dhcp
wireless_mode managed
wireless_essid any
wpa-driver wext
wpa-conf /etc/wpa_supplicant.conf
iface atml0 inet dhcp
# Wired or wireless interfaces
auto eth0
iface eth0 inet static
address 192.168.99.3
netmask 255.255.255.0
dns-nameservers 192.168.179.1
iface eth1 inet dhcp
# Ethernet/RNDIS gadget (g_ether)
# ... or on host side, usbnet and random hwaddr
iface usb0 inet static
address 192.168.7.2
netmask 255.255.255.0
network 192.168.7.0
gateway 192.168.7.1
# Bluetooth networking
iface bnep0 inet dhcp</pre>
Finally, sync and unmount the sdcard. The new Ubuntu system is now ready to boot. After boot, the login will prompt for username ubuntu with password temppwd. The remaining work includes setting up DNS, routing, adding Ubuntu repositories to /etc/apt/sources.list. And finally, we are able to run apt-get update / apt-get upgrade / apt-get install.
<pre>root@arm:/home/fm# df -h /
Filesystem Size Used Avail Use% Mounted on
/dev/root 59G 1.4G 55G 3% /</pre>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment