Migrating STM32 to CH32V307: RISC-V Low-Level Differences for FreeRTOS / RT-Thread
A frequent question on the 21ic RISC-V board (and in our own community) is
what changes when an STM32F103/F4 Cortex-M project is ported to a CH32V307 (RISC-V RV32IMAC)? FreeRTOS or RT-Thread typically works out of the box — but several low-level traps exist that bite first-time migrators. This thread compiles the practical differences you need to know, drawing on WCH EVT examples, RT-Thread's BSP support, and community debugging.
1. Toolchain Choice Switches the ABI
ARM Cortex-M uses the AAPCS ABI (r0-r12 caller-saved, sp/r13/lr/r14/pc/r15, xPSR). RISC-V uses ILP32 with its own conventions: x0 (zero), x1 (ra), x2 (sp), x8-x9 (s0/fp, s1), x10-x11 (a0-a1, return regs), x12-x17 (a2-a7, args), x18-x27 (s2-s11). If you previously relied on which registers are clobbered by an interrupt, you need to recheck.
Practical consequence: any inline assembly in your STM32 code (often CMSIS-DSP functions or zero-delay busy loops) will not assemble and must be rewritten.
2. Interrupt Stack Handling Is Different
The biggest day-one surprise for ARM migrators is the
interrupt stack. ARM Cortex-M uses a dedicated MSP stack for handlers and PSP for threads; the FPU pushes lazily. RISC-V, by contrast, has
no hardware-maintained exception frame. The trap handler saves the full register context (including mepc, mstatus, mcause, mtval) onto the current stack or a dedicated IRQ stack.
For FreeRTOS this means:
- The WCH port supplied in WCH-EVT uses
portSAVE_CONTEXT / portRESTORE_CONTEXT macros that push the full 32+ register context on the current task's stack
- If you upgrade the FreeRTOS version, double-check the RISC-V port macro names — they have changed between FreeRTOS-Kernel 10.x and 11.x
- Stack overflow detection must account for the larger saved context (~144 bytes minimum on RV32, more if extended with FPU registers)
For RT-Thread the BSP for CH32V307 (in rt-thread/bsp/wch) handles this transparently, but if you write a custom interrupt, you must call
rt_interrupt_enter() /
rt_interrupt_leave() to enable accurate scheduling statistics.
3. Clock Tree Configuration
CH32V307's clock tree differs in two ways from STM32F4:
- HSE is 8 MHz typical but the PLL multiplier matrix is different; PLL multipliers of 5/7/9 etc. work fine, but the USB 48 MHz derivation requires PLL_Q = 9 on STM32, while CH32V307 uses a dedicated USB clock divider
- The internal HSI trim registers live at different addresses; if you copy-paste an LSE/HSE fallback from an STM32 HAL, you will hang the boot
WCH provides a clock-config wizard inside MounRiver Studio (MRS) that generates correct
SystemClock setups. Use it instead of guessing.
4. FSMC and GPIO Quirks
If your STM32F4 used FSMC to talk to an external SRAM/NOR/PSRAM, CH32V307's FSMC is largely compatible at the API surface but expects a slightly different timing-pattern layout. The good news: WCH-EVT provides a working FSMC example for 16-bit SRAM and 16-bit NAND.
GPIO is mostly drop-in, but three subtle differences:
- CH32V307 has 5 V-tolerant GPIO pins (PA0/PA1/PB0/PB1/PB2) — useful but easy to forget on F4 ports where most pins are 5 V
- EXTI lines are mapped differently for some pins; check the alternate-function table, not just the pin number
- AF remapping bits sit at a different offset in the CFGR registers
5. Toolchain & Library Compatibility
MounRiver Studio (MRS) is WCH's official IDE. It bundles GCC for RISC-V (including picolibc and newlib-nano options), OpenOCD profiles for WCH-Link, and a graphical clock config / pin mux viewer. For STM32CubeMX-style projects, MRS imports the MX-ioc pin file format for CH32V-series parts.
Third-party library compatibility hurdles:
- CMSIS packs: there are no official CMSIS-Pack archives for CH32V. You must replace CMSIS device headers with WCH-EVT equivalents. Most ARM-only HAL wrappers need rewriting.
- DSP libraries: CMSIS-DSP is for ARM NEON/CM4 SIMD. CH32V407 has RVV (vector) extension and CH32V307 does not; do not assume SIMD intrinsics work.
- Real-time OS: FreeRTOS has an official RISC-V port that works; RT-Thread has BSPs for CH32V003/V203/V307/V407; Zephyr has had WCH in-tree support since 2025 (Tech62 on the WCH BBS has been actively answering Zephyr questions).
- OpenOCD debugging: WCH-LinkE / WCH-Link are the canonical debug probes. If you prefer J-Link or CMSIS-DAP, check RISC-V compatibility before buying.
6. Practical Migration Checklist
When porting an STM32 project, walk through this checklist:
- Update toolchain from arm-none-eabi-gcc to riscv-none-elf-gcc (MRS bundles this)
- Replace startup file with WCH-EVT equivalent (
startup_ch32v30x.s)
- Replace CMSIS device headers with
ch32v30x.h
- Rewrite any inline asm
- Validate clock config via MRS wizard
- Migrate FreeRTOS port to the upstream RISC-V port (the WCH-EVT port is a known-good starting point)
- For RT-Thread, swap in
bsp/wch/ch32v307 and update Kconfig options
- Validate GPIO AF mappings against the alternate-function table
- Recheck any DMA stream-to-channel mapping — CH32V307 uses different DMA controllers than STM32F4
- Validate USB 2.0 FS code; CH32V307 has a built-in USB FS PHY but the register layout is not 1:1 with STM32
7. When to Stay on STM32 vs Migrate
Migration is worth it when:
- You need the USB high-speed peripheral (CH32V317 at 480 Mbps; CH32H417 at 5 Gbps; or CH32V208 at BLE 5.3)
- You need extra Ethernet (CH32V307 has built-in gigabit Ethernet)
- BOM cost matters — WCH parts are typically 30-60% cheaper than comparable STM32 at high quantity
- You are planning a vector-extension upgrade path (CH32V407 with RVV is pin-compatible with the V307 in many layouts)
Stay on STM32 when:
- Existing CMSIS-DSP SIMD code is central to performance
- The toolchain investment in your team is significant and not repaid by the BOM savings
- Your code relies on ARM-specific peripherals (TrustZone, MPU region layouts)
Sources & Further Reading
- 21ic forum thread: STM32 to CH32V307 RTOS migration Q&A
- WCH-EVT repository (FreeRTOS + RT-Thread + bare-metal examples): https://www.wch.cn/products/CH32V307.html
- FreeRTOS RISC-V port documentation
- RT-Thread BSP for CH32V307
For more WCH RISC-V discussion, see our WCH MCU category. For K1/K3 and broader RISC-V SoC topics, browse the K1 / K3 / OpenWrt categories.
Source: 21ic RISC-V forum thread "STM32 migration to CH32V307 RTOS porting differences" — https://bbs.21ic.com/icview-3528952-1-1.html