A simple Makefile based library for WCH’s range of CH32Vxxx RISC-V uControllers.
There’s not too much original work here, most of it has been collated from various file dumps etc. from WCH’s own site and other pages.
|
Note
|
The following assumes you are using some version of linux. It should work on mac with suitable adjustments. Not tried on windows. PRs for different platforms are welcomed. |
I’ve yet to find a known good binary build of the riscv32-unknow-* toolchain, the following shows how to build from source.
Add the following to your .bashrc or equivalent (don’t forget to reload your shell).
export CH32_RISCV=${HOME}/opt/ch32-riscv
export RISCV_OPENOCD_WCH=${HOME}/opt/riscv-openocd-wch
export PATH=${PATH}:${CH32_RISCV}/bin:${RISCV_OPENOCD_WCH}/binsudo apt-get install autoconf automake autotools-dev curl python3 python3-pip python3-tomli libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev ninja-build git cmake libglib2.0-dev libslirp-dev bearsudo pacman -Syu curl python3 libmpc mpfr gmp base-devel texinfo gperf patchutils bc zlib expat libslirp bear hidapi libjaylinksudo yum install autoconf automake python3 libmpc-devel mpfr-devel gmp-devel gawk bison flex texinfo patchutils gcc gcc-c++ zlib-devel expat-devel libslirp-devel bear libgudev-devel libusb-devel hidapi hidapi-devel# Clone master branch
git clone --branch master https://github.com/riscv/riscv-gnu-toolchain ~/github.com/riscv/riscv-gnu-toolchain
cd ~/github.com/riscv/riscv-gnu-toolchain
# Configure build, the --with-* options seem to be correct for the WCH CH32V range of uControllers
./configure --prefix=${CH32_RISCV} --with-arch=rv32g --with-abi=ilp32
# Build and install
make -j$(nproc)
# Test
riscv32-unknown-elf-gcc --version
# Output should be something like this
riscv32-unknown-elf-gcc () 14.2.0
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.I use the excellent wlink to flash the uController.
# udev rule for programmer
sudo cp run/60-libch32v.rules /etc/udev/rules.d/60-libch32v.rules
# reload rules
sudo udevadm control --reload-rulesAt the time of writing, wlink v0.1.1 was the latest released version. I suggest checking the release page to see if that’s changed.
# Get and unpack required version
cd /tmp
wget https://github.com/ch32-rs/wlink/releases/download/v0.1.1/wlink-v0.1.1-linux-x64.tar.gz
tar -xf wlink-v0.1.1-linux-x64.tar.gz
# Copy wlink binary to somewhere in your $PATH (I use ${HOME}/.local/bin)
mkdir -p ${HOME}/.local/bin
cp wlink-linux-x64/wlink ${HOME}/.local/bin
# Test
wlink list
# You should get something like the following (assuming you have a WCH-Link adapter connected)
<WCH-Link#0 libusb device> Bus 001 Device 004 ID 1a86:8010(USB-FS 12 Mbps) (RV mode)I’ve forked link:https://github.com/Seneral/riscv-openocd-wch to provide a somewhat stable openocd build.
git clone https://github.com/nj-designs/riscv-openocd-wch.git ${HOME}/github.com/nj-designs/riscv-openocd-wch
cd ${HOME}/github.com/nj-designs/riscv-openocd-wch
./bootstrap
./configure --prefix=${RISCV_OPENOCD_WCH} --program-prefix=wlink- --enable-wlink --disable-werror
make -j$(nproc)
make installAs an alternative, I’ve included a a build of openocd in the run dir.
Once all of the tools above are install/configured, you can build and test a version of blinky as follows.
To build, simply run make in the root of this repo.
If all goes well, the last few lines of output should look something like this:
Linking...
riscv32-unknown-elf-gcc -std=gnu2x -march=rv32imac_zicsr -mabi=ilp32e -ffreestanding -fno-pic -Os -Werror -g -Wall -Wextra -Ilib/include -Ibuild -DAPP_STDOUT_BUFFER_SIZE=1024 -DAPP_PROVIDE_PRINTF=1 -DAPP_PRINTF_DISABLE_SUPPORT_FLOAT -DAPP_PRINTF_DISABLE_SUPPORT_EXPONENTIAL -DAPP_PRINTF_DISABLE_SUPPORT_LONG_LONG -DAPP_HSE_FREQ=16000000 -DAPP_SYSCLK_FREQ=48000000 -DWCH_CH32V203G6U6=0x96ef63e9 -DLIBCH32_DEVICE_ID=WCH_CH32V203G6U6 -DLIBCH32_DEVICE_NAME="CH32V203G6U6" -DLIBCH32_FAMILY="v203" -DLIBCH32_FLASH_PROG_ADDR=0x08000000 -DLIBCH32_FLASH_SIZE=32768 -DLIBCH32_FLASH_START=0x00000000 -DLIBCH32_HAS_ADC1=1 -DLIBCH32_HAS_ADC2=1 -DLIBCH32_HAS_ADTM1=1 -DLIBCH32_HAS_GPIOA=1 -DLIBCH32_HAS_GPIOB=1 -DLIBCH32_HAS_GPIOD=1 -DLIBCH32_HAS_GPTM2=1 -DLIBCH32_HAS_GPTM3=1 -DLIBCH32_HAS_GPTM4=1 -DLIBCH32_HAS_I2C1=1 -DLIBCH32_HAS_SPI1=1 -DLIBCH32_HAS_USART1=1 -DLIBCH32_HAS_USART2=1 -DLIBCH32_LD_SCRIPT="ch32v.ld" -DLIBCH32_MABI="ilp32e" -DLIBCH32_MARCH="rv32imac_zicsr" -DLIBCH32_SRAM_SIZE=10240 -DLIBCH32_SRAM_START=0x20000000 -DLIBCH32_SYS_TICK_WIDTH=64 -ffunction-sections -fdata-sections build/lib/src/reset.o build/lib/src/v203/vector-v203.o build/app/led-flash/led-flash.o build/lib/src/adc.o build/lib/src/adtm.o build/lib/src/afio.o build/lib/src/core.o build/lib/src/dma.o build/lib/src/gpio.o build/lib/src/gptm.o build/lib/src/i2c.o build/lib/src/init.o build/lib/src/list_mgr.o build/lib/src/printf.o build/lib/src/rcc.o build/lib/src/spi.o build/lib/src/stdout-buffered.o build/lib/src/usart.o -Wl,-Map,build/led-flash.map -nostdlib -nodefaultlibs -nolibc -nostartfiles -Wl,--no-relax -Wl,--gc-sections -Wl,--defsym=RAM_ORIGIN=0x20000000 -Wl,--defsym=RAM_LENGTH=10240 -Wl,--defsym=FLASH_ORIGIN=0x00000000 -Wl,--defsym=FLASH_LENGTH=32768 -Wl,-Tlib/ld/link.ld --output build/led-flash.elf
riscv32-unknown-elf-size -A -x build/led-flash.elf
build/led-flash.elf :
section size addr
.init 0x4 0x0
.vector 0xfc 0x4
.text 0x69c 0x100
.fini 0x0 0x79c
.dalign 0x0 0x20000000
.dlalign 0x0 0x79c
.data 0x8 0x20000000
.bss 0x30 0x20000008
.stack 0x800 0x20002000
.gptm2 0x50 0x40000000
.gptm3 0x50 0x40000400
.gptm4 0x50 0x40000800
.usart2 0x1c 0x40004400
.i2c1 0x22 0x40005400
.afio 0xc 0x40010000
.gpio_a 0x1c 0x40010800
.gpio_b 0x1c 0x40010c00
.gpio_d 0x1c 0x40011400
.adc1 0x50 0x40012400
.adc2 0x50 0x40012800
.spi1 0x22 0x40013000
.adtm1 0x50 0x40012c00
.usart1 0x1c 0x40013800
.dma1 0xa8 0x40020000
.rcc 0x30 0x40021000
.pfic 0xd14 0xe000e000
.systick 0x18 0xe000f000
.riscv.attributes 0x54 0x0
.comment 0xf 0x0
.debug_line 0x2835 0x0
.debug_info 0x66b5 0x0
.debug_abbrev 0x1885 0x0
.debug_aranges 0x2f8 0x0
.debug_str 0x3660 0x0
.debug_ranges 0x20 0x0
.debug_loclists 0xa69 0x0
.debug_rnglists 0x239 0x0
.debug_line_str 0x1f9 0x0
.debug_frame 0x4b0 0x0
Total 0x11529
riscv32-unknown-elf-objdump -h -S -C build/led-flash.elf > build/led-flash.lst
riscv32-unknown-elf-nm -n build/led-flash.elf > build/led-flash.sym
riscv32-unknown-elf-objcopy -O binary build/led-flash.elf build/led-flash.binIf you want to debug your program, first flash your code to the device using make flash.
wlink-openocd -f run/wch-riscv.cfg -c init -c halt -c wlink_reset_resume
# or
./run/openocd -f run/wch-riscv.cfg -c init -c halt -c wlink_reset_resumemake start-gdb-
❏ Improve RCC setup
-
❏ Introduce concept of boards to build system
-
❏ Add ini file as a build dependency