User:Vazhnov/PlatformIO + VIM + ccls + Sipeed Longan nano RISC-V

Intro
I'm not a developer.

For my job, I have to edit some shell and Python scripts. I use Vim + vim-syntastic + linters (pylint, shellcheck).

As a hobby, I'm trying to learn how to program in Asm and C for architecture RISC-V.

PlatformIO
PlatformIO is a popular platform with good support of multiple boards (like Arduino, STM32, …).

PlatformIO install
PlatformIO can be installed by Python's package management system pip. Here is an example how to install PlatformIO with Python virtualenv, to not interfere with your system:

Disable telemetry, if you want:

Test: {{Cmd|pio boards|output= Platform: gd32v

=
=============================================================================== ID                      MCU            Frequency    Flash    RAM    Name --- -  ---  ---  -  --- gd32vf103v-eval          GD32VF103VBT6  108MHz       128KB    32KB   GD32VF103V-EVAL sipeed-longan-nano      GD32VF103CBT6  108MHz       128KB    32KB   Sipeed Longan Nano sipeed-longan-nano-lite GD32VF103C8T6  108MHz       64KB     20KB   Sipeed Longan Nano Lite wio_lite_risc-v         GD32VF103CBT6  108MHz       128KB    32KB   Wio Lite RISC-V }}

PlatformIO init
When run at the first time, PlatformIO downloads:


 * — from https://github.com/sipeed/platform-gd32v
 * — from https://github.com/riscv-mcu/GD32VF103_Firmware_Library
 * — from https://github.com/riscv-mcu/riscv-gnu-toolchain

After the last command, creates an empty structure + file  which is important for a syntax checker(s):

PlatformIO integration with different IDE
Inside a directory with source code, it is possible to create a file structure to help your favourite IDE to catch settings.

In common, PlatformIO creates such structure:

Differences described below:


 * : creates configuration files and ,
 * : creates configuration files and ,
 * : creates configuration file (XML),
 * : creates configuration files  and  (both are XML) and a directory ,
 * : creates a configuration file with  options,
 * : creates a configuration files and ,
 * : creates a configuration file ,
 * : creates a configuration files and  (JSON),
 * : creates a configuration file with  options,
 * : creates a configuration files and  (both are XML),
 * : creates a configuration files, and ,

vim
When using Vim + vim-syntastic, it is hard to work with C/C++ code because of errors like

/usr/lib/gcc/riscv64-linux-gnu/11/include/stdint.h|9 col 16 error| fatal error: stdint.h: No such file or directory [c/gcc]

Solution: use language server + LSP client. As an option, use language server + Native LSP client from.

Assembly
Attempt to open RISC-V assembly file with Vim will result with a bunch of errors: hello.s|4 error| Error: no such instruction: `li s1,0x10000000' [asm/gcc] hello.s|5 error| Error: no such instruction: `la s2,message' [asm/gcc] hello.s|6 error| Error: no such instruction: `addi s3,s2,14' [asm/gcc] hello.s|8 error| Error: no such instruction: `lb s4,0(s2)' [asm/gcc] hello.s|9 error| Error: no such instruction: `sb s4,0(s1)' [asm/gcc]

Because vim-syntastic tries to check syntax with system gcc, which doesn't know about RISC-V commands.

Put one of examples into any vimrc file:

ccls
is required by Neovim to check code syntax/style. It is still in "testing" state in Gentoo Portage, so:

Check:

Neovim
v0.5 supports the Language Server Protocol (LSP), which is needed, so testing versions should be allowed:

Install Neovim and Vim plug as it described in Neovim.

Create a configuration file:

Run, execute:

Then add a code from https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#ccls at the end of the configuration file:

udev rules
Create an udev configuration file:

Or follow the official documentation: 99-platformio-udev.rules.

dfu-util
— device firmware update (DFU) USB programmer.

Check:

Boot your Sipeed Longan nano board with "Boot0" button pressed.

QEMU
Let's play with assembler without a real hardware:

If binaries from PlatformIO are used:

Compile:

Create a file, to tell the linker we want to take manual control of the memory layout :

Do some magic:

And run:

Test project: gd32v-lcd
Prepare a test project:

Run neovim:

Execute:

You should see: Language client log: /home/user/.cache/nvim/lsp.log Detected filetype:  c

Client: ccls (id: 1, pid: 5947, bufnr: [1]) filetypes:      c, cpp, objc, objcpp autostart:      true root directory: /tmp/longan-sandbox/gd32v-lcd cmd:            ccls

Configured servers list: ccls

Compile project with PlatformIO:

{{Cmd|pio run|collapse-output=true|output= Processing sipeed-longan-nano (platform: gd32v; framework: gd32vf103-sdk; board: sipeed-longan-nano) --- Verbose mode can be enabled via `-v, --verbose` option CONFIGURATION: https://docs.platformio.org/page/boards/gd32v/sipeed-longan-nano.html PLATFORM: GigaDevice GD32V (1.2.1) > Sipeed Longan Nano HARDWARE: GD32VF103CBT6 108MHz, 32KB RAM, 128KB Flash DEBUG: Current (altera-usb-blaster) External (altera-usb-blaster, gd-link, jlink, rv-link, sipeed-rv-debugger, um232h) PACKAGES: - framework-gd32vf103-sdk 1.0.0 - tool-dfuutil 1.9.200310 - toolchain-gd32v 9.2.0 LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf LDF Modes: Finder ~ chain, Compatibility ~ soft Found 0 compatible libraries Scanning dependencies... No dependencies Building in release mode Compiling .pio/build/sipeed-longan-nano/src/lcd.o Compiling .pio/build/sipeed-longan-nano/src/led.o Compiling .pio/build/sipeed-longan-nano/src/main.o Compiling .pio/build/sipeed-longan-nano/src/systick.o Compiling .pio/build/sipeed-longan-nano/standard_peripheral/Source/gd32vf103_adc.o Compiling .pio/build/sipeed-longan-nano/standard_peripheral/Source/gd32vf103_bkp.o src/lcd.c: In function 'lcd_init': src/lcd.c:176:5: warning: implicit declaration of function 'delay_1ms' [-Wimplicit-function-declaration] 176 |    delay_1ms(1); |    ^ Compiling .pio/build/sipeed-longan-nano/standard_peripheral/Source/gd32vf103_can.o Compiling .pio/build/sipeed-longan-nano/standard_peripheral/Source/gd32vf103_crc.o Compiling .pio/build/sipeed-longan-nano/standard_peripheral/Source/gd32vf103_dac.o Compiling .pio/build/sipeed-longan-nano/standard_peripheral/Source/gd32vf103_dbg.o Compiling .pio/build/sipeed-longan-nano/standard_peripheral/Source/gd32vf103_dma.o Compiling .pio/build/sipeed-longan-nano/standard_peripheral/Source/gd32vf103_eclic.o Compiling .pio/build/sipeed-longan-nano/standard_peripheral/Source/gd32vf103_exmc.o Compiling .pio/build/sipeed-longan-nano/standard_peripheral/Source/gd32vf103_exti.o Compiling .pio/build/sipeed-longan-nano/standard_peripheral/Source/gd32vf103_fmc.o Compiling .pio/build/sipeed-longan-nano/standard_peripheral/Source/gd32vf103_fwdgt.o Compiling .pio/build/sipeed-longan-nano/standard_peripheral/Source/gd32vf103_gpio.o Compiling .pio/build/sipeed-longan-nano/standard_peripheral/Source/gd32vf103_i2c.o Compiling .pio/build/sipeed-longan-nano/standard_peripheral/Source/gd32vf103_pmu.o /home/user/.platformio/packages/framework-gd32vf103-sdk/GD32VF103_standard_peripheral/Source/gd32vf103_i2c.c: In function 'i2c_flag_clear': /home/user/.platformio/packages/framework-gd32vf103-sdk/GD32VF103_standard_peripheral/Source/gd32vf103_i2c.c:610:14: warning: variable 'temp' set but not used [-Wunused-but-set-variable] 610 |    uint32_t temp; |             ^ /home/user/.platformio/packages/framework-gd32vf103-sdk/GD32VF103_standard_peripheral/Source/gd32vf103_i2c.c: In function 'i2c_interrupt_flag_clear': /home/user/.platformio/packages/framework-gd32vf103-sdk/GD32VF103_standard_peripheral/Source/gd32vf103_i2c.c:718:14: warning: variable 'temp' set but not used [-Wunused-but-set-variable] 718 |    uint32_t temp; |             ^ Compiling .pio/build/sipeed-longan-nano/standard_peripheral/Source/gd32vf103_rcu.o Compiling .pio/build/sipeed-longan-nano/standard_peripheral/Source/gd32vf103_rtc.o Compiling .pio/build/sipeed-longan-nano/standard_peripheral/Source/gd32vf103_spi.o Compiling .pio/build/sipeed-longan-nano/standard_peripheral/Source/gd32vf103_timer.o Compiling .pio/build/sipeed-longan-nano/standard_peripheral/Source/gd32vf103_usart.o Compiling .pio/build/sipeed-longan-nano/standard_peripheral/Source/gd32vf103_wwdgt.o Compiling .pio/build/sipeed-longan-nano/standard_peripheral/system_gd32vf103.o Compiling .pio/build/sipeed-longan-nano/RISCV/drivers/n200_func.o Compiling .pio/build/sipeed-longan-nano/RISCV/env_Eclipse/entry.o Compiling .pio/build/sipeed-longan-nano/RISCV/env_Eclipse/handlers.o Compiling .pio/build/sipeed-longan-nano/RISCV/env_Eclipse/init.o Compiling .pio/build/sipeed-longan-nano/RISCV/env_Eclipse/start.o Compiling .pio/build/sipeed-longan-nano/RISCV/env_Eclipse/your_printf.o Compiling .pio/build/sipeed-longan-nano/RISCV/stubs/_exit.o /home/user/.platformio/packages/framework-gd32vf103-sdk/RISCV/env_Eclipse/your_printf.c: In function '__wrap_printf': /home/user/.platformio/packages/framework-gd32vf103-sdk/RISCV/env_Eclipse/your_printf.c:4:1: warning: control reaches end of non-void function [-Wreturn-type] 4 | }     | ^ Compiling .pio/build/sipeed-longan-nano/RISCV/stubs/close.o Compiling .pio/build/sipeed-longan-nano/RISCV/stubs/fstat.o Compiling .pio/build/sipeed-longan-nano/RISCV/stubs/isatty.o Compiling .pio/build/sipeed-longan-nano/RISCV/stubs/lseek.o Compiling .pio/build/sipeed-longan-nano/RISCV/stubs/read.o Compiling .pio/build/sipeed-longan-nano/RISCV/stubs/sbrk.o Compiling .pio/build/sipeed-longan-nano/RISCV/stubs/write.o Compiling .pio/build/sipeed-longan-nano/RISCV/stubs/write_hex.o Archiving .pio/build/sipeed-longan-nano/libRISCV.a Indexing .pio/build/sipeed-longan-nano/libRISCV.a Archiving .pio/build/sipeed-longan-nano/libstandard_peripheral.a Indexing .pio/build/sipeed-longan-nano/libstandard_peripheral.a Linking .pio/build/sipeed-longan-nano/firmware.elf Building .pio/build/sipeed-longan-nano/firmware.bin Checking size .pio/build/sipeed-longan-nano/firmware.elf Adding dfu suffix to firmware.bin Building .pio/build/sipeed-longan-nano/firmware.hex dfu-suffix (dfu-util) 0.9

Copyright 2011-2012 Stefan Schmidt, 2013-2014 Tormod Volden This program is Free Software and has ABSOLUTELY NO WARRANTY Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

Suffix successfully added to file Advanced Memory Usage is available via "PlatformIO Home > Project Inspect" RAM:  [========= ]  85.2% (used 27926 bytes from 32768 bytes) Flash: [=        ]   7.1% (used 9338 bytes from 131072 bytes)

=
==================================================== [SUCCESS] Took 2.01 seconds ================================================================= }}

Flash the SoC (will also download and install ):

{{Cmd|pio run --target upload|collapse-output=true|output= Processing sipeed-longan-nano (platform: gd32v; framework: gd32vf103-sdk; board: sipeed-longan-nano) --- Verbose mode can be enabled via `-v, --verbose` option CONFIGURATION: https://docs.platformio.org/page/boards/gd32v/sipeed-longan-nano.html PLATFORM: GigaDevice GD32V (1.2.1) > Sipeed Longan Nano HARDWARE: GD32VF103CBT6 108MHz, 32KB RAM, 128KB Flash DEBUG: Current (altera-usb-blaster) External (altera-usb-blaster, gd-link, jlink, rv-link, sipeed-rv-debugger, um232h) PACKAGES: - framework-gd32vf103-sdk 1.0.0 - tool-dfuutil 1.9.200310 - tool-gd32vflash 0.1.0 - tool-openocd-gd32v 0.1.1 - toolchain-gd32v 9.2.0 LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf LDF Modes: Finder ~ chain, Compatibility ~ soft Found 0 compatible libraries Scanning dependencies... No dependencies Building in release mode Checking size .pio/build/sipeed-longan-nano/firmware.elf Advanced Memory Usage is available via "PlatformIO Home > Project Inspect" RAM:  [========= ]  85.2% (used 27926 bytes from 32768 bytes) Flash: [=        ]   7.1% (used 9338 bytes from 131072 bytes) Configuring upload protocol... AVAILABLE: altera-usb-blaster, dfu, gd-link, jlink, rv-link, serial, sipeed-rv-debugger, um232h CURRENT: upload_protocol = dfu Uploading .pio/build/sipeed-longan-nano/firmware.bin dfu-util 0.9

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc. Copyright 2010-2020 Tormod Volden and Stefan Schmidt This program is Free Software and has ABSOLUTELY NO WARRANTY Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

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 DfuSe interface name: "Internal Flash " Found GD32VF103, which reports a bad page size and count for its internal memory. Fixed layout based on part number: page size 1024, count 128. Downloading to address = 0x08000000, size = 9344

Erase  	[                         ]   0%            0 bytes Erase  	[=====                    ]  21%         2048 bytes Erase  	[==========               ]  43%         4096 bytes Erase  	[================         ]  65%         6144 bytes Erase  	[=====================    ]  87%         8192 bytes Download	[                        ]   0%            0 bytes Download	[=====                   ]  21%         2048 bytes Download	[==========              ]  43%         4096 bytes Download	[================        ]  65%         6144 bytes Download	[=====================   ]  87%         8192 bytes Download	[=========================] 100%        9344 bytes Download done. File downloaded successfully dfu-util: dfuse_download: libusb_control_transfer returned -4
 * [upload] Error 74

=
==================================================== [FAILED] Took 3.21 seconds ================================================================= }}

(error "dfuse_download: libusb_control_transfer returned -4" is OK).

Board will restart automatically with a new code, and you will see an bouncing amiga ball.

Dig inside
PlatformIO uses to compile the code.

It is possible to pass additional options to the GCC with  option of  in your project. For example, lets keep all assembly source files after compilation:

Also, let's create a disassemble of whole binary firmware: