HiFive Unmatched
As of 20210807, -CURRENT and 13-STABLE have support for the HiFive Unmatched, including USB, Ethernet and NVMe.
Note that no SD card support is present, as that requires a driver for mmc-spi-slot, which itself requires an overhaul of FreeBSD's spibus to expose more low-level functionality required to control the SDC/MMC directly via SPI without an intervening controller.
Quick Start
The following steps describe how to install FreeBSD to an NVMe drive on the Unmatched. Make sure you have the SD card that shipped with the board, otherwise see #Booting.
Download a copy of the memstick or mini-memstick installer from FreeBSD's Download Page.
Copy the installer to a USB drive, e.g. dd if=FreeBSD-14.0-CURRENT-riscv-riscv64-mini-memstick.img of=/dev/da1 bs=1m status=progress
- Insert the SD card and USB drive into the Unmatched.
- Power-on the board. It should boot straight to the installer (see below if not).
Follow the installation steps, targeting your NVMe drive for the root filesystem (most likely it will show up as nda0).
- Reboot, and optionally remove the USB drive. The board should boot into the newly installed system either way.
If you don't have an NVMe drive and would like to boot from a USB instead, then choose the GENERICSD image from the download page. Despite the name, this contains a live install that can be copied directly to a USB.
Manually Booting from USB
If the board does not automatically boot from USB (e.g. because it detects an OS install on the NVMe drive), escape to U-Boot's command line and run:
pci enum run usb_boot
UART1 Quirk
Whilst seemingly not very detrimental to performance, the board suffers from a missing pull-up resistor on its UART1_RX line, which is wired to both the M.2 E-key (WiFi/Bluetooth) slot and the J28 header. This results in a floating signal value that can be sampled as a start bit and trigger interrupts for incoming data, with the interrupt rate having been seen to be as high as 180k per second. Unless you are using this secondary UART, it is recommended that it be disabled by adding the following to /boot/loader.conf and restarting:
hint.uart.1.disabled="1"
You can verify that this has taken effect by checking the output of devinfo(8); if successful, only uart0 should appear in the output (or, when using the -v option, uart1 should show as disabled). Note that devctl(8) can be used to enable and disable the UART once booted.
External Links
https://github.com/sifive/meta-sifive/tree/2021.04/recipes-bsp/u-boot/files/unmatched
https://sifive.cdn.prismic.io/sifive/167a1a56-03f4-4615-a79e-b2a86153148f_FU740_errata_20210205.pdf
Booting
The HiFive Unmatched can load the first stage boot from either onboard flash or SD card. The board ships with an SD card with U-Boot and Linux preinstalled. For now we will use the provided SD card to boot.
Per the reference manual there are four partitions on the provided card:
Partition |
Format |
Description |
1 |
Raw |
U-Boot SPL |
2 |
Raw |
U-Boot Proper |
3 |
fat16 |
Linux kernel, .dtb, ... |
4 |
ext4 |
Root FS |
For our purposes we care only abut the first two partitions. U-Boot will search NVMe, USB, then the SD card.
U-Boot
A U-Boot flavor built for the Unmatched is available in ports (sysutils/u-boot-sifive-fu740). Note it is available on all architectures, not just riscv64, so can be built and/or installed on e.g. an amd64 system to obtain the firmware files.
Outdated firmware is known to have the following issues:
- Rebooting does not work
- No RTC is present in the device tree so obtaining the time requires NTP
- The CPU clock frequency is lower
- On some boards the memory timings can lead to corruption
Internal Flash
It is recommended that U-Boot be written to the internal flash rather than using an external SD card, as it avoids the need for a separate SD card, and can be accessed directly from FreeBSD for future upgrades.
Note: Due to interactions between the mx25l flash driver and gpart(8), it is not possible to write to the partition table on the internal flash directly, so a temporary memory disk is used to prepare an image.
To install a fresh copy of U-Boot to the internal flash, execute the following:
# kldload mx25l # mdconfig -s 32M md0 # gpart create -s GPT md0 # gpart add -t hifive-fsbl -b 40 -s 1M -l spl md0 # gpart add -t hifive-bbl -b 2088 -s 4M -l uboot md0 # gpart add -t "!3de21764-95bd-54bd-a5c3-4abe786f38a8" -b 10280 -s 128K -l env md0 # gpart show md0 => 40 65469 md0 GPT (32M) 40 2048 1 hifive-fsbl (1.0M) 2088 8192 2 hifive-bbl (4.0M) 10280 256 3 !3de21764-95bd-54bd-a5c3-4abe786f38a8 (128K) 10536 54967 - free - (27M) # dd if=/usr/local/share/u-boot/u-boot-sifive-fu740/u-boot-spl.bin of=/dev/md0p1 bs=4096 conv=sync # dd if=/usr/local/share/u-boot/u-boot-sifive-fu740/u-boot.itb of=/dev/md0p2 bs=4096 conv=sync # dd if=/dev/md0 of=/dev/flash/spi0 bs=4096 conv=sync # mdconfig -d -u 0
To boot from the internal flash (QSPI0 in SiFive's documentation), set MSEL[3:0] to 0110:
+----------> CHIPIDSEL | +--------> MSEL3 | | +------> MSEL2 | | | +----> MSEL1 | | | | +--> MSEL0 | | | | | +-+-+-+-+-+ | | |X|X| | ON(1) | | | | | | |X|X| | |X| OFF(0) +-+-+-+-+-+ BOOT MODE SEL
In future, unless the partition tables need to change, the firmware can be upgraded from the Unmatched by dd'ing the updated files directly to flash.
SD Card
Note: FreeBSD does not have a driver for SD cards directly connected to an SPI bus, such as on the Unmatched. The instructions below assume using FreeBSD with a separate card reader or on a different machine.
To boot from the SD card, ensure the MSEL[3:0] DIP switches on the board are configured as 1011:
+----------> CHIPIDSEL | +--------> MSEL3 | | +------> MSEL2 | | | +----> MSEL1 | | | | +--> MSEL0 | | | | | +-+-+-+-+-+ | |X| |X|X| ON(1) | | | | | | |X| |X| | | OFF(0) +-+-+-+-+-+ BOOT MODE SEL
To install a fresh copy of U-Boot to an SD card, install sysutils/gdisk, and execute the following (assuming da0 as the target device):
# sgdisk -g --clear -a 1 \ --new=1:34:2081 --change-name=1:spl --typecode=1:5B193300-FC78-40CD-8002-E86C45580B47 \ --new=2:2082:10273 --change-name=2:uboot --typecode=2:2E54B353-1271-4842-806F-E436D6AF6985 \ /dev/da0 # dd if=u-boot-spl.bin of=/dev/da0p1 bs=512 conv=sync # dd if=u-boot.itb of=/dev/da0p2 bs=512 conv=sync
These partition offsets and types must be exact, as U-Boot is hard-coded to look for them there. Notice that they differ slightly from what is required for the internal flash. This is the reason sgdisk must be used, since gpart(8) creates a header that extends past LBA 34.