How to Add CH32V Support to PlatformIO
CH32V are quite cheap RISC-V architecture microcontrollers from WinChipHead (Nanjing Qinheng Microelectronics). There is also CH32F — these are microcontrollers based on the ARM architecture.
To get started, we will need two things:
A CR-CH32VXX development board (devboard) with a CH32V003 — which is one of the cheapest microcontrollers.
And a WCH-LinkE — a programmer for the CH32V. You can find standard WCH-Link programmers on sale, but they are not suitable for the CH32V00x series because it uses a single-wire programming and debugging protocol. And this is only supported by the more expensive WCH-LinkE.
By the way, there are projects that turn an RP2040 into a similar programmer, but the official utilities (MounRiver Studio) do not support anything other than WCH-Link. However, I don’t use the official IDE anyway. Therefore, I will probably try doing this and describe the process in the near future.
Why do I use PlatformIO instead of MounRiver Studio?
On the one hand, MounRiver Studio is available for Linux, which is my main OS for work. But on the other hand, when I tried to install it and it started asking for the root account password for some unknown actions, my paranoia got the better of me. So I decided it would be better to go and figure out how to add support to PlatformIO. Of course, if it’s really necessary, you could somehow run it either in Docker, under an isolated user, or even on a separate machine.
Out of the box, PlatformIO does not support the CH32V platform. To do anything at all with these microcontrollers, you need to install a third-party support package, and now I will tell you how to do it.
The main source of support is the community repository: https://github.com/Community-PIO-CH32V/platform-ch32v Open the main PlatformIO page and go to the Platforms section:
Click Advanced Instalation:
In the dialog, enter
https://github.com/Community-PIO-CH32V/platform-ch32v.git
and start the installation. This process may take a few minutes while
PlatformIO downloads the necessary packages.
At the end of the installation, we will see a dialog like this. It is
quite long and doesn’t fit on the screen, so you need to scroll down to
the bottom and click OK.
Now let’s check how compilation and flashing work. Create a new project:
Creating a project for the first time may take a while, as PlatformIO downloads necessary components again.
In the new project, we will immediately get an example that blinks an
LED on pin PC1.
main.c
#include <ch32v00x.h>
#include <debug.h>
#define BLINKY_GPIO_PORT GPIOC
#define BLINKY_GPIO_PIN GPIO_Pin_1
#define BLINKY_CLOCK_ENABLE RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE)
void NMI_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void HardFault_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
int main(void) {
SystemCoreClockUpdate();
Delay_Init();
GPIO_InitTypeDef GPIO_InitStructure = {0};
BLINKY_CLOCK_ENABLE;
GPIO_InitStructure.GPIO_Pin = BLINKY_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(BLINKY_GPIO_PORT, &GPIO_InitStructure);
uint8_t ledState = 0;
while (1) {
GPIO_WriteBit(BLINKY_GPIO_PORT, BLINKY_GPIO_PIN, ledState);
ledState ^= 1;
Delay_Ms(1000);
}
return 0;
}
void NMI_Handler(void) {}
void HardFault_Handler(void)
{
while (1)
{
}
}This example, of course, compiles without any problems, so it’s time to connect the programmer to the devboard according to this wiring diagram:
For programming the CH32V00x, you only need 2 power wires and 1 for
SWDIO. You also need to manually add a jumper wire from
PC1 to D1. The designer of this devboard did
this on purpose so as not to occupy the microcontroller pins if you
don’t need the LED.
Once connected, click on PlatformIO: Upload. As a result, the LED blinks:
I also want to show you how to output a simple message to UART and see it in PlatformIO. The WCH-LinkE, besides programming, has pins for UART. You don’t see them in the photo because they are located in the second row of pins on the other side:
| Pin | Description |
|---|---|
| RX | UART RX (Receive data via UART) |
| TX | UART TX (Transmit data via UART) |
| TDO | JTAG Test Data Out |
| TDI | JTAG Test Data In |
| RST | Reset |
JTAG here is intended for working with the ARM line of WCH products.
And we don’t need it right now. Instead, we only need to connect the
UART TX of the CH32V003 microcontroller (PD5) to the UART
RX of the programmer.
We also need to modify the firmware code a little bit:
// Make sure this header file is included
#include <debug.h>
...
int main(void) {
SystemCoreClockUpdate();
Delay_Init();
// Add debug output initialization to UART1 at a baud rate of 9600
USART_Printf_Init(9600);
...
while (1) {
GPIO_WriteBit(BLINKY_GPIO_PORT, BLINKY_GPIO_PIN, ledState);
ledState ^= 1;
// printf now outputs messages directly to UART1
printf("LED is now %s\n", ledState ? "ON" : "OFF");
Delay_Ms(500);
}
...And as a result, we get:











Comments
Post a Comment