Awesome
Foboot: The Bootloader for Fomu
Foboot is a failsafe bootloader for Fomu. It exposes a DFU interface to the host. Foboot comes in two halves: A Software half and a Hardware half. These two halves are integrated into a single "bitstream" that is directly loaded onto an ICE40UP5k board, such as Fomu.
Requirements
To build the hardware, you need:
- Python 3.5+
- Nextpnr
- Icestorm
- Yosys
- Git
Subproject hardware dependencies will be taken care of with lxbuildenv
.
To build the software, you need:
- RISC-V toolchain
Building the project
The hardware half will take care of building the software half, if it is run with --boot-source bios
(which is the default). Therefore, to build Foboot, enter the hw/
directory and run:
$ python3 foboot-bitstream.py --revision hacker --seed 19
This will verify you have the correct dependencies installed, compile the Foboot software, then synthesize the Foboot bitstream. The resulting output will be in build/gateware/
. You should write build/gateware/top-multiboot.bin
to your Fomu device in order to get basic bootloader support.
The seed
argument is to set initial conditions for the
place-and-route phase. nextpnr-ice40
uses a simulated annealing
algorithm that can result in one of several locally optimal layouts.
Only some of these will meet the timing requirements for Fomu.
If you see something like
ERROR: Max frequency for clock 'clk48_$glb_clk': 45.41 MHz (FAIL at 48.00 MHz)
try a different seed. You can search for an appropriate seed with:
for seed in $(seq 0 100)
do
python3 ./foboot-bitstream.py --revision pvt --seed $seed 2>&1 |
grep 'FAIL at 48.00 MHz' && continue
echo "Working Seed is $seed"
break
done
This can take a considerable time.
Usage
You can write the bitstream to your SPI flash.
Loading using fomu-flash
If you're using fomu-flash
, you would run the following:
$ fomu-flash -w build/gateware/top-multiboot.bin
Erasing @ 018000 / 01973a Done
Programming @ 01973a / 01973a Done
$ fomu-flash -r
resetting fpga
$
Fomu should now show up when you connect it to your machine:
[172294.296354] usb 1-1.3: new full-speed USB device number 33 using dwc_otg
[172294.445661] usb 1-1.3: New USB device found, idVendor=1209, idProduct=70b1
[172294.445675] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[172294.445684] usb 1-1.3: Product: Fomu Bootloader (0)
[172294.445692] usb 1-1.3: Manufacturer: Kosagi
Using dfu-util
to flash the bootloader
Safe way to test
Just do
dfu-util -D build/gateware/top.bin
to copy into the SPI flash, then
dfu-util -e
each time you want to run the generated bitstream after a reboot.
A multiboot enabled bootloader is also generated; you can try that out with
dfu-util -D build/gateware/top-multiboot.bin
dfu-util
loads the bootloader into flash at 0x40000; it'll be overridden
by any other code you attempt to flash using dfu-util
Loading the bootloader as first bootloader
WARNING: Flashing a new bootloader could brick your device It's best to wait for an official release
First build the flasher program, that will run on the Fomu (you only need to do this once):
cd booster
cc -O2 -o make-booster -I ./include make-booster.c
make
Then package everything up ready for loading:
cd releases
bash ./release.sh pvt
This will create a new directory in releases
named by the head of
your git tree and the last official release. So you'll see something
like v2.0.3-8-g485d232
In that directory will be a file named pvt-updater-
version.dfu
Load it onto the Fomu using dfu-util
:
dfu-util -D pvt-updater-v2.0.3-8-g485d232.dfu
Your Fomu will flash rainbow for about five seconds, then reboot and go back to blinking steadily. To verify that your code has loaded, use
dfu-util -l
and look at the version output.
Loading and running other bitstreams
To load a new bitstream, use the dfu-util -D
command. For example:
$ dfu-util -D blink.bin
This will reflash the SPI beginning at offset 262144.
To exit DFU and run the bitstream at offset 262144, run:
$ dfu-util -e
Note that, like Toboot, the program will auto-boot once it has finished loading.
Building the Software
Software is contained in the sw/
directory.