Skip to main content

CH32 Environment Setup

The RISC-V toolchain situation for the CH32 series is quite chaotic. The following two options are recommended:

  • The official riscv-wch-elf bundled with MRS: Supports WCH's rv32imafcxw extended instruction set, but has incomplete C++ standard library support, making it incompatible with libraries like Eigen.
  • Upstream riscv32-unknown-elf: Does not support WCH's extended instruction set, but provides complete C++ standard library support. On Windows, that means using MSYS2, which can be a bit of a hassle.

For quick compilation, you can use the Docker image provided by this project.

CMake Configuration

An additional option needs to be configured: LIBXR_CH32_CONFIG_FILE, which specifies the path to the CH32 peripheral library configuration file, such as: ch32v30x_conf.h.

set(LIBXR_SYSTEM FreeRTOS)
set(LIBXR_DRIVER ch)

set(LIBXR_CH32_CONFIG_FILE "ch32v30x_conf.h")

add_subdirectory(libxr)

...

CH32 Driver Library

WCH’s official peripheral drivers have (but are not limited to) the following bugs:

  • Multiple extern "C" definitions, causing header include errors under C++.
  • USB peripheral source and header files exist but are not actually referenced.
  • FreeRTOS mstatus-related bits are set incorrectly, leading to abnormal task switching and priority handling.
  • Definitions for non-existent peripheral groups.

All of the above have been fixed in the sample project.

In addition, for LibXR’s time base to work, you must manually add the following code to the SysTick interrupt handler:

void SysTick_Handler( void )
{
extern void libxr_systick_handler(void);
libxr_systick_handler();
......
}

Flash Issues

  • The flash write clock frequency must be less than 60 MHz.
  • After an erase, if no write is performed, although the flash contents should be 0xFF, the actual value read back is a magic number (0xE339u).
  • Many models include “bonus” flash whose speed is roughly two orders of magnitude slower than the normal flash.
  • When using the extra flash, you need to add the wch_riscv unfreeze command to OpenOCD for programming to work properly.

Reference OpenOCD Commands

"openOCDLaunchCommands": [
"init",
"wch_riscv unfreeze"
],

Example Project

CH32V307+FreeRTOS+XRUSB

CH32V203+FreeRTOS+XRUSB