by Gui Andrade
Before I start, the standard disclaimers: I take no responsibility if you break your board, etc., etc.
I was really excited by the possibility of a Debian RISC-V computer where I can even put custom accelerators on its FPGA. Here's how you can do exactly that.
Beware, it's quite an involved process. And there's one particularly unfortunate issue I haven't had the chance to diagnose yet: for some reason, Linux only activates a single core on the processor.
That aside, lots of things work quite well. Including package management! So if you're so inclined to try it out, compile away:
This runs on a physical PolarFire Icicle board, and displays over UART1:
# DEPENDENCIES:
# pip install kconfiglib
# riscv64-unknown-linux-gnu-gcc
git clone https://github.com/archshift/hart-software-services
git checkout spi-flash-boot
cp boards/mpfs-icicle-kit-es/def_config .config
# Enable booting from SPI Flash
echo "CONFIG_SERVICE_BOOT_SPI_FLASH=0x400" >> .config
make BOARD=mpfs-icicle-kit-es CROSS_COMPILE=riscv64-unknown-linux-gnu-
TODO. I built U-Boot from Microchip's Yocto configuration.
Once you have a u-boot.elf
file, do the following:
# Define the payload configuration
cat <<EOT >> ubootcfg.yaml
set-name: 'PolarFire-SoC-HSS::U-Boot'
hart-entry-points: {u54_1: '0x80200000', u54_2: '0x80200000', u54_3: '0x80200000', u54_4: '0x80200000'}
payloads:
u-boot.elf: {exec-addr: '0x80200000', owner-hart: u54_1, secondary-hart: u54_2, secondary-hart: u54_3, secondary-hart: u54_4, priv-mode: prv_s}
EOT
# We need this tool to create a bootloader payload
pushd hart-software-services/tools/hss-payload-generator
make
popd
# Create the payload
hart-software-services/tools/hss-payload-generator/hss-payload-generator -c ./ubootcfg.yaml uboot-payload.bin
# Convert the payload to the INTEL HEX format our flashing tool expects
bincopy convert -i binary -o ihex uboot-payload.bin uboot-payload.hex
git clone --depth 1 --branch v5.6.16 https://github.com/gregkh/linux
cd linux
git clone https://github.com/archshift/polarfire-linux buildsh
# Patch the kernel for PolarFire SoC
./buildsh/patch.sh
# Configure the kernel. You can leave the settings as they are and activate "Save".
./buildsh/menuconfig.sh
# Build images
./buildsh/mk-images.sh
# Initialize disk image
dd if=/dev/zero bs=1M count=2048 of=drive.img
# Partition the disk
fdisk drive.img
> g # make GPT table
> n # new partition, give it +256MB
> t # change partition type, use type 1: EFI system partition
> n # new partition, give it the remaining space
> w # write changes
# Give the disk image loop devices /dev/loop0 (boot partition) and /dev/loop1 (root partition)
sudo losetup -Pf drive.img
# Make the filesystems
sudo mkfs.fat /dev/loop0p1
sudo mkfs.ext4 /dev/loop0p2
# Mount the partition
mkdir /tmp/boot
sudo mount /dev/loop0p1 /tmp/boot
sudo cp fitImage boot.scr.uimg /tmp/boot
# Unmount
sudo umount /tmp/boot
# Mount the partition
mkdir /tmp/root
sudo mount /dev/loop0p2 /tmp/root
# Install essential packages
EXTRA_PKGS=ssh,nano,curl,build-essential,debian-ports-archive-keyring,sudo,tmux
sudo debootstrap --foreign --arch riscv64 --include=$EXTRA_PKGS sid /tmp/root http://deb.debian.org/debian-ports/
# Install fstab
echo "/dev/mmcblk0p1 /boot vfat defaults 0 2" > /tmp/root/etc/fstab
echo "/dev/mmcblk0p2 / ext4 defaults 0 1" >> /tmp/root/etc/fstab
# Unmount
sudo umount /tmp/root
# Note that you're going to need the uncompressed kernel image here.
KERNEL=path/to/kernel/arch/riscv/boot/Image
qemu-system-riscv64 -M virt -m 1024 -smp 5 -display none \
-serial stdio -drive file=drive.img,format=raw,id=hd0 \
-device virtio-blk-device,drive=hd0 -append "root=/dev/vda2 rw" \
-kernel "$KERNEL" -netdev user,id=net0 \
-device virtio-net-device,netdev=net0
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
# debootstrap doesn't install everything, but it'll download them to the cache. Manually install them now.
dpkg -i -E /var/cache/apt/archives/*.deb
# We'll still have broken packages after this step but the necessary utilities for networking should be installed.
sync
# Reboot now
# Enable networking
dhclient
# Fix broken packages
apt --fix-broken install
# Do it twice to make sure no stragglers stay unconfigured
apt --fix-broken install
# Ensure all the extra packages we wanted are now installed
apt install ssh nano curl build-essential debian-ports-archive-keyring sudo tmux
# Enable systemd
ln -s /lib/systemd/systemd /sbin/init
# DON'T FORGET TO DO THIS NOW
passwd root
sync
# Close QEMU now
There you go! Now you should have a fully functional drive.img
.
You will need to copy the firmware payload into the SoC's eNVM flash.
For this you will have the misfortune of using Libero, Microchip's FPGA development platform, or SoftConsole, their firmware development platform. You might be able to also use a JTAG debugger for this, but I'm only familiar with Libero, so that's the tool I'll describe.
Clone the Icicle Kit reference design and open Libero. Click Project->Execute Script
, and select ICICLE_KIT_eMMC.tcl
under the reference design. This should populate a project.
On the left sidebar, under Program Design
, click Generate FPGA Array Data
. This will take a long time. Then, Configure Design Initialization Data and Memories
. A new view will pop up. Click the eNVM
tab.
Click the Add
button, and select Add Boot Mode 1 Client
. Navigate to the hart-software-services/Default
directory from "Building firmware". Select hss.hex
. Click OK.
On the left sidebar, under Program Design
, click Generate Bitstream
. If all goes well, you can then proceed to click Run PROGRAM Action
, which will transfer the firmware to your board.
You will need to copy the U-Boot payload into the board's SPI Flash memory at the address 0x400
.
Again, for this you will have the misfortune of using Libero. If you have a JTAG debugger, you can avoid Libero, but I'm not familiar with that process.
Assuming you've done everything in "Installing firmware" above, once again click Configure Design Initialization Data and Memories
. Navigate to the SPI Flash
tab.
First, use the drop-down to reconfigure the SPI Flash to the correct size: 1,048,576 KB
. Then click Add->Add Data Storage Client
. Select the uboot-payload.hex
file from "Building U-Boot."
On the left sidebar, under Program SPI Flash Image
, click Generate SPI Flash Image
. If all goes well, you can then proceed to click Run PROGRAM_SPI_IMAGE Action
, which will transfer the bootloader to your board.
# Access the boot monitor
sudo screen /dev/ttyUSB0 115200
# Reboot the board, then press any key to stop booting.
# Make the NAND available as a USB device.
> usbdmsc
# Find the block device that corresponds to your NAND flash. It should be 8GB.
sudo fdisk -l
# Copy the NAND image.
sudo dd if=drive.img of=/dev/sdXY