Wch_micro_controllers
For anyone who hasn’t noticed, the landscape for embedded systems has seen some major changes in the last two years.
A large amount of this change is based around the introduction of a serious competitor to ARM cpus; RISC-V(Reduced Instruction Set Computer version 5).
So in this article I want to dive into the new controllers being produced by WCH and go over some of the interesting things I have found.
TOPICS:⌗
- Hardware & Specs
- Devboards
- Tooling
- Language Support
- Some example code in C
- Some attempts in Rust
Hardware & Specs⌗
The new hardware in question is going to focused around the RISC-V ch32v203 to be even more specific the ch32v203k8c6 variant that I’ve managed to hand solder onto a DIP breakout board.
And for those wondering; yes the QFN32 and QFP32 aren’t really ideal for hand soldering; but I don’t have any solder paste at the moment so some 60/40 will work for now.
**CH32V203**
| NAME | K8T6 | C6T6 | F8P6 | G8R6 |
| CPU Freq | 144Mhz | 144Mhz | 144Mhz | 144Mhz |
| Flash Mem | 64k | 32k | 64k | 64k |
| SRAM | 20k | | | |
| GPIO | 28 | | | |
| Package | LQFP32 | | | |
| UART | 2 | | | |
| CAN | 1 | | | |
| SPI | 1 | | | |
| I2C | 1 | | | |
| | | | | |
I’ve left a lot of this table blank for now, I’ll update it as I explore the other varients of the ch32v203 series.
The speed of the cpu itself is decent and the memory is more than enough for any applications I would probably use it for given it’s set of peripherals available.
The controllers support RTC, CAN, USBD and USBHD along with two watchdog timers built into them. It feels very similar to an stm32f4 series chip.
Devboards⌗
WCH have around 4-6 different development boards available online at the moment. Most of these can be bought either through the Aliexpress store or on LCS for around $4-$25 per unit, depending on model.
Most the devboards have a usb-C at a minimum as a default, which is really nice to see compared to many devboards that are still using micro usb type-b or even still mini-b.
The boards are pretty bare bones however mostly functioning as a way to breakout all the pins to standard 2.54mm Dupont headers.
The exception would be the 30X series that seem to have RJ45 and usb-C connections on-board.
If you are looking to get into playing around with them or developing with them, I would honestly get the wch-link debugger/programmer and build my own devboard.
Tooling⌗
IDE⌗
This is where things get a bit interesting. The suggested tool for programming and working with their uC’s is the MouanRiver Studio IDE. It’s based on Eclipse and should be pretty familiar to anyone who has used the STM32CubeIDE program.
GCC⌗
The tool chain itself is a GCC variant and uses the triple riscv-none-elf-gcc
. At that point it’s all going to be the same as any other GCC tool chain
except you just need to pay attention that it’s compiled with the
correct ISA extensions, imac
in the case of the CH32V203 series.
Rust⌗
For doing any rust based development on the wch micro-controllers, you’ll want to look at all of these crates:
- embedded-hal
- nb
- riscv-rt
- riscv
- panic-halt
- ch32v2
But if you’re looking to get started with something that will just work, then I highly recommend you checkout the repo below and give it a spin.
Language Support⌗
- C
- C++
- Rust: (2024-01-01), yes the ch32v10x, ch32v20x, ch32v003 and ch32v30x work.
Some example code in C⌗
#include "debug.h"
void GPIO_Toggle_INIT(void){
/* --- SNIP ---*/
}
void main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
SYstemCoreClockUpdate();
Delay_Init();
GPIO_Toggle_INIT();
while(1) {
Delay_ms(250);
GPIO_WriteBit(
GPIOA,
GPIO_Pin_1,
(i == 0) ? (i = Bit_SET): (i = Bit_RESET)
);
}
}
Some attempts in Rust⌗
The rust example code isn’t really all that interesting, mostly because of all the work that the HAL does in the background.
#![no_std]
#![no_main]
use hal::gpio::GpioExt;
use panic_halt as _;
use riscv as _;
use riscv_rt::entry;
use ch32v20x_hal as hal;
use hal::pac;
use hal::prelude::*;
#[entry]
fn main() -> ! {
let peripherals = pac::Peripherals::take().unwrap();
let rcc = peripherals.RCC.constrain();
let _clocks = rcc.config.sysclk_144m_via_hsi().freeze();
// nanoCH32V203: 8MHz HSE, blue LED
//let gpioa = peripherals.GPIOA.split();
//let mut led = gpioa.pa15.into_push_pull_output();
// FlappyBoard: No HSE, ice-blue LED
let gpiob = peripherals.GPIOB.split();
let mut led = gpiob.pb8.into_push_pull_output();
let cycle = 144_000_000 / 2;
loop {
unsafe { riscv::asm::delay(cycle) }
led.toggle();
}
}
The above code basically just uses the singleton pattern where we only have a single instance of the peripherals.
Once we have this instance we break it out or destructure it into the needed parts; in this case the GPIO pin structs.
The example code shows either pb8
or pa15
being tied to an led, but for
my setup I have a raw ch32v203k8 soldered to a LQFP breakout board with an led
on pb1.
Thoughts⌗
I like it, the peripherals are plentiful, the architecture open-source and has refernce and programming manuals availble.
It’s at such a good price point that it makes it a great alternative to using stm32, r2040 and some of my samd controllers.
Having built in USB capibilities also means I can forgo trying to find some of the commonly used controllers for mechanical keyboards as well.
with that said there really isn’t an amazing devboard availble at the moment.
I’m hoping that WCH creates some that feature the wch programmer/debugger like the link-e or DAP.
For now though I have 11 of the wch link-e programmers just sitting around so I’m probably not going to have an issue with that.
Conclusion⌗
The Good
- Good Price Point.
- Interesting cpu design.
- Amazing features.
The not so good
- Unknown errata/hardware bugs if there are any(it’s a new chip)
- Lack of AEQ or any other kinds of certifications.
- Possibly may be hampered by geopolitical situation for Western customers.