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

NRF905 Revisited

I have worked with the NRF905 radio transceiver in the past as part of a weather station. At the time I wasn’t entirely happy about the code for the radio as it felt a little hacky. Like many others before me I vowed “This time I’m going to do it right” 🙂 so I have set about rewriting the radio part in a more object oriented way. I have put together a transceiver pair as shown below and I intend working on the code to simply the NRF905 application interface as much as I can. Right now there is little abstraction going on – that needs to change.
The transceiver pair consists of a couple of NRF905’s wired to some STM32F030’s mounted on breakout boards. These are wire-wrapped together and a full schematic will eventually be posted along with the code over on github


Update 19-Nov-2019
I have updated the code on github with a tighter interface to the nrf905 class. I also did an initial range test and was getting error free line of sight range of about 200m @ 10dBm. The transmitter was on top of a car and the receiver was at about 1m above the ground. Transmitter and receiver had 1/4 wave monopole antennae. A longer range is possible if you are not concerned about the odd missing packet.