Last month I received Microchip PolarFire SoC FPGA Icicle development kit that features PolarFire SoC FPGA with a Penta–core 64-bit RISC-V CPU subsystem and an FPGA with 254K LE, and booted it into the pre-installed Linux operating systems based on OpenEmbedded.
Today, I’ll show how to get started with the Yocto BSP and run the EEMBC CoreMark benchmark, and I’ll check out the FPGA with Libero SoC Design Suite in a couple of weeks.
Operating Systems supported by PolarFire SoC FPGA
My initial idea was to focus this part of the review on Linux on RISC-V status, checking some system information, running some benchmarks (e.g. SBC-Bench), compiling the Linux kernel, and installing services like a LEMP stack (Linux, Nginx (pronounced Engine-X), MySQL, PHP) which could be used for WordPress hosting for instance. But then I looked at the operating systems supported with Microchip PolarFire SoC FPGA.
There’s a Yocto Linux BSP and a Buidlroot Linux BSP supported by Microchip, and Embedded Linux distributions from third parties like Siemens Embedded and WindRiver. FreeBSD is said to be coming soon, and several real-time operating systems should probably be for the small 64-bit RISC-V core from the SoC.
That means there’s no package manager and no Debian-based root filesystem excepted by some of the tools I planned to use. So while in theory, it would still be possible to achieve what I intended to do, I don’t have the 100+ hours required to achieve that… So I scaled down my ambition, and instead will report my experience building the Yocto images from images, cross-compile a hello world, and natively compile and run EEMBC benchmark. It’s not my first time playing with the Yocto Project, but I still learned a few things along the way, and I hope you will too.
Webserver demo and Voltage/Current Analytics
Before working on the Yocto BSP, I connected the board to Ethernet to complete Microchip’s getting started guide, and run a webserver.
1 2 |
$ cd /opt/microchip/iiohttpserver $ ./run |
We can access a web page that will show voltage and current for VDDA (XCVR Tx/Rx Lanes Supply), VDD25 (PLL and PNVM Supply), VDDA25 (XCVR PLL Supply), and VDD (Core Supply) by going to http://<board_ip_address>
It will be interesting to revisit this page once we run EEMBC CoreMark benchmark.
Yocto Linux BSP
Let’s build Linux using the Yocto BSP as explained on Github. For reference, I’m using a laptop running Ubuntu 20.04, and I had to change some of the commands.
First, let’s install the repo utility:
1 2 3 4 |
export REPO=$(mktemp /tmp/repo.XXXXXXXXX) curl -o ${REPO} https://storage.googleapis.com/git-repo-downloads/repo gpg --keyserver hkps://keyserver.ubuntu.com --recv-key 8BB9AD793E8E6153AF0F9A4416530D5E920F5C65 curl -s https://storage.googleapis.com/git-repo-downloads/repo.asc | gpg --verify - ${REPO} && install -m 755 ${REPO} ~/bin/repo |
then a few dependencies:
1 |
sudo apt install python3-distutils libyaml-dev libelf-dev chrpath diffstat |
Time to initialize the repo:
1 |
~/bin/repo init -u https://github.com/polarfire-soc/meta-polarfire-soc-yocto-bsp.git -b master -m tools/manifests/riscv-yocto.xml |
We can now configure the build:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
. ./meta-polarfire-soc-yocto-bsp/polarfire-soc_yocto_setup.sh /home/jaufranc/edev/Microchip/yocto-dev expect is already installed at the requested version (5.45.4-2build1) expect is already installed at the requested version (5.45.4-2build1) No packages will be installed, upgraded, or removed. 0 packages upgraded, 0 newly installed, 0 to remove and 9 not upgraded. Need to get 0 B of archives. After unpacking 0 B will be used. spawn sudo dpkg-reconfigure -freadline dash sudo] password for jaufranc: Configuring dash ---------------- The system shell is the default command interpreter for shell scripts. Using dash as the system shell will improve the system's overall performance. It does not alter the shell presented to interactive users. Use dash as the default system shell (/bin/sh)? [yes/no] yes Init OE ### Shell environment set up for builds. ### You can now run 'bitbake <target>' Common targets are: core-image-minimal core-image-full-cmdline core-image-sato core-image-weston meta-toolchain meta-ide-support You can also run generated qemu images with a command like 'runqemu qemux86'. Other commonly useful commands are: - 'devtool' and 'recipetool' handle common recipe tasks - 'bitbake-layers' handles common layer tasks - 'oe-pkgdata-util' handles common target package tasks Adding layers NOTE: Starting bitbake server... NOTE: Starting bitbake server... NOTE: Starting bitbake server... NOTE: Starting bitbake server... NOTE: Starting bitbake server... NOTE: Starting bitbake server... Creating auto.conf To build an image run --------------------------------------------------- MACHINE=icicle-kit-es bitbake mpfs-dev-cli --------------------------------------------------- Buildable machine info --------------------------------------------------- Default MACHINE=icicle-kit-es * icicle-kit-es: Microchip Polarfire SoC Icicle Kit Engineering Sample, emmc/sd boot. * qemuriscv64: The 64-bit RISC-V machine --------------------------------------------------- Bitbake Image --------------------------------------------------- * mpfs-dev-cli: MPFS Linux console-only image with development packages. * core-image-minimal-dev: OE console-only image, with some additional development packages. * core-image-minimal: OE console-only image * core-image-full-cmdline: OE console-only image with more full-featured Linux system functionality installed. * qemuriscv64: The 64-bit RISC-V machine --------------------------------------------------- |
To start the build, run the following command:
1 |
MACHINE=icicle-kit-es bitbake mpfs-dev-cli |
I remember Yocto build system can take a lot of time having spent over 24 hours building an image on a low-end laptop about 10 years ago, and with the default settings, my laptop, powered by an 8-core AMD Ryzen 7 2700U processor and fitted with 16 GB RAM, quickly become very slow and close to unusable with a 50+ CPU load:
I let the build run its course as I went to bed after launching it. But I did not check the storage requirements, and the build stops after about two hours with my hard drive running out of space. As we’ll see once the build is completed, around 100 GB of free storage is required.
While we are on the topic of system requirements, Libero SoC design suite will need around 35 GB extra space, and for PolarFire SoC development at least 16 GB RAM. So you’ll want to have a powerful workstation to develop applications on PolarFire SoC FPGA Icicle development kit with plenty of RAM and sufficient storage.
Back to our Yocto build. The ideal would be to have a dedicated build server, but if you intend to use your computer at the same time as the build take place you may want to edit [your_yocto_build_dir]/conf/local.conf
1 2 |
BB_NUMBER_THREADS = "4" PARALLEL_MAKE = "-j 4" |
then
1 |
source setup-environment ./your_build_folder |
Before starting the build…
An alternative is to pause the build with Ctrl-Z, which works in a similar way to Ctrl-C, but uses SIGTSTP instead of SIGINT in order to pause the process, and not terminate it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
time MACHINE=icicle-kit-es bitbake mpfs-dev-cli Loading cache: 100% | | ETA: --:--:-- Loaded 0 entries from dependency cache. Parsing recipes: 100% |##########################################| Time: 0:01:43 Parsing of 2381 .bb files complete (0 cached, 2381 parsed). 3667 targets, 166 skipped, 0 masked, 0 errors. NOTE: Resolving any missing task queue dependencies Build Configuration: BB_VERSION = "1.51.0" BUILD_SYS = "x86_64-linux" NATIVELSBSTRING = "ubuntu-20.04" TARGET_SYS = "riscv64-oe-linux" MACHINE = "icicle-kit-es" DISTRO = "nodistro" DISTRO_VERSION = "nodistro.0" TUNE_FEATURES = "riscv64" meta = "HEAD:14795ee305f3c11fcc31cc7ca815b8ff1020e29a" meta-oe meta-python meta-multimedia meta-networking = "HEAD:dcb9ecc1e5720c9614b1cd27575e1e4886dff5c1" meta-riscv = "HEAD:35d1d5849294ff9f2fb98b90657bbf7a1e532d0d" meta-polarfire-soc-yocto-bsp = "HEAD:3c53ffcae8ac86686a53cd15b4541fc7eca1e36f" NOTE: Fetching uninative binary shim http://downloads.yoctoproject.org/releases/uninative/3.1/x86_64-nativesdk-libc.tar.xz;sha256sum=5d0611df544edff6428cef7d871257a91aa6ba1bd92f5365a2df8deb54b6b31e (will check PREMIRRORS first) Initialising tasks: 100% |#######################################| Time: 0:00:11 Sstate summary: Wanted 2529 Local 0 Network 0 Missed 2529 Current 0 (0% match, 0% complete) NOTE: Executing Tasks WARNING: expat-native-2.3.0-r0 do_fetch: Failed to fetch URL https://downloads.sourceforge.net/expat/expat-2.3.0.tar.bz2, attempting MIRRORS if available WARNING: libtalloc-2.3.2-r0 do_fetch: Failed to fetch URL https://www.samba.org/ftp/talloc/talloc-2.3.2.tar.gz, attempting MIRRORS if available WARNING: boost-1.76.0-r0 do_fetch: Failed to fetch URL https://dl.bintray.com/boostorg/release/1.76.0/source/boost_1_76_0.tar.bz2, attempting MIRRORS if available WARNING: htop-3.0.5-r0 do_fetch: Failed to fetch URL git://github.com/htop-dev/htop.git, attempting MIRRORS if available Currently 8 running tasks (5382 of 7084) 75% |####################### | Currently 6 running tasks (6040 of 7084) 85% |########################## | 0: cmake-3.20.1-r0 do_compile (pid 3565535) 72% |#################### | 1: boost-1.76.0-r0 do_compile - 24m44s (pid 3578779) 2: kernel-devsrc-1.0-r0 do_install - 15m17s (pid 3619862) 3: gcc-11.1.0-r0 do_package_write_ipk - 1m23s (pid 3665048) 4: libcheck-0.15.2-r0 do_package_write_ipk - 32s (pid 3669480) 5: libsamplerate0-0.1.9-r1 do_package_write_ipk - 24s (pid 3669801) [1]+ Stopped MACHINE=icicle-kit-es bitbake mpfs-dev-cli real 328m42.945s user 0m0.000s sys 0m0.004s jaufranc@cnx-laptop-4:~/edev/Microchip/yocto-dev/build$ |
Since bitbake spawns so many other processes, we have to wait for them to complete, and it took about 10 minutes to get back to having a usual computer.
I stopped for about 3 hours, and then it can be resumed with the command “fg“. It’s like a hibernation mode for terminal programs, and it’s been around forever, but I either forgot about it, or never used it myself. The complete build took around 7 to 8 hours on my machine.
That’s the space used by the Yocto BSP:
1 2 3 4 5 6 7 8 |
~/edev/Microchip/yocto-dev$ du --max-depth=1 -h 313M ./.repo 36M ./meta-openembedded 376K ./meta-polarfire-soc-yocto-bsp 6.3M ./meta-riscv 94G ./build 45M ./openembedded-core 94G . |
We can find the images in tmp-glibc/deploy/images/icicle-kit-es/ folder:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
ls -lh tmp-glibc/deploy/images/icicle-kit-es/ total 9.8G -rwxr-xr-x 1 jaufranc jaufranc 1.3K Sep 26 18:06 boot.scr.uimg lrwxrwxrwx 2 jaufranc jaufranc 68 Sep 26 18:07 fitImage -> fitImage--5.12.1+git0+ce6fc289da-r0-icicle-kit-es-20210926061423.bin -rw-r--r-- 2 jaufranc jaufranc 4.6M Sep 26 18:07 fitImage--5.12.1+git0+ce6fc289da-r0-icicle-kit-es-20210926061423.bin lrwxrwxrwx 2 jaufranc jaufranc 68 Sep 26 18:07 fitImage-icicle-kit-es.bin -> fitImage--5.12.1+git0+ce6fc289da-r0-icicle-kit-es-20210926061423.bin -rw-r--r-- 2 jaufranc jaufranc 1.7K Sep 26 18:08 fitImage-its--5.12.1+git0+ce6fc289da-r0-icicle-kit-es-20210926061423.its lrwxrwxrwx 2 jaufranc jaufranc 72 Sep 26 18:08 fitImage-its-icicle-kit-es -> fitImage-its--5.12.1+git0+ce6fc289da-r0-icicle-kit-es-20210926061423.its -rw-r--r-- 2 jaufranc jaufranc 4.6M Sep 26 18:08 fitImage-linux.bin--5.12.1+git0+ce6fc289da-r0-icicle-kit-es-20210926061423.bin lrwxrwxrwx 2 jaufranc jaufranc 78 Sep 26 18:08 fitImage-linux.bin-icicle-kit-es -> fitImage-linux.bin--5.12.1+git0+ce6fc289da-r0-icicle-kit-es-20210926061423.bin -rw-r--r-- 2 jaufranc jaufranc 11K Sep 26 18:08 microchip-mpfs-icicle-kit--5.12.1+git0+ce6fc289da-r0-icicle-kit-es-20210926061423.dtb lrwxrwxrwx 2 jaufranc jaufranc 85 Sep 26 18:08 microchip-mpfs-icicle-kit.dtb -> microchip-mpfs-icicle-kit--5.12.1+git0+ce6fc289da-r0-icicle-kit-es-20210926061423.dtb lrwxrwxrwx 2 jaufranc jaufranc 85 Sep 26 18:08 microchip-mpfs-icicle-kit-icicle-kit-es.dtb -> microchip-mpfs-icicle-kit--5.12.1+git0+ce6fc289da-r0-icicle-kit-es-20210926061423.dtb lrwxrwxrwx 2 jaufranc jaufranc 38 Sep 26 18:06 mmc-tftp-icicle-kit-es.txt -> mmc-tftp-icicle-kit-es-v2021.04-r0.txt -rw-r--r-- 2 jaufranc jaufranc 1.2K Sep 26 18:06 mmc-tftp-icicle-kit-es-v2021.04-r0.txt lrwxrwxrwx 2 jaufranc jaufranc 38 Sep 26 18:06 mmc-tftp.txt -> mmc-tftp-icicle-kit-es-v2021.04-r0.txt -rw-r--r-- 2 jaufranc jaufranc 1.6M Sep 26 18:08 modules--5.12.1+git0+ce6fc289da-r0-icicle-kit-es-20210926061423.tgz lrwxrwxrwx 2 jaufranc jaufranc 67 Sep 26 18:08 modules-icicle-kit-es.tgz -> modules--5.12.1+git0+ce6fc289da-r0-icicle-kit-es-20210926061423.tgz -rw-r--r-- 2 jaufranc jaufranc 5.1K Sep 27 09:29 mpfs-dev-cli.env -rw-r--r-- 2 jaufranc jaufranc 5.4G Sep 27 09:46 mpfs-dev-cli-icicle-kit-es-20210927021251.rootfs.ext4 -rw-r--r-- 2 jaufranc jaufranc 103K Sep 27 09:27 mpfs-dev-cli-icicle-kit-es-20210927021251.rootfs.manifest -rw-r--r-- 2 jaufranc jaufranc 5.5G Sep 27 09:50 mpfs-dev-cli-icicle-kit-es-20210927021251.rootfs.wic -rw-r--r-- 2 jaufranc jaufranc 1.4G Sep 27 09:58 mpfs-dev-cli-icicle-kit-es-20210927021251.rootfs.wic.gz -rw-r--r-- 2 jaufranc jaufranc 225K Sep 27 09:27 mpfs-dev-cli-icicle-kit-es-20210927021251.testdata.json lrwxrwxrwx 2 jaufranc jaufranc 53 Sep 27 09:46 mpfs-dev-cli-icicle-kit-es.ext4 -> mpfs-dev-cli-icicle-kit-es-20210927021251.rootfs.ext4 lrwxrwxrwx 2 jaufranc jaufranc 57 Sep 27 09:27 mpfs-dev-cli-icicle-kit-es.manifest -> mpfs-dev-cli-icicle-kit-es-20210927021251.rootfs.manifest lrwxrwxrwx 2 jaufranc jaufranc 55 Sep 27 09:27 mpfs-dev-cli-icicle-kit-es.testdata.json -> mpfs-dev-cli-icicle-kit-es-20210927021251.testdata.json lrwxrwxrwx 2 jaufranc jaufranc 52 Sep 27 09:58 mpfs-dev-cli-icicle-kit-es.wic -> mpfs-dev-cli-icicle-kit-es-20210927021251.rootfs.wic lrwxrwxrwx 2 jaufranc jaufranc 55 Sep 27 09:58 mpfs-dev-cli-icicle-kit-es.wic.gz -> mpfs-dev-cli-icicle-kit-es-20210927021251.rootfs.wic.gz -rwxr-xr-x 1 jaufranc jaufranc 477K Sep 26 22:30 payload.bin lrwxrwxrwx 2 jaufranc jaufranc 36 Sep 26 18:06 u-boot.bin -> u-boot-icicle-kit-es-v2021.04-r0.bin lrwxrwxrwx 2 jaufranc jaufranc 36 Sep 26 18:06 u-boot-icicle-kit-es.bin -> u-boot-icicle-kit-es-v2021.04-r0.bin -rw-r--r-- 2 jaufranc jaufranc 476K Sep 26 18:06 u-boot-icicle-kit-es-v2021.04-r0.bin lrwxrwxrwx 2 jaufranc jaufranc 49 Sep 26 18:06 u-boot-mpfs-initial-env -> u-boot-mpfs-initial-env-icicle-kit-es-v2021.04-r0 lrwxrwxrwx 2 jaufranc jaufranc 49 Sep 26 18:06 u-boot-mpfs-initial-env-icicle-kit-es -> u-boot-mpfs-initial-env-icicle-kit-es-v2021.04-r0 -rw-r--r-- 2 jaufranc jaufranc 3.2K Sep 26 18:06 u-boot-mpfs-initial-env-icicle-kit-es-v2021.04-r0 |
The uncompressed image is 5.5GB large so it would be into an 8GB SD card, but 16GB or 32GB cards are recommended. This is the command provided by Microchip to flash it to an SD card:
1 |
zcat tmp-glibc/deploy/images/icicle-kit-es/mpfs-dev-cli-icicle-kit-es.wic.gz | sudo dd of=/dev/sdX bs=4096 iflag=fullblock oflag=direct conv=fsync status=progress |
But if you want image verification, utilities like USBImager would be preferred. That’s what I used to flash the image to a 32GB SD card, which I then inserted into the SD card slot of the board to try it out.
Let’s interrupt the boot to check the SD card is detected:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
U-Boot 2021.04 (Sep 26 2021 - 09:16:21 +0000) CPU: rv64imafdc Model: Microchip MPFS Icicle Kit DRAM: 2 GiB MMC: mmc@20008000: 0 In: serial@20100000 Out: serial@20100000 Err: serial@20100000 Net: eth0: ethernet@20112000 Hit any key to stop autoboot: 0 RISC-V # mmcinfo Device: mmc@20008000 Manufacturer ID: 0 OEM: 3432 Name: SD16G Bus Speed: 50000000 Mode: SD High Speed (50MHz) Rd Block Len: 512 SD version 3.0 High Capacity: Yes Capacity: 29.1 GiB Bus Width: 4-bit Erase Group Size: 512 Bytes |
All good, let’s carry on… and it fails to switch to the kernel. I eventually reflashed the image using the uncompressed binary, and I could login to the terminal:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
root@icicle-kit-es:~# uname -a Linux icicle-kit-es 5.12.1 #1 SMP Sun Sep 26 08:45:19 UTC 2021 riscv64 riscv64 riscv64 GNU/Linux root@icicle-kit-es:~# df -g df: invalid option -- 'g' Try 'df --help' for more information. root@icicle-kit-es:~# df -f df: invalid option -- 'f' Try 'df --help' for more information. root@icicle-kit-es:~# df -h Filesystem Size Used Avail Use% Mounted on /dev/root 5.2G 4.2G 733M 86% / devtmpfs 817M 0 817M 0% /dev tmpfs 818M 0 818M 0% /dev/shm tmpfs 327M 9.5M 318M 3% /run tmpfs 4.0M 0 4.0M 0% /sys/fs/cgroup tmpfs 818M 0 818M 0% /tmp tmpfs 818M 100K 818M 1% /var/volatile tmpfs 164M 0 164M 0% /run/user/0 root@icicle-kit-es:~# fdisk -l GPT PMBR size mismatch (11334293 != 61067263) will be corrected by write. The backup GPT table is not on the end of the device. Disk /dev/mmcblk0: 29.12 GiB, 31266439168 bytes, 61067264 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: gpt Disk identifier: 707A61C6-0BE8-405E-BF47-9E8071F3EEC9 Device Start End Sectors Size Type /dev/mmcblk0p1 8192 47009 38818 19M Microsoft basic data /dev/mmcblk0p2 47010 63393 16384 8M BIOS boot /dev/mmcblk0p3 65536 11334259 11268724 5.4G Linux filesystem |
The rootfs was not resized automatically, and it seems there’s a problem with the GPT table… I’m not quite sure what happened here. But since our self-built image is working, and we have an eMMC flash let’s flash it to the internal storage instead.
Power off the board, remove the SD card, and connect to ttyUSB0 with Bootterm to access the HSS terminal:
1 |
bt ttyUSB0 |
Before restarting the board, interrupting the boot, and type “usbdmsc
” to expose the eMMC flash as a USB mass storage to our Ubuntu laptop.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
[5.623947] HSS_MMCInit(): Attempting to select eMMC ... Passed Press a key to enter CLI, ESC to skip Timeout in 5 seconds .[6.915522] HSS_ShowTimeout(): Character 32 pressed [6.921945] HSS_TinyCLI_Parser(): Type HELP for list of commands [6.929236] HSS_TinyCLI_Parser(): >> usbdmsc [27.703151] HSS_TinyCLI_Execute(): Unknown command >><<. [27.710094] HSS_TinyCLI_Parser(): >> usbdmsc [37.207116] HSS_MMCInit(): Attempting to select SDCARD ... [38.215220] mmc_init_common(): MSS_MMC_init() returned unexpected 0 Failed [38.223900] HSS_MMCInit(): Attempting to select eMMC ... Passed Waiting for USB Host to connect... (CTRL-C to quit) USB Host connected. Waiting for disconnect... (CTRL-C to quit) 664064 bytes written, 21166080 bytes read |
We’ll need another Micro USB cable connected to J16 Micro USB port to see the flash in Ubuntu.
We can unmount the Boot and root partitions before flashing the image as we did for the SD card. I tried with the gz image first, but I had the same problem as with the SD card with the root partition failing to mount even on PC, so I went with the uncompressed image, and everything went smoothly.
After completion, we can remove the micro USB cable connected to J16, and access our Linux image…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
jaufranc@cnx-laptop-4:~/edev/Microchip/yocto-dev/build$ bt ttyUSB1 Trying port ttyUSB1... Connected to ttyUSB1 at 115200 bps. Escape character is 'Ctrl-]'. Use escape followed by '?' for help. icicle-kit-es login: root root@icicle-kit-es:~# uname -a Linux icicle-kit-es 5.12.1 #1 SMP Sun Sep 26 08:45:19 UTC 2021 riscv64 riscv64 riscv64 GNU/Linux root@icicle-kit-es:~# df -h Filesystem Size Used Avail Use% Mounted on /dev/root 5.2G 4.2G 733M 86% / devtmpfs 817M 0 817M 0% /dev tmpfs 818M 0 818M 0% /dev/shm tmpfs 327M 9.6M 318M 3% /run tmpfs 4.0M 0 4.0M 0% /sys/fs/cgroup tmpfs 818M 0 818M 0% /tmp tmpfs 818M 100K 818M 1% /var/volatile tmpfs 164M 0 164M 0% /run/user/0 root@icicle-kit-es:~# |
Hello World Cross-Compilation
Let’s try to cross-compile the Hello World program.
1 2 3 4 5 |
#include <stdio.h> int main() { printf("Hello, World!\n"); return 0; } |
for RISC-V using the Yocto toolchain, which we’ll first add to our path:
1 |
export PATH=$PATH:~/edev/Microchip/yocto-dev/build/tmp-glibc/sysroots-components/x86_64/gcc-cross-riscv64/usr/bin/riscv64-oe-linux |
and use the RISCV GCC tool to build it:
1 2 3 4 5 |
riscv64-oe-linux-gcc hello.c -o hello hello.c:1:10: fatal error: stdio.h: No such file or directory 1 | #include <stdio.h> | ^~~~~~~~~ compilation terminated. |
Oops, it does not work as expected. It looks like the toolchain is not properly installed, or I used the wrong one. I’ve tried to play with CFLAGS, but no luck… Maybe it’s only supposed to work within Yocto/Bitbake framework… I’ve got more experience with buildroot, and usually the cross-compilation toolchain works out of the box.
EEMBC CoreMark Benchmark
So I’ll build EEMBC CoreMark natively, i.e. directly on the board. The image we’ve built comes with git and the GNU GCC toolchain so it should be straightforward.
1 2 3 |
https://github.com/eembc/coremark cd coremark/ make -j4 |
This both builds and runs CoreMark with two files generated
- run1.log
12345678910111213141516172K performance run parameters for coremark.CoreMark Size : 666Total ticks : 14935Total time (secs): 14.935000Iterations/Sec : 1339.136257Iterations : 20000Compiler version : GCC11.1.0Compiler flags : -O2 -DPERFORMANCE_RUN=1 -lrtMemory location : Please put data memory location here(e.g. code in flash, data on heap etc)seedcrc : 0xe9f5[0]crclist : 0xe714[0]crcmatrix : 0x1fd7[0]crcstate : 0x8e3a[0]crcfinal : 0x382fCorrect operation validated. See README.md for run and reporting rules.CoreMark 1.0 : 1339.136257 / GCC11.1.0 -O2 -DPERFORMANCE_RUN=1 -lrt / Heap - run2.log
123456789101112131415162K validation run parameters for coremark.CoreMark Size : 666Total ticks : 14907Total time (secs): 14.907000Iterations/Sec : 1341.651573Iterations : 20000Compiler version : GCC11.1.0Compiler flags : -O2 -DPERFORMANCE_RUN=1 -lrtMemory location : Please put data memory location here(e.g. code in flash, data on heap etc)seedcrc : 0x18f2[0]crclist : 0xe3c1[0]crcmatrix : 0x0747[0]crcstate : 0x8d84[0]crcfinal : 0xd304Correct operation validated. See README.md for run and reporting rules.
The board achieved a 1339.136257 score, or about 2.23 CoreMark/MHz since the RISC-V cores run at 600 MHz. But Microchip reports 3.25 CoreMark/MHz on the board. Let’s try again with the same flags as used by the company:
1 2 |
make clean make XCFLAGS="-O3 -DHAS_STDIO -DHAS_TIME_H -DUSE_CLOCK -fno-common -funroll-loops -finline-functions -falign-functions=16 -falign-jumps=4 -falign-loops=4 -finline-limit=1000 -fno-if-conversion2 -fselective-scheduling -fno-tree-dominator-opts -lpthread -DHAS_FLOAT=0 -mtune=sifive-7-series" |
This is the content of run1.log:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
2K performance run parameters for coremark. CoreMark Size : 666 Total ticks : 12874295 Total time (secs): 12 Iterations/Sec : 1666 Iterations : 20000 Compiler version : GCC11.1.0 Compiler flags : -O2 -O3 -DHAS_STDIO -DHAS_TIME_H -DUSE_CLOCK -fno-common -funroll-loops -finline-functions -falign-functions=16 -falign-jumps=4 -falign-loops=4 -finline-limit=1000 -fno-if-conversion2 -fselective-scheduling -fno-tree-dominator-opts -lpthread -DHAS_FLOAT=0 -mtune=sifive-7-series -DPERFORMANCE_RUN=1 -lrt Memory location : Please put data memory location here (e.g. code in flash, data on heap etc) seedcrc : 0xe9f5 [0]crclist : 0xe714 [0]crcmatrix : 0x1fd7 [0]crcstate : 0x8e3a [0]crcfinal : 0x382f Correct operation validated. See README.md for run and reporting rules. |
Somehow the CoreMark score is nowhere to be found, but we still have the Iterations/Sec that went from 1341.651573 to 1666. So it’s improved. It’s easy to see why the score did not show by looking at the code:
1 2 3 4 5 6 7 8 9 10 11 |
ee_printf( "Correct operation validated. See README.md for run and reporting " "rules.\n"); #if HAS_FLOAT if (known_id == 3) { ee_printf("CoreMark 1.0 : %f / %s %s", default_num_contexts * results[0].iterations / time_in_secs(total_time), COMPILER_VERSION, COMPILER_FLAGS); |
Let’s repeat this with -DHAS_FLOAT=1 instead…
1 |
make clean make XCFLAGS="-O3 -DHAS_STDIO -DHAS_TIME_H -DUSE_CLOCK -fno-common -funroll-loops -finline-functions -falign-functions=16 -falign-jumps=4 -falign-loops=4 -finline-limit=1000 -fno-if-conversion2 -fselective-scheduling -fno-tree-dominator-opts -lpthread -DHAS_FLOAT=1 -mtune=sifive-7-series" |
This time it looks correct:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
2K performance run parameters for coremark. CoreMark Size : 666 Total ticks : 12842191 Total time (secs): 12.842191 Iterations/Sec : 1557.366652 Iterations : 20000 Compiler version : GCC11.1.0 Compiler flags : -O2 -O3 -DHAS_STDIO -DHAS_TIME_H -DUSE_CLOCK -fno-common -funroll-loops -finline-functions -falign-functions=16 -falign-jumps=4 -falign-loops=4 -finline-limit=1000 -fno-if-conversion2 -fselective-scheduling -fno-tree-dominator-opts -lpthread -DHAS_FLOAT=1 -mtune=sifive-7-series -DPERFORMANCE_RUN=1 -lrt Memory location : Please put data memory location here (e.g. code in flash, data on heap etc) seedcrc : 0xe9f5 [0]crclist : 0xe714 [0]crcmatrix : 0x1fd7 [0]crcstate : 0x8e3a [0]crcfinal : 0x382f Correct operation validated. See README.md for run and reporting rules. CoreMark 1.0 : 1557.366652 / GCC11.1.0 -O2 -O3 -DHAS_STDIO -DHAS_TIME_H -DUSE_CLOCK -fno-common -funroll-loops -finline-functions -falign-functions=16 -falign-jumps=4 -falign-loops=4 -finline-limit=1000 -fno-if-conversion2 -fselective-scheduling -fno-tree-dominator-opts -lpthread -DHAS_FLOAT=1 -mtune=sifive-7-series -DPERFORMANCE_RUN=1 -lrt / Heap |
But that’s only 2.59 CoreMark/Mhz, still not quite up to 3.125 CoreMark/MHz. Actually, it matches Microchip’s results using unsigned index. Somebody tried to do the same and was advised to change the code in posix/core_portme.h to use signed index:
1 |
typedef signed int ee_u32; |
After running the benchmark again, the score is even higher:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
2K performance run parameters for coremark. CoreMark Size : 666 Total ticks : 16767651 Total time (secs): 16.767651 Iterations/Sec : 1789.159376 Iterations : 30000 Compiler version : GCC11.1.0 Compiler flags : -O2 -O3 -DHAS_STDIO -DHAS_TIME_H -DUSE_CLOCK -fno-common -funroll-loops -finline-functions -falign-functions=16 -falign-jumps=4 -falign-loops=4 -finline-limit=1000 -fno-if-conversion2 -fselective-scheduling -fno-tree-dominator-opts -lpthread -DHAS_FLOAT=1 -mtune=sifive-7-series -DPERFORMANCE_RUN=1 -lrt Memory location : Please put data memory location here (e.g. code in flash, data on heap etc) seedcrc : 0xe9f5 [0]crclist : 0xe714 [0]crcmatrix : 0x1fd7 [0]crcstate : 0x8e3a [0]crcfinal : 0x5275 Correct operation validated. See README.md for run and reporting rules. CoreMark 1.0 : 1789.159376 / GCC11.1.0 -O2 -O3 -DHAS_STDIO -DHAS_TIME_H -DUSE_CLOCK -fno-common -funroll-loops -finline-functions -falign-functions=16 -falign-jumps=4 -falign-loops=4 -finline-limit=1000 -fno-if-conversion2 -fselective-scheduling -fno-tree-dominator-opts -lpthread -DHAS_FLOAT=1 -mtune=sifive-7-series -DPERFORMANCE_RUN=1 -lrt / Heap |
1789.159376 CoreMark corresponds to roughly 2.98 CoreMark/MHz. Let’s do a final hack by defining HAS_FLOAT=0 in the make command line. Results:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
2K performance run parameters for coremark. CoreMark Size : 666 Total ticks : 16694339 Total time (secs): 16 Iterations/Sec : 1875 Iterations : 30000 Compiler version : GCC11.1.0 Compiler flags : -O2 -O3 -DHAS_STDIO -DHAS_TIME_H -DUSE_CLOCK -fno-common -funroll-loops -finline-functions -falign-functions=16 -falign-jumps=4 -falign-loops=4 -finline-limit=1000 -fno-if-conversion2 -fselective-scheduling -fno-tree-dominator-opts -lpthread -DHAS_FLOAT=0 -mtune=sifive-7-series -DPERFORMANCE_RUN=1 -lrt Memory location : Please put data memory location here (e.g. code in flash, data on heap etc) seedcrc : 0xe9f5 [0]crclist : 0xe714 [0]crcmatrix : 0x1fd7 [0]crcstate : 0x8e3a [0]crcfinal : 0x5275 Correct operation validated. See README.md for run and reporting rules. |
Let’s use the Iterations/Sec result: 1875 as the CoreMark 1.0 value, and in this case, we can indeed achieve exactly 3.125 CoreMark/MHz as Microchip did for using a signed index. Why signed is significantly faster than unsigned, I’m not quite sure… and we’d need to look at the assembly, and check the number of cycles for each instruction to find out.
It truly shows how benchmarks can be tweaked/manipulated to achieve greater results, and also the importance of compile flags to optimize the code. The voltage/current analytics web page did not show any significant variation during testing.
That will be all for today, and in a few weeks, I’ll hopefully post something about the FPGA part. Somebody asked me to assess virt-io over the PCI-e bus, but due to time constraints, I was unable to do so. I still asked Microchip who replied that it should work, but they haven’t tested for it…
If you are interested in the board, it’s available from various distributors, such as Mouser, for under $500.
Jean-Luc started CNX Software in 2010 as a part-time endeavor, before quitting his job as a software engineering manager, and starting to write daily news, and reviews full time later in 2011.
Support CNX Software! Donate via cryptocurrencies, become a Patron on Patreon, or purchase goods on Amazon or Aliexpress
Epic article, as always, Jean-Luc.
As a long-time Yocto dev, I can state that the statement there’s no packaging, etc. is not WHOLLY accurate, though.
The system as it’s designed builds out packages (whether you use them or not on the target for upgrades, installs, etc.) and it uses them to stage it into the root filesystem image. You have a choice of three differing packaging systems: RPM, Debian, and Ipk. Each has their own consequences. You can build an image with just the desired stuff for the target or you can build the “world” which handles all of the packages specified in your metadata layers and it will then provide you .rpm, .deb, and/or .ipks for you to use in a packaging repository accordingly.
You’re also not limited in sysvinit or systemd for your init/supervision choices either. Check out meta-runit over on GitHub. It’s a layer that is slowly growing over time to support more and more of the whole of Yocto with the option choice of runit instead of the other two. Runit’s more suited for a lot of the advanced embedded systems targets and it’s used by at least one Fortune 500 company at the core of things.
(Yeah, this class of thing is what I do for my day job and I maintain several piece parts in the space on github… X-D )
Thanks for the correction. I understand the OpenEmbedded image is relying on ipk packages.
I did not link directly to it, but there’s a short discussion about the “lack of package manager” @ https://exchange.riscv.org/t/icicle-kit-linux-package-manager/76
I wonder why customer use of a supplied device should be so hard?
Because these are not consumer devices.
So the buyer is not a customer, and products are not supplied as working products. With working software.
You have to waste, paid time to get them to work. Why supply documentation when it is not a consumer product.
Why does aRM supply engineers documents on what instructions and voltages their designs use, engineers are not consumers, by your standards DPG.
To me it is more make and forget, lazy, greedy manufacturing and a way to charge for extra product support.
Microchip customers will normally build their own boards and then customize their software. The Yocto and Buildroot BSP provides more flexibility to build custom images, and customers may not want to rely on Microchip’s packages repository, preferring to handle firmware updates by themselves.
That means they’ll have a team of engineers many of which are already familiar with either Yocto or buildroot. Documentation is there, but still, it’s a bit all over the place. Larger customers will normally be assigned one or more FAEs (Field Application Engineer) for technical support, who will help with any technical issues that may arise.
Bingo! Some of us, though, are slowly working towards “better” for a lot of this. It’s unfortunately presumed you’ve got a team of engineers or an SME (Waves hand…) working on this stuff. There needs to be a BIT better because there’s all sorts of amazing things possible with Yocto (Buildroot/OpenWRT’s not scalable- so while you can get simplistic solutions or, heh, a router appliance with OpenWRT, it’s more difficult to get, say an embedded secured DVR, for example, with it. It becomes hard to make something that scales to gigs of “firmware” (yes) with those tools.
>So the buyer is not a customer
These are evaluation boards. Evaluating if the supplied software is garbage or not is part of the process.
>You have to waste, paid time to get them to work. Why supply documentation >when it is not a consumer product.
These boards are used during product development. If you are developing a product you are already “wasting time” doing component selection, trying to reduce the BoM cost etc.
>Why does aRM supply engineers documents on what instructions
ARM supplies reference manuals for their cores and nothing else. Are you unaware of what ARM the company actually does? Here’s a hint: They don’t make any chips.
>and voltages their designs use, engineers are not
>consumers, by your standards DPG.
ARM doesn’t supply information about voltages. Voltages would be chip specific and those will be supplied by whatever company made your chip and maybe only if you have an NDA with them.
As an engineer that works on these sorts of boards on a daily basis I’m not too surprised if an eval board costs thousands of dollars and the software is complete garbage. You aren’t paying thousands of dollars for these boards because they are working Raspberry Pi like boards you can run a web server on and feel smug about being a Linux haxor. You’re paying thousands of dollars for the vendors reference platform to test your stuff on, poke the vendor with questions and decide if you want to drop hundreds of thousands of dollars on bringing a product to production using their chip.
>To me it is more make and forget, lazy, greedy manufacturing
>and a way to charge for extra product support.
These aren’t sold in the volumes required for them to be some sort of scam to separate money from chumps.
And that’s why products supplied to consumers are crap, the hardware and software engineers are just making it up as they go along. Hack it then dump it, Orange Pi style. Just fire and forget.
>And that’s why products supplied to consumers are crap,
>the hardware and software engineers are just making
>it up as they go along.
What do you base that on? Have you worked on a consumer product that is out in the wild being used? If not you are just talking out of your arse.
>Hack it then dump it, Orange Pi style. Just fire and forget.
The orange pi stuff is hobbyist grade boards produced for as little as possible. These hard CPU core + FPGA chips are not going into that level of product. The chip alone is too expensive to be used in e-waste grade products. You have no idea what you are talking about.
Heh. We’ve all been there at one point in time. Well…most of us.
He’s a base level hobbyist and doesn’t get there’s a deep end there to that pool. He’s still thinking like it’s all like a Pi4 as best as I can tell and has NEVER built out any consumer, industrial, or mission-critical products. 35+ years of it in my case. But…unlike some, I kind of live it as well as work with it.
Not QUITE. Let me guess. Hobbyist, right? That’s not negative, that’s just trying to, again, frame this in the right ways so you can get this…
An OrangePI isn’t a consumer part any more than any of the others are. NONE of them are consumer parts. They’re either maker parts, industrial eval kits, or BOTH (Embrace the epic power of, “AND!!” it applies here)
The presumption that they have clean documentation, etc. is going to disappoint you. REPEATEDLY. If you want this sort of thing, Stick with a Pi Foundation device, an indstrial X86 computer and the like. An FPGA system (this) isn’t intended for the likes of yourself, unless you up your game. Seriously. You’re playing in the playground that the pros do. MY world. And you either live it and get on with analyzing the things or you don’t. (Ever wonder why the LKML list can be so caustic at times or why Linus has his trademarked rants? This is a part of it. There’s all sorts of things I get to deal with and I get paid well to do that.) Worse, this one’s an FPGA as stated earlier, bonded to an SoC as a unified device. Have you ever done either, VHDL, Verilog, Chisel3, SpinalHDL, or any other HDL coding to basically define a digital circuit? This is in a whole new league of “engineer” than you’re used to involved with THAT part of it.
There’s tons of rather complicated documentation involved with Yocto, along with a lot of books you can obtain to start you off with. Just like with trying to do Linux drivers. Buildroot’s a differing story- it’s a system kind of derived from the Linux Kernel configuration system and it’s a nasty mess with little in the way of docs that’re useful for it. In this case, you can actually do like Jean-Luc managed to do here and learn a bit about Yocto (I’d even give advice…even now…) and find out that you’re talking about rolling your own distribution, etc. instead of sysadmining a Pi4.
Making rants about things like, “hack it, dump it,” isn’t productive and it’s neither going to change the situation…or make you any happier. You either need to up your game or stick to things that have an ecosystem that can accommodate your expertise…and skip the unhelpful commentary that makes you look, well, foolish and childish.
> Hobbyist, right?
To be more precise: just a retired old fart who thinks the solution to every problem is a crappy Android TV box. Not able to distinguish between distro and kernel, hardware and software, board maker and SoC maker.
Oh look the guy who programmed the hated Orange Pi software and who encouraged others to buy Orange Pi boards, without declaring he worked for Orange Pi.
Waste paid time… Looks at his desk covered with a mix of company and personal HW, including FPGA boards for RISC-V and related dev…
Sorta. And it’s seldom wasting time (well…some vendors…it IS that…) and more a level of investment in knowledge about the systems you’re working with. Right now none of the RISC-V related space is really anything other than a playground for the virtuosos, the paid grandmasters, etc. to do things unless you’re willing to step up to the plate and try to become one of them.
25+ years of doing Linux stuff professionally and 22 of it making Embedded Linux possible in my case (I shipped one of the earliest recorded systems on the market and kept doing it… :-D) so in my case, it’s almost like puttering around on my craft when I’m not working on it for my employer. It’s, sadly, not in the space of a lot of the things we’re used to in this group, to be honest. It’s getting there and I’m eager to contribute a lot more than a drib here and a drop there.
Because it’s presumed you’re like, heh, me, there and live, breathe and eat Embedded systems, specifically Embedded Linux.
When you’re dealing with embedded stuff, the vendors presume you’re either a complete ninny or someone that deeply knows what you’re doing. Nothing in-between…and the ninny route’s more than a bit offensive.
Actual you condescending arse cleaner. I am paid not by the hour but by results. If what I tell a company to do, does not work or create profit I don’t get paid. Companies are told to fire people like you, by people like me. I earn enough to work as and when I chose.
People like you are the problem in the industry…
Any plans on showing how to debug thru a simple blink-led program on the risc-v ?
Or how to synthesize a new fpga bitstream?
It’s possible to use sysfs to control GPIOs:
It’s the same as with any Arm Linux-based system. I’ll probably try GPIO that with another board like the upcoming Radxa Starlight JH7110.
A post about the FPGA part is coming, but I’m not sure what it will look like yet. Last week, I tried to download Libero SoC design suite, but I could not create an account for the download. Microchip support still has not replied about that. I’ll need to ping them again… There’s still time, as I’ll be working on Zidoo M6 mini PC first.
Following up on that I can see Microchip has a bunch of code sample in /opt/microchip:
Include a GPIO sample in C language that just use system calls to sysfs:
This will blink all four user LEDs at the top left corner of the board.
The code samples can be found @ https://github.com/polarfire-soc/polarfire-soc-linux-examples
I don’t know if there’s any tools ON target to synthesize a bitstream there. If this was coupled to an ice40k or an ECP5, be a differing story since IceStorm works on pretty much any Linux. Unless they’ve made a PolarFire toolchain for RISC-V
or as source…that’s not happening.