Porting Chopstx to RISC-V MCU

For GD32VF103 (Note: it's not GD32 F 103, but GD32 VF 103), I ported Chopstx in master. It will be released in Chopstx 2.0.

It was in 2018, when I ported Chopstx to GD32F103 in Chopstx 1.9. GD32F103 uses ARM Cortex-M3 core and peripherals are compatible to STM32F103, the porting work was just some tweaks.

On the other hand, GD32VF103 uses RISC-V core named Bumblebee, and its USB peripheral is different to GD32F103.

In this opportunity, I write some of my random thoughts for Chopstx and comments on RISC-V MCU.

RISC-V MCU named Bumblebee

The MCU core is 32-bit RISC-V architecture (RV32I) with M-A-C extentions, referred as RV32IMAC.

Information are available from riscv-mcu.com, and they publish documents and code at: https://github.com/riscv-mcu

I get GD32VF103_User_Manual_EN_V1.0.pdf and GD32VF103_User_Manual_CN_V1.0.pdf, and "Bumblebee Core Architecture Manual.pdf" as well.

I also get some reference code from n200-sdk and GD32VF103_Demo_Suites to see how the core and peripherals are accessed by their reference code.

It's great to have all (mostly, in fact) information available to public.

For now, I don't know how to reset the MCU from code. There is an explanation in User Manual, but it is a description for GD32F103 (not GD32VF103) which is irrelevant. Perhaps, it's an error by cut and paste from GD32F103 manual.

RISC-V Priviledged Architecture only defines a special register for exception handling: mscratch

Good. I like it. (IIRC, MIPS core has two special registers (k0 and k1) and SuperH core has four registers to be used in exception handling.)

Standard Extension for Compressed Instructions is great. I like it. No 32-bit word requirement for instruction alignment is good.

Interrupt Controller

Bumblebee core has an Interrupt Controller named "ECLIC". It seems it's "enhanced" version of CLIC (Core-Local Interrupt Controller).

CLIC specification is available at:


An implementation of PLIC (Platform-Level Interrupt Controller) is available at:


Chopstx's Requirement to Interrupt Controller Hardware

In Chopstx, the requirement for MCU is simple: Each hardware interrupt should be able to be masked independently.

In ECLIC, I like interrupt handling support with no vector.

(E)CLIC is a bit over-specification for Chopstx. I prefer more simpler interrupt controller.

Fast Interrupt Handling?

People care about "fast" interrupt handling, or less (and less) interrupt latency.

From the viewpoint of Chopstx, if your application requires so fast response (say, latency less than 100 instructions ~= 1us for GD32VF103), just make it busy loop, or let off-load such a task to another core/MCU or FPGA.

Synchronous Interrupt Handling

The RISC-V specification for WFI instruction is great. The instruction is waken up even with interrupt masked state when interrupt occurs.

It will be great if we have a mode of WFI or another instruction to receive interrupt synchronously; At the wake up of the instruction, MCAUSE register is updated.

No thanks to EABI

There is a proposal of different ABI for RISC-V, named EABI.

EABI: https://github.com/riscv/riscv-eabi-spec/blob/master/EABI.adoc

In my opinion, in such a situation, I recommend to use RV32E with less registers.

Note that, in Chopstx, the number of callee saved registers matters for interrupt latency.

The idle thread in Chopstx is a special thread, which is entered when there is nothing todo, and is exited by an interrupt.

Usually, it goes like this:

  • On receive of an interrupt, control goes to the internal interrupt handling from the idle thread (the idle thread is "interrupted"). This means the exit from the idle thread. Control never "return"s to the point of interruption. Here, no save of caller saved registers is needed, because control has been already "exited" from the idle thread.
  • A thread which handles the hardware event is determined by hardware interrupt number.
  • It does context switch to the thread, restoring callee saved registers.