||8 months ago|
|01-blink||8 months ago|
|02-chase||8 months ago|
|03-clock||8 months ago|
|04-uart||8 months ago|
|05-write||8 months ago|
|06-irq-delay||8 months ago|
|07-uart0irq||8 months ago|
|08-i2c||8 months ago|
|bootloader||8 months ago|
|.gitignore||8 months ago|
|02-chase.gif||9 months ago|
|README.md||8 months ago|
|UNLICENSE||8 months ago|
|memmap||8 months ago|
|platform_regs.inc||8 months ago|
A bit of assembly on RED-V Thing Plus
This repo contains a progression of example programs written in RISC-V assembly, to run on Sparkfun's RED-V Thing Plus. It's a result of my attempt to learn a bit of RISC-V assembly.
You'll need a compiler capable of compiling for (bare metal)
rv32imac architecture. There are precompiled toolchains available from SiFive. The
Makefiles are set to use
riscv32-elf-as by default, but
riscv64-unknown-elf-as and variations should be also fine (you'll need to adjust
PREFIX in the
Another piece of software that you may want to use is
JLinkExe from Segger, for flashing via
make flash. You'll also need to adjust the
JLINKEXE path in the
Makefiles. This is avoidable; you can also just copy the resulting
.hex file(s) onto the virtual "drive" that the onboard JLink emulates for the PC; JLink will then automatically flash it.
The examples are in the numbered subdirectories; they get progressively more complicated. Most of the code is carried over from the earlier to the later ones.
Two files in the main directory are reused (via symlinks) in all the examples:
memmap (which tell the linker addresses for flash and RAM), and
platform_regs.inc which have definitions for some of the MCU memory-mapped registers, from the manual.
The filenames in the examples follow the convention that
main.s is the main file, which includes various other
.s files. The
p_*.s contain the MCU-specific code.
Commentary about the board
The RED-V Thing board carries SiFive's FE310-G002 RV32IMAC microcontroller (with supporting crystals and flash), as well as a JLink debugger (actually licensed from Segger). This is very nice - no external hardware needed for flashing, and debugging via JTAG, and a convenient access to UART0. (Most conveniently used using the non-open-source JLink software; but
openocd also works.) The board is roughly compatible with SiFive's Hifive1 RevB board, to the point that Hifive1B firmware runs fine on the RED-V, except the RED-V is missing the LEDs and the (imo pointless) ESP32 wifi.
Commentary about the MCU
To do anything with the onboard FE310-G002, one will need FE310 datasheet and most importantly FE310 manual. These are refreshingly short and to the point. They sort of reinforce that FE310-G002 isn't really meant (I guess) to be used in real-world embedded applications: only the basic peripherals (exactly those that I use the most), with just the basic features. On the other hand, this makes it superb to play around with - they are really dead simple and straightforward; one doesn't have to read through hundreds of pages of descriptions of tens of registers that allow (somewhat) obscure features. Just a RISC-V core with basic UART, SPI, I2C, PWM, timer, interrupts. These are designed quite well to go with a RISC-V core: tricks like error flags in bit31 for easy sign tests, etc. There seems to be also a reasonably good attempt at a "sleep" solution (Always-On domain), but I am not that sure about the low power requirements - there are a bunch of extra parts (crystals, flash) that would need to be taken care of in sleep.
Anyway, the MCU is a good demonstration that SiFive digital designers know what they're doing.
On reset, FE310-G002 jumps to
0x20000000 (usually, this is to some extent configurable), which is mapped to the beginning of the onboard flash. From factory, this contains SiFive's bootloader (which they didn't release sources for). In any case, the RED-V board uses the exact same bootloader as the HiFive1B board. Its function is to
a) guard against the scenario when the MCU makes itself inaccessible to JTAG (e.g. sleep without wake sources) - this is done by blinking a LED after 1 second, if RESET is pressed again just after that, then the bootloader does not jump to user code, but just stalls. This allows the JLink to connect to the chip and so reprogram the flash.
b) initialise the ESP32 on the HiFive1B board.
It emits some text over UART (115200 baud); e.g. the result of b).
Now on RED-V: For a), the LED that's blinked on HiFive1B does not exist on RED-V, so that's not visible; but otherwise the mechanism works. For b), there is no ESP32, so it just errors out.
Someone disassebled the original bootloader and also rewrote it into C here. It turns out that it does a few other things, so that more of the MCU peripherals are not in their reset states:
- it seems to use PMU/sleep mechanism on power-up-reset to reset(?) the ESP32, so it clobbers the PMUSLEEPn registers and triggers sleep once. It uses another "magic value" in
AON_BACKUP15do that it isn't done on subsequent boots - but if the user application uses
AON_BACKUP15for something else, it will happen again.
- it sets up UART, switches the clock to external crystal (!), and does a "bench clock reset", which seems to only do some computation with numbers of cycles?
- leaves the SPI peripheral and SPI pins enabled - makes sense on HiFive1b board, but the LED on the RED-V Thing uses one of those pins...
Anyway, I wrote a simple alternative one which just does a) above. It's in the