Longan-nano RISC-V and PlatformIO

longan_patchwork

The Longan-nano board shown above includes a microcontroller with a RISC-V core. The chip seems to be very similar to the STM32F103C8T6 with the exception that the ARM-Cortex M3 core has been swapped out for a RISC-V Bumblebee core called the GD32VF103CBT6. This little development kit has an Arduino nano form factor and also sports a 160×80 full colour display, an RGB LED and a micro SD-card socket. This particular one came from Seeed Studio at a cost of $4.90 + shipping.

There are two ways of programming this chip: You can use a JTAG debugger (various kinds supported) or you can put the chip into DFU (Device Firmware Update) mode by holding the Reset and Boot button down, releasing the Reset button first. This allows you to program the board using a simple USB-Serial converter. I’ve gone with this initially but will definitely be exploring the details of the RISC-V core with a proper debugger shortly.

Developing code
The documentation for this chip pushes you towards using PlatformIO for development. This is an extension for Visual Studio Code – another first for me. You first install VSCode and then add in the PlatformIO extension (I just followed the online guide and it all just worked 🙂 )

There is good support for the GD32VF103CBT6 within PlatformIO and so there is no problem with setting up environment variables, directories and so on. I chose to develop in C++ which caused me a slight problem with the gd32vf103.h header file. This is intended for use with C projects and includes a definition the bool type. This causes a problem for C++ as it already has such a type. If you edit gd32vf103.h as follows you can fix this (around line 180 look for the enum declaration called bool)

#ifndef __cplusplus
typedef enum {FALSE = 0, TRUE = !FALSE} bool;
#endif

One more thing: when you include this file in your C++ files be sure to surround the include statement with “extern C” as shown below:

extern "C" {
#include "gd32vf103.h"
}

If you don’t do this you run into all sorts of problems with C++ decorated names.

And along came a gotcha
I have to admit that I have been a little lazy when it comes to function return values over the years. Let’s say you write an I/O function that may, in some future design, return an error code – as the project is only starting however you have not written that code yet.
So, your code might look like this:

int test()
{
    int X;
    X = 1;
    /* etc */
}

Note the missing return statement – after all, you haven’t written that code yet. Well, this runs fine on ARM Cortex MCU’s I’ve used, and, also on x86. On RISC-V/GCC9.2 this crashes your program. I spent a while scratching my head over this one. The C++ standard apparently states that behavior in this example is “undefined”. So, be warned: If you state that you are going to return a value then do!

Demo code
I’ve started a repository on github with some examples (multi-colour blinky and a graphics demo for now). You can view it here

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s