Is there C boot code (source) for RevB02 hardware?

I’m brand new to Risc-V, just received my HiFive1-RevB02 board.
I like to start things off by building and installing the boot firmware, so can someone point me to it? I’ve downloaded everything I could from the HiFive1 webpage, but don’t see anything that appears to be bare-metal boot code.
Thanks in advance for any pointers to code or docs related to this.

Welcome @edsut Here is a very detailed discussion of the FE310 (HiFive) Boot Process which is illustrated and summarized below.

Admittedly, the boot process entry point is a little bit circuitous. Table 5 of Chapter 5 of the Manual shows how the boot vector address depends on the state of the MSEL pins (earlier Manual version v19p05, available elsewhere, has Table 7 called “Target of the reset vector” which explains the MSEL settings).

Unfortunately, the MSEL pins are not accessible, but are hard-wired (presumably floating up) to 11’b which is mentioned as the hardware default condition (and determined empirically).

This causes a jump to the Mask ROM at 0x1 0000.

Section 5.1.1 of the Manual says that the Mask ROM has instructions which further jump to OTP at 0x2 0000.

Now, the “Boot Code” section at the beginning of Chapter 5 of the Datasheet gives us the default OTP program which is a jump to SPI-Flash at 0x2000 0000. Quoting the Datasheet:

As shipped, the OTP memory at the boot location is preprogrammed to jump immediately to the end of the OTP memory, which contains the following code to jump to the beginning of the SPI-Flash at 0x2000 0000:

fence 0,0
li t0, 0x20000000
jr t0

fence 0,0 is encoded as 0x0000 000F, and the instruction may be modified by burning additional bits to transform it into a JAL instruction ( opcode 0x6F ) to execute arbitrary code rather than jumping directly to the beginning of the SPI-Flash.

A little clarification to the above:

In general, note that li t0, 0x20000000 is a pseudo-instruction which is actually the two instructions lui t0, %hi(0x20000000), to load a 20-bit long immediate value, and addi t0, t0, %lo(0x20000000), to load a 12-bit short immediate value. Specifically, the Datasheet is mis-stated here: the immediate value loaded is 0x20010 (OTP_BOOT), not 0x20000000 as printed.

Within the OTP memory and not described in the Datasheet is a proprietary library which performs an SPI flash recovery mechanism. This library counts how many recovery attempts to read the SPI flash ID code after power cycling, and goes into a tight loop after the 5th failure, in order to prevent further execution into a non-existent or defective SPI memory device…

Thus, at power-up, program execution will jump to 0x2000_0000 where, in case of the HiFive board is a “double-tap” bootloader which helps get back to a happy state in case of runaway user code. It is completely optional, and all of its code is described well and available as double_tap_dontboot.c with its related discussion (and binaries) available here . User code then starts at 0x2001_0000.

In contrast to the “double tap” bootloader, a really lean start-up and minimalist example is in start.s and of RISC Five Easy As PI.

You can either map/link and load your code to 0x8000 0000, for RAM operation; or to 0x2000 0000, for Flash/ROM operation, and all will be fine.

Don’t worry if you erase, re-flash, and wipe out what’s there; it’s easy to put back to the original state.

@pds Thanks much for the details. I’m looking forward to digging into this, and a warning… I’ll probably have more questions.