Code Monkey home page Code Monkey logo

foboot's Introduction

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

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.

Usage

You can write the bitstream to your SPI 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

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.

foboot's People

Contributors

david-sawatzke avatar enjoy-digital avatar mithro avatar tomkeddie avatar xobs avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

foboot's Issues

Failing to flash bitstream with ecpprog

Hello,
I'm trying to flash the r2.0 bootloader foboot-v3.0-orangecrab-r0.2-25F.bit into my orangecrab with ecpprog (latest commit).

However, the verification always fails at byte 4096, I tried many times and the result is the same:

$ ecpprog ../foboot-v3.0-orangecrab-r0.2-25F.bit
init..
IDCODE: 0x41111043 (LFE5U-25)
ECP5 Status Register: 0x06400000
reset..
flash ID: 0x00 0x00 0x00
file size: 266307
erase 64kB sector at 0x000000..
erase 64kB sector at 0x010000..
erase 64kB sector at 0x020000..
erase 64kB sector at 0x030000..
erase 64kB sector at 0x040000..
programming..  266307/266307
verify..       4096/266307Found difference between flash and file!
ABORT.

Any ideas why this is happening?

ecpbram fails on first run after a clean-build

Because the output folder structure is not created, ecpbram fails to create the rand.init file.

On completion of the gateware build there is a small warning:

Hexfiles have different number of words! (0 vs. 1506)
Failed to open input file

But the final message from python suggests that everything was built successfully.

Foboot build complete.  Output files:
        build/gateware/top.bit             Basic Bitstream file.  Load this onto the FPGA for testing.
        build/gateware/foboot_jtag_spi.svf Loads gateware into FLASH via JTAG
        build/gateware/foboot.bit          Optimised Bitstream file. (QSPI, Compressed, Higher CLK)  Load this into FLASH.
        build/gateware/top.svf             Serial Vector Format File. Useful when loading over JTAG.
        build/gateware/top.v               Source Verilog file.  Useful for debugging issues.
        build/software/include/generated/  Directory with header files for API access.
        build/software/bios/bios.elf       ELF file for debugging bios.

We'll need to make sure that our output folders are present before before creating the ecpbram init file.

Flash size limit of 1.5MB

I had not updated the FLASH size limit that was introduced.
As a result the DFU will fail if you attempt to upload more than 1.5MB of data, even though the FLASH is 8MB in size.

Issues building and testing new bootloader for OrangeCrab r0.2

Hi there!

I'm trying to modify the bootloader to also look at one of the IO pins when determining whether or not to enter DFU mode, and I can't seem to produce a bitstream that actually /works/. Particularly, I can run the entire compilation process, create a bitstream, upload it with dfu-util, but once it loads, the RGB LED seems to just get stuck at green (which doesn't seem to actually correspond to any state of the bootloader), regardless if the IOs are tied high, low, or left floating. I'm not sure if I'm doing something wrong, or if that's an expected behavior of the bootloader when running from the "user" section. I'm hoping to avoid having to actually flash it as the real bootloader to test it. I have a Segger J-LINK if it turns out to be necessary to use JTAG to recover the bootloader (i.e., not super worried about bricking the device), but I'm similarly hoping to avoid having to go down that road if possible.

Below are all the changes I've made to in my attempts to get this working. Any help would be appreciated!
These are divided into two sections, system-specific tweaks I had to make to the Makefile and linker script to get it building on my machine, and then the changes I attempted to make to the bitstream to try and get it to look at IO pins besides the onboard button

Build environment

parallels@parallels-Parallels-Virtual-Platform:~$ uname -a
Linux parallels-Parallels-Virtual-Platform 4.15.0-34-generic #37-Ubuntu SMP Mon Aug 27 15:21:48 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

parallels@parallels-Parallels-Virtual-Platform:~$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04.5 LTS"

parallels@parallels-Parallels-Virtual-Platform:~$ yosys --version
Yosys 0.9+3521 (git sha1 4f2b78e1, clang 6.0.0-1ubuntu2 -fPIC -Os)

parallels@parallels-Parallels-Virtual-Platform:~$ nextpnr-ecp5 --version
nextpnr-ecp5 -- Next Generation Place and Route (Version f6d436d5)

parallels@parallels-Parallels-Virtual-Platform:~$ ecppack --version
Project Trellis ecppack Version 1.0-182-g8c0a638

parallels@parallels-Parallels-Virtual-Platform:~$ riscv32-unknown-elf-gcc --version
riscv32-unknown-elf-gcc (GCC) 10.1.0
Copyright (C) 2020 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.

parallels@parallels-Parallels-Virtual-Platform:~$ riscv32-unknown-elf-ld --version
GNU ld (GNU Binutils) 2.35
Copyright (C) 2020 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.

My build-and-flash command is:

python3 foboot-bitstream.py --platform orangecrab --revision 0.2 --device 25F && \
cp build/gateware/orangecrab.bit build/gateware/orangecrab.dfu && \
dfu-suffix -v 1209 -p 5af0 -a build/gateware/orangecrab.dfu && \
dfu-util -D build/gateware/orangecrab.dfu 

System-specific changes

Modified sw/Makefile to support my system:

diff --git a/sw/Makefile b/sw/Makefile
index a08bf1a..04d478e 100644
--- a/sw/Makefile
+++ b/sw/Makefile
@@ -1,5 +1,5 @@
 # Earlier versions of the Raspberry Pi image only had riscv32-gcc
-ifneq (,$(wildcard /usr/bin/riscv32-unknown-elf-gcc))
+ifneq (,$(wildcard /opt/riscv/bin/riscv32-unknown-elf-gcc))
 TRGT       ?= riscv32-unknown-elf-
 else
 TRGT       ?= riscv64-unknown-elf-

Modified the linker script so that it actually links

Not sure if this is because I'm using the most recent riscv-gnu-toolchain, but ld was complaining about .srodata.landing_url_descriptor overflowing into .data. I had to tweak the rodata section to look like:

diff --git a/sw/ld/linker.ld b/sw/ld/linker.ld
index 5796f16..7282043 100644
--- a/sw/ld/linker.ld
+++ b/sw/ld/linker.ld
@@ -21,7 +21,7 @@ SECTIONS
                _frodata = .;
                *(.rodata .rodata.* .gnu.linkonce.r.*)
                *(.rodata1)
-               *(.srodata)
+               *(.srodata .srodata.*)
                _erodata = .;
        } > rom

Changes to the actual bitstream

Then I made a few changes to the platform scripts to support treating IO0 and IO1 as readable peripherals via a CSR much like the usr_btn is.

Added two IOs to hw/deps/litex-boards/litex_boards/platforms/orangecrab.py

Just adding these two pins to be able to reference them later in the stack

diff --git a/litex_boards/platforms/orangecrab.py b/litex_boards/platforms/orangecrab.py
index efdd103..4cae9d8 100644
--- a/litex_boards/platforms/orangecrab.py
+++ b/litex_boards/platforms/orangecrab.py
@@ -84,6 +84,8 @@ _io_r0_2 = [
     ("rst_n", 0, Pins("V17"), IOStandard("LVCMOS33")),
 
     ("usr_btn", 0, Pins("J17"), IOStandard("SSTL135_I")),
+    ("io_0", 0, Pins("GPIO:0"), IOStandard("LVCMOS33")),
+    ("io_1", 0, Pins("GPIO:1"), IOStandard("LVCMOS33")),
 
     ("rgb_led", 0,
         Subsignal("r", Pins("K4"), IOStandard("LVCMOS33")),

Added the two IOs to hw/rtl/plaform/orangecrab.py

Modified add_button to make two more "buttons" that read those two pins similar to how the real button is added

diff --git a/hw/rtl/platform/orangecrab.py b/hw/rtl/platform/orangecrab.py
index 40fb8e4..47cc86c 100644
--- a/hw/rtl/platform/orangecrab.py
+++ b/hw/rtl/platform/orangecrab.py
@@ -91,7 +91,12 @@ class Platform(LatticePlatform):
     def add_button(self, soc):
         try:
             btn = self.request("usr_btn")
+            io0 = self.request("io_0")
+            io1 = self.request("io_1")
+
             soc.submodules.button = Button(btn)
+            soc.submodules.io0 = Button(io0)
+            soc.submodules.io1 = Button(io1)
         except:
             ...

Added the two new "button" CSRs to hw/foboot-bitstream.py

diff --git a/hw/foboot-bitstream.py b/hw/foboot-bitstream.py
index d2c1512..241474c 100755
--- a/hw/foboot-bitstream.py
+++ b/hw/foboot-bitstream.py
@@ -75,6 +75,8 @@ class BaseSoC(SoCCore, AutoDoc):
         "lxspi":          15,
         "messible":       16,
         "button":         17,
+        "io0":            18,
+        "io1":            19,
     }
 
     SoCCore.mem_map = {

Finally, modified sw/src/main.c to consider the new IO pins when determining whether to enter DFU mode

diff --git a/sw/src/main.c b/sw/src/main.c
index ca77fd1..2f216a4 100644
--- a/sw/src/main.c
+++ b/sw/src/main.c
@@ -117,7 +117,14 @@ static int nerve_pinch(void) {
 
 static int button_pressed(void){
 #ifdef CSR_BUTTON_BASE
+#   ifdef CSR_IO0_BASE
+#       ifdef CSR_IO1_BASE
+          return button_i_read() != 1 || io0_i_read() != 1 || io1_i_read() != 1;
+#       else
+          return button_i_read() != 1 || io0_i_read() != 1;
+#       endif
     return button_i_read() != 1;
+#   endif
 #else
     return 1;
 #endif

Thanks for taking a look at this! Any insight would be appreciated, and hopefully this can go on to serve a power user in the future if they want to try this!

Potential typo bug in foboot/main.c

In the reboot function we have this piece of code:

    if (boot_config & 0x00000002) // DDR_EN
        picorvspi_cfg3_write(picorvspi_cfg3_read() | 0x40);
    if (boot_config & 0x00000002) // CFM_EN
        picorvspi_cfg3_write(picorvspi_cfg3_read() | 0x10);

The comments document different bit names, but the bit is the same (0x2 in both if conditions). This looks like a bug.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.