“All creatures bow down and surrender to the mighty GigaDevice GD32 VF103 on RISC-V!”

Hey GD32 VF103 on RISC-V: I surrender… For now

Me vs Tech: I will never admit defeat to Tech because I have too much pride… Or toxic masculinity.

I have failed only once… Building a simple IoT Sensor Device on FPGA. The reason for that failure was strongly evident… FPGA Programming is not meant for ordinary mortals! I tucked that project away until we have better open-source graphical FPGA programming tools that can synthesise exactly what I need, without micromanaging every single LUT (OK that’s an exaggeration)

Porting Mynewt OS to GD32 VF103 on RISC-V is my second failure. As I have documented earlier, the low level Mynewt OS code was running fine, even Embedded Rust. But then other issues crept in. Here’s what failure looks like…

History of GitHub commits on the GD32 VF103 port of Mynewt OS. From https://github.com/lupyuen/stm32bluepill-mynewt-sensor/commits/gd32vf103


1️⃣ Too comfortable with Arm Semihosting, SWD Flashing + Debugging and ST-Link

After working on RISC-V for a while, I gotta admit that Arm and STMicroelectronics did a really great job with programming support: Flashing and Debugging!

I love using Arm Semihosting to display debug messages on OpenOCD! Yes some developers are annoyed by the slow transfer of debug messages over Semihosting… But I solved it the software way: Buffering in memory before going a giant dump of debug messages.

I don’t like the hassle of connecting another UART port just to see debug messages. To me, Embedded Programming should be Plug and Play… Just Plug in the ST-Link USB Programmer and start Playing with the gadget! Let’s not subject Embedded Newbies to any extra hassle… We should be thankful they are still hanging on!

While experimenting with Nordic nRF52, I realised there’s something magical about the ST-Link USB dongle. It’s known as a High Level Adapter for SWD, because ST-Link handles the complex SWD protocol internally and presents a simple, high-speed USB interface to OpenOCD. (That’s why I had to use a Raspberry Pi to remove the Flash Protection on nRF52)

So using ST-Link and OpenOCD to flash and debug any STM32 microcontroller, even Nordic nRF52, are super efficient. Today I still enjoy rapid iterative development on PineTime Smart Watch (nRF52)… Arm Semihosting + SWD + ST-Link make the perfect workflow for Embedded Developers!

Now here are my gripes about RISC-V and GD32 VF103…

  1. Took me a while to figure out how to connect OpenOCD to GD32 VF103 via JTAG. Instructions were spotty, and I had to build a special version of OpenOCD just to support GD32 VF103!
  2. Building OpenOCD on macOS to support GD32 VF103 was relatively painless. But building OpenOCD on WindowsIt really hurts! You can see in the Commit Log above that I gave up after many failed attempts to build OpenOCD on Windows… Just not worth my time to solve this tooling issue. (I think GigaDevice should be the party to solve this and provide the Windows binaries for OpenOCD!)
  3. Flashing over JTAG is slow. It disrupts my iterative coding workflow. And I become much less productive. Wished there’s some High Level Adapter for JTAG that flashes more efficiently.
  4. Debug output goes… where? JTAG doesn’t expose a debug messaging port like Arm Semihosting. So I have to use the UART port. Only Sipeed’s JTAG dongle includes a UART interface… Are there other JTAG dongles that support this? I doubt so. (I gave up while porting the UART driver, which was supposed to make my debugging more productive)

2️⃣ GD32 VF103 is just too different from SiFive FE310-G000

Mynewt (and Zephyr) has already been ported to a RISC-V development board: SiFive HiFive1 based on the SiFive FE310-G000 microcontroller. So why don’t we start with the HiFive1 code and tweak it for GD32 VF103?

That’s how I started… And I quickly ran into deep sh… shenanigans.

GD32 VF103 has too many I/O ports: UART, I2C, SPI, CAN, USB… Most of them don’t exist on SiFive FE310-G000. Most modern microcontrollers have a huge selection of ports so I’m not blaming GigaDevice. Since GD32 VF103 was inspired by STM32 Blue Pill (F103), it has as many ports as Blue Pill. (That’s the reason why I upgraded from Arduino Uno to Blue Pill… Farewell Bit Banging, Hello Proper Ports!)

This causes problems when we port an operating system like Mynewt to GD32 VF103… We need to build a driver for UART, another for I2C, another for SPI, another for CAN, another for USB, …

I gave up while building the UART driver (so that I could debug GD32 VF103 more productively).


3️⃣ GD32 VF103 is also too different from STM32 Blue Pill

Since GD32 VF103 was inspired by STM32 Blue Pill, why not copy the driver code from Blue Pill?

It’s not 100% the same. GigaDevice tried very hard to make them look the same (even the Interrupt Vector Table). But the architectures are fundamentally different: Arm vs RISC-V.

System Constants get renamed, Peripheral Addresses get shuffled around, … It gets very tiring to reconcile the STM32 Blue Pill docs with GD32 VF103.

Maybe if I had a whole class of IoT students, I could assign this as homework. But to me it feels like… Administrative Paperwork. Not sure if it’s worth my time.


4️⃣ Is there really an urgency to support RISC-V?

Reflecting on my earlier optimism about RISC-V and GD32 VF103… It seemed to be a sure thing that the China-US Trade War would escalate and the IoT Ecosystem in the East would stop producing Arm chips altogether, and move on to RISC-V.

But that’s not happening any more.

I backtracked to first principles and recalled… What problem are we solving?

If we are trying to make sure that RISC-V boards have a decent operating system like Mynewt (and a proper language like Rust) for teaching IoT… Maybe that’s not so urgent any more. The supply of STM32 Blue Pills and Nordic nRF52 microcontrollers will last for a long while.

Meanwhile we have $20 smart watches like PineTime running on nRF52 desperately seeking a decent operating system like Mynewt (and a proper language like Rust) for teaching IoT. Isn’t that an urgent problem to solve?

Thus I’m waving the White Flag at RISC-V and GD32 VF103 for now… Retreating to the warm cozy feeling of Arm Semihosting, SWD Flashing + Debugging and ST-Link… As I hack away productively on the PineTime Smart Watch.

No Regrets!


The incomplete port of Mynewt OS to GD32 VF103 on RISC-V is at the gd32vf103 branch of the repository below. Basic features like task scheduling are working and so is Rust… Just that we have no drivers for UART, I2C, SPI, CAN, USB, …