CH32 Environment Setup
Current mainline documentation assumes the WCH GCC15 toolchain path, with compiler prefix riscv32-wch-elf-.
The template projects use this toolchain. The docker-image-ch32-riscv image provides the same toolchain (WCH GCC15 v240).
CMake Configuration
CH32 projects need one extra option: LIBXR_CH32_CONFIG_FILE, which tells LibXR which CH32 peripheral configuration header is active, for example ch32v30x_conf.h.
set(LIBXR_SYSTEM FreeRTOS)
set(LIBXR_DRIVER ch)
set(LIBXR_CH32_CONFIG_FILE "ch32v30x_conf.h")
add_subdirectory(libxr)
The template projects determine the compiler prefix automatically. When the project is assembled by hand or several RISC-V toolchains are installed, set COMPILER_PREFIX explicitly.
Peripheral Library Notes
The official WCH peripheral library still carries several long-standing problems. The current example projects already work around issues such as:
- duplicated
extern "C"definitions that break C++ header inclusion; - USB sources and headers existing in the vendor library but not being wired into the project correctly by default;
- incorrect FreeRTOS
mstatushandling affecting task switching and priority behavior; - peripheral-group definitions that remain present even though the actual peripheral does not exist.
Projects that do not start from the example projects and arrange the vendor library by hand need to handle these issues again.
SysTick
CH32Timebase now derives microseconds and milliseconds directly from the CH32 64-bit SysTick hardware counter. It no longer depends on a software accumulator called from SysTick_Handler.
Before constructing CH32Timebase, the BSP configures SysTick as:
- HCLK-driven;
- a free-running 64-bit up-counter;
- enabled;
- without auto-reload or count-down mode;
- with
SystemCoreClock >= 1 MHz.
Do not stop or reset this counter during use, and do not change HCLK without re-establishing the timebase. The BSP may still manage compare values and RTOS tick interrupts, but it must not implement the tick by periodically clearing this same counter.
Flash Notes
Keep the following in mind:
- during erase and program, the driver switches the flash access clock to SYSCLK/2 and requires
SystemCoreClockto be at most120 MHz; - after erase but before a write, flash may look like
0xffexternally while actual readback can still show magic value0xE339u; - many parts include extra flash regions that are much slower than the main flash;
- when using those extra flash areas, OpenOCD often needs
wch_riscv unfreezeto keep programming stable.
Reference OpenOCD snippet:
"openOCDLaunchCommands": [
"init",
"wch_riscv unfreeze"
],