GD32VF103 RISC-V¶
Manufactured by Gigadevice with 128kB Flash and 32kB Ram at 108MHz, this RISC-V core uses most of the STM32F10x peripherals
See also
Features¶
Core¶
RISC-V Open Design Core, NOT ARM.
SVD Summary¶
46 peripherals
1074 registers
7713 bitfields
SVD Named Peripherals¶
ADC0 RCU
ADC1 RTC
AFIO SPI0
BKP SPI1
CAN0 SPI2
CAN1 TIMER0
CRC TIMER1
DAC TIMER2
DBG TIMER3
DMA0 TIMER4
DMA1 TIMER5
EXMC TIMER6
EXTI USART0
FMC USART1
FWDGT USART2
GPIOA UART3
GPIOB UART4
GPIOC USBFS_GLOBAL
GPIOD USBFS_HOST
GPIOE USBFS_DEVICE
I2C0 USBFS_PWRCLK
I2C1 WWDGT
ECLIC PMU
Interesting Features¶
Instruction profiling for performance measurement using RISC-V “instructions execute” and “instruction clock” registers
Totally different interrupt peripheral to STM32F10x
Two ADC’s
One DAC
The RISC-V processors have a 12 bit (plus-or-minus 2048) byte conditional branch range. The usual assembly language trick for getting around this limitation is to invert the sense of the test and conditionally branch over an unconditional branch with more offset bits.
Note
Re GD32VF103Cx conditional branch range: Since instructions can only be aligned to 4 bytes, or 2 bytes for compressed instructions, the 12-bit offset actually encodes an offset that is in multiples of 2 bytes, which is clever, so the range is +/-4096 bytes.
Mecrisp-Quintus¶
Matthias Koch has released his experimental port of Mecrisp-Quintus Forth for the GD32VF103 RISC-V MCU
Download it here: https://sourceforge.net/projects/mecrisp/files/mecrisp-quintus-0.36-experimental.tar.gz
Note
if the date is later than 12Dec2021 check the https://sourceforge.net/projects/mecrisp/files/ site for the latest version.
Premade Boards¶
The Longan-Nano¶
Longan Nano is a $5 development board based on GD32VF103CBT6 MCU with RISC-V 32-bit core of GigaDevice.
Sold by Seeed comes with a 0.96inch 160x80 IPS RGB LCD and an acrylic transparent case.
Chip: GD32VF103, 128kB Flash, 32kB Ram at 108MHz.
Board, 160x80 IPS RGB LCD, USB “C” socket, micro SD slot, Boot-0 and Reset button etc.
Pinouts¶
Notes:¶
Manually taken from the schematic
, so double check in case of errors.
LCD (P1)¶
160x80 IPS RGB LCD, doesn’t seem have any inbuilt fonts.
GPIO |
Signal |
---|---|
Hardwired |
LedA (backlight 2V8) |
PB1 |
Reset |
PB10 |
RS |
PA7 |
SDA |
PA5 |
SCL |
PB2 |
CS |
LEDS¶
Colour |
GPIO |
---|---|
Red |
GPIOC_13 |
Green |
GPIOA_1 |
Blue |
GPIOA_2 |
Terminal¶
USART 0 BASE $40013800
Connect a 3.3V terminal bridge to T0 and R0 of the board:
Board |
USB/serial dongle |
---|---|
3V3 |
3V3 |
R0 |
TXD |
T0 |
RXD |
GND |
GND |
SD Card (J2)¶
Signal |
PIN |
Connects to |
GPIO |
---|---|---|---|
DAT2 |
1 |
N/C |
|
DAT3/CS |
2 |
SPI_CS_TF |
PB12 |
CMD/MOSI |
3 |
SPI1_MOSI |
PB15 plus 10K pullup to 3V3 |
CLK |
5 |
SPI1_SCLK |
PB13 |
DAT0/MISO |
7 |
SPI1_MISO |
PB14 plus 10K pullup to 3V3 |
DAT1 |
8 |
N/C |
|
PAD4 |
9 |
GND |
|
PAD3 |
12 |
GND |
|
PAD2 |
11 |
GND |
|
PAD1 |
10 |
GND |
Header (P2)¶
Pin |
GPIO |
Description |
---|---|---|
1 |
GND |
|
2 |
GD_UART0_TX |
|
3 |
GD_UART0_RX |
|
4 |
3V3 |
|
5 |
PA13 |
JTMS |
6 |
PA14 |
JTCK |
7 |
PA15 |
JTDI |
8 |
PB3 |
JTDO |
Unused GPIO’s¶
PA3 PB4
PA4 PB5
PA6 PB6
PA8 PB7
PA9 PB8
PA9 PB9
PA10 PB10
PA11 PB11
PA12
Wio Lite RISC-V (GD32VF103) - With ESP8266¶
Wio Lite RISC-V is a feather form factor RISC-V development board Based on GD32VF103, with the onboard ESP8266 Wio Core, it also features WiFi function.
https://www.seeedstudio.com/Wio-Lite-RISC-V-GD32VF103-p-4293.html $6.90 USD
Polos GD32V Alef¶
Polos GD32VF103 Alef Board – RISC-V MCU Board with 128KB Flash 32KB RAM
https://www.analoglamb.com/product/polos-gd32v-alef-board-risc-v-mcu-board/ $2.99 USD
Flashing the Mecrisp-Quintus binary¶
The GD32VF103 has a bootloader bug that makes it return the wrong page size and page count for its internal flash. While this is merely an annoyance for uploads (we get extra data), it breaks downloads completely since only half the pages are erased and written. (Every other page is left untouched when we use the reported page size of 2048.)
Nucleisys (the core designer) has a fork of dfu-utils with a fix for this bug [1]. and this patch is a cleaned-up version of that. I’ve added a new quirk that allows custom fixup code to run after the memory layout is read but before it’s used, so much of this code is applicable to other devices that may have similar bugs.
https://github.com/riscv-mcu/gd32-dfu-utils/commit/c2c8215061b08146e6a4c8c22bc57fae95c656
GD Tools for Linux are required to flash!¶
https://github.com/riscv-mcu/gd32-dfu-utils
"description": "GD32V FLASH TOOLS",
"name": "tool-gd32vflash",
"system": "linux_x86_64",
"url": "https://github.com/riscv-mcu/gd32-dfu-utils",
"version": "0.1.0"
Flashing¶
Erasure is required first or a Mecrisp-Quintus update probably won’t run or may have odd behaviour. Erasing is not documented in the dfu-util documentation, for fear of people bricking their (generic) devices but I doubt if bricking is possible in this case.
dfu-util -a 0 -d 28e9:0189 -s 0x8000000:mass-erase:force -D mecrisp-quintus-gd32vf103cb.bin
dfu-util: Invalid DFU suffix signature
dfu-util: A valid DFU suffix will be required in a future dfu-util release!!!
Opening DFU capable USB device...
ID 28e9:0189
Run-time device DFU version 011a
Claiming USB DFU Interface...
Setting Alternate Setting #0 ...
Determining device status: state = dfuERROR, status = 10
dfuERROR, clearing status
Determining device status: state = dfuIDLE, status = 0
dfuIDLE, continuing
DFU mode device DFU version 011a
Device returned transfer size 2048
GD32 flash memory access detected
Device model: GD32VF103CB
Memory segment (0x08000000 - 0801ffff)(rew)
Erase size 1024, page count 128
Performing mass erase, this can take a moment
Setting timeout to 35 seconds
Downloading to address = 0x08000000, size = 18816
Download [=========================] 100% 18816 bytes
Download done.
File downloaded successfully
Connect a Terminal¶
Use a USB/3.3v Dongle like this` like one of these.
power is supplied via the USB connector. Board needs a power/reset after flashing.
serial comms is connected as below at 115200 baud :
Longan-nano |
usb/3.3v serial dongle |
---|---|
To |
RX |
Ro |
TX |
0v |
0v |
Mecrisp-Quintus Greeting Message¶
Using Picocom as the serial terminal
picocom -b 115200 /dev/cuaU0 --imap lfcrlf,crcrlf --omap delbs,crlf --send-cmd "ascii-xfr -s -l200"
Mecrisp-Quintus 0.27 for RISC-V 32 IMC on GD32VF103CB by Matthias Koch
This one is running a init word that increases teh clock and baud rate. It also has all
Clock: 8MHz --> 104MHz
Serial: 115200 bps --> 460800 bps, please change the terminal speed accordingly.
If Picocom is in use, 50mS will now be adequate for EOL delays.
Words¶
words4
--- Mecrisp-Quintus 0.27 ---
hflash! flash! flashpageerase eraseflash
eraseflashfrom sp@ sp! rp@
rp! dup drop ?dup
swap nip over tuck
rot -rot pick depth
rdepth >r r> r@
rdrop rpick 0= 0<>
0< >= <= <
> u>= u<= u<
u> <> = min
max umin umax +
- slt sltu 1-
1+ 2- 2+ cell+
negate not shr shl
2* cells 2/ abs
even base binary decimal
hex eint? eint dint
wfi mcause mepc cycles64
cycles unhandled fault irq-fault
irq-collection hook-emit hook-key hook-emit?
hook-key? hook-pause nop emit
key emit? key? pause
serial-emit serial-key serial-emit? serial-key?
reset accept tib >in
current-source setsource source query
compare cr bl space
spaces [char] char (
\ ." c" s"
(.") (c") (s") count
ctype type skipstring risc-v
hex. .rs words h.s
.s u.s token parse
does> <builds create registerliteral,
literal, call, inline, skipdefinition
string, ['] ' postpone
exit recurse state ]
[ : ; execute
immediate inline compileonly 0-foldable
1-foldable 2-foldable 3-foldable 4-foldable
5-foldable 6-foldable 7-foldable constant
2constant smudge setflags aligned
here flashvar-here addrinflash? addrinram?
align h, , allot
forgetram compiletoram? compiletoram compiletoflash
(create) variable 2variable nvariable
buffer: dictionarystart dictionarynext hook-find
find (find) k j
i leave (do) unloop
+loop loop do ?do
case ?of of endof
endcase uj-encoding? sb-encoding? cj-encoding?
then else if ahead
repeat while until again
begin and bic or
xor clz ror rol
arshift rshift lshift not
invert true false evaluate
interpret hook-quit quit digit
number .digit hold hold<
sign #> f#S f#
#S # <# f.
f.n ud. d. u.
. * um* m*
/ mod u/mod /mod
2dup 2drop 2swap 2nip
2over 2tuck 2rot 2-rot
2>r 2r> 2r@ 2rdrop
d2/ d2* dshr dshl
dabs dnegate d- d+
s>d ud* udm* */
*/mod u*/ u*/mod um/mod
m/mod ud/mod d/mod d/
f* f/ 2! 2@
du< du> d< d>
d0< d0= d<> d=
move fill @ !
+! h@ h@signed h!
h+! c@ c@signed c!
c+! bis! bic! xor!
bit@ hbis! hbic! hxor!
hbit@ cbis! cbic! cxor!
cbit@ --- Flash Dictionary ---
104mhz init words4 flashfree
ramfree memstats free DBG
DBG_ID DBG_CTL DBG_ID. DBG_CTL.
DBG. EXTI EXTI_INTEN EXTI_EVEN
EXTI_RTEN EXTI_FTEN EXTI_SWIEV EXTI_PD
EXTI_INTEN. EXTI_EVEN. EXTI_RTEN. EXTI_FTEN.
EXTI_SWIEV. EXTI_PD. EXTI. GPIOA
GPIOA_CTL0 GPIOA_CTL1 GPIOA_ISTAT GPIOA_OCTL
GPIOA_BOP GPIOA_BC GPIOA_LOCK GPIOA_CTL0.
GPIOA_CTL1. GPIOA_ISTAT. GPIOA_OCTL. GPIOA_BOP.
GPIOA_BC. GPIOA_LOCK. GPIOA. GPIOB
GPIOB_CTL0 GPIOB_CTL1 GPIOB_ISTAT GPIOB_OCTL
GPIOB_BOP GPIOB_BC GPIOB_LOCK GPIOB_CTL0.
GPIOB_CTL1. GPIOB_ISTAT. GPIOB_OCTL. GPIOB_BOP.
GPIOB_BC. GPIOB_LOCK. GPIOB. PMU
PMU_CTL PMU_CS PMU_CTL. PMU_CS.
PMU. RCU RCU_CTL RCU_CFG0
RCU_INT RCU_APB2RST RCU_APB1RST RCU_AHBEN
RCU_APB2EN RCU_APB1EN RCU_BDCTL RCU_RSTSCK
RCU_AHBRST RCU_CFG1 RCU_DSV RCU_CTL.
RCU_CFG0. RCU_INT. RCU_APB2RST. RCU_APB1RST.
RCU_AHBEN. RCU_APB2EN. RCU_APB1EN. RCU_BDCTL.
RCU_RSTSCK. RCU_AHBRST. RCU_CFG1. RCU_DSV.
RCU. USART0 USART0_STAT USART0_DATA
USART0_BAUD USART0_CTL0 USART0_CTL1 USART0_CTL2
USART0_GP USART0_STAT. USART0_DATA. USART0_BAUD.
USART0_CTL0. USART0_CTL1. USART0_CTL2. USART0_GP.
USART0. u.2 u.4 u.8
h.4 h.2 u.ns const.
addr. .decimal b8loop. b16loop.
b16loop-a. b32loop. b32sloop. 1b.
2b. 4bl. 4bh. 16b.
bin. bin1. bin2. bin4.
bin4l. bin4h. DBG DBG_ID
DBG_CTL DBG_ID. DBG_CTL. DBG.
EXTI EXTI_INTEN EXTI_EVEN EXTI_RTEN
EXTI_FTEN EXTI_SWIEV EXTI_PD EXTI_INTEN.
EXTI_EVEN. EXTI_RTEN. EXTI_FTEN. EXTI_SWIEV.
EXTI_PD. EXTI. GPIOA GPIOA_CTL0
GPIOA_CTL1 GPIOA_ISTAT GPIOA_OCTL GPIOA_BOP
GPIOA_BC GPIOA_LOCK GPIOA_CTL0. GPIOA_CTL1.
GPIOA_ISTAT. GPIOA_OCTL. GPIOA_BOP. GPIOA_BC.
GPIOA_LOCK. GPIOA. GPIOB GPIOB_CTL0
GPIOB_CTL1 GPIOB_ISTAT GPIOB_OCTL GPIOB_BOP
GPIOB_BC GPIOB_LOCK GPIOB_CTL0. GPIOB_CTL1.
GPIOB_ISTAT. GPIOB_OCTL. GPIOB_BOP. GPIOB_BC.
GPIOB_LOCK. GPIOB. PMU PMU_CTL
PMU_CS PMU_CTL. PMU_CS. PMU.
RCU RCU_CTL RCU_CFG0 RCU_INT
RCU_APB2RST RCU_APB1RST RCU_AHBEN RCU_APB2EN
RCU_APB1EN RCU_BDCTL RCU_RSTSCK RCU_AHBRST
RCU_CFG1 RCU_DSV RCU_CTL. RCU_CFG0.
RCU_INT. RCU_APB2RST. RCU_APB1RST. RCU_AHBEN.
RCU_APB2EN. RCU_APB1EN. RCU_BDCTL. RCU_RSTSCK.
RCU_AHBRST. RCU_CFG1. RCU_DSV. RCU.
USART0 USART0_STAT USART0_DATA USART0_BAUD
USART0_CTL0 USART0_CTL1 USART0_CTL2 USART0_GP
USART0_STAT. USART0_DATA. USART0_BAUD. USART0_CTL0.
USART0_CTL1. USART0_CTL2. USART0_GP. USART0.
ok.
Register Print¶
I’ve also made a svd2forth file for the rp2040, here it’s printing out “RCU.” This is almost the same as the STM32F103 “RCC.” print.
rcu.
RCU_CTL () $03036483
3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1|
1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0
0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 1 1 0 0 1 0 0 1 0 0 0 0 0 1 1
RCU_CFG0 () $002D840A
3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1|
1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0
0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 1 1 0 0 0 0 1 0 0 0 0 0 0 1 0 1 0
RCU_INT () $00000000
3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1|
1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
RCU_APB2RST (read-write) $00000000
3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1|
1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
RCU_APB1RST (read-write) $00000000
3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1|
1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
RCU_AHBEN (read-write) $00000014
3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1|
1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5
RCU_APB2EN (read-write) $0000403D
3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1|
1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 1 1 0 1
RCU_APB1EN (read-write) $00000000
3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1|
1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
RCU_BDCTL () $00000018
3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1|
1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0
RCU_RSTSCK () $0C000000
3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1|
1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0
0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
RCU_AHBRST (read-write) $00000000
3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1|
1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
RCU_CFG1 (read-write) $00000000
3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1|
1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
RCU_DSV () $00000000
3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1|
1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Utility Programs Ported So Far¶
Memstats¶
Electronic Device ID¶
id
UNIQUE_ID[31:0] 0x3641294D | 6 A ) M
UNIQUE_ID[63:32] 0x00123736 | . . 7 6
UNIQUE_ID[95:64] 0xFFFFFFFF | . . . .
ok.
Register Views¶
Now this device uses the old familiar STM32F103 peripherals, if you know that chip, you’ll recognize the bitfields … BUT all the bitfield names have been changed!
There are so many registers that I can’t fit them all in a “development version” of this chip like I can in a 128kB STM32F103.
46 peripherals
1074 registers
7713 bitfields
Compiling¶
V-0.26¶
A very deep change: Added support for compressed instruction set RV32IMC
For smaller opcodes, register map was changed in all source files on all targets as compressed instructions are available mostly for x8 to x15:
x3 –> x8 TOS
x4 –> x9 Data stack pointer
x5 –> x14 Unsaved temporary 1
x6 –> x15 Unsaved temporary 2
x8 –> x3 Loop index
x9 –> x4 Loop limit
Many changes and improvements everywhere, which surely introduced new bugs: If something crashes on 0.26 and works fine on 0.25, please report.
Added linux-rv32imc target
Switched HX8K and GD32VF103 to IMC Forth core
Added FIFO to the receive side of the Icebreaker UART
HX8K target is now very similiar to Icebreaker
Fixed a few elements left on the stack in fixpt-math-lib-tests.fs
Updated toolchain calls to use riscv64-linux-gnu-* available as package “binutils-riscv64-linux-gnu” in Debian 10
Uses a different toolset to V0.25.
I Installed riscv64-binutils-2.33.1,1 for FreeBSD 12.1 and just had to edit the mecrisp-quintus-0.26-experimental/mecrisp-quintus-source/gd32vf103cb/Makefile like so
# ARMGNU?=riscv64-linux-gnu
ARMGNU?=/usr/local/bin/riscv64-unknown-freebsd12.0
V-0.25¶
If you want to cross compile Matthias GD32VF103CB release, grab the toolchain here, it works on both FreeBSD and Linux being statically linked.
https://sourceforge.net/projects/mecrisp/files/mecrisp-quintus-toolchain.tar.gz/download