Bootloaders and cheap RISC-V (CH32X035 and CH32V003) - Page 1
Forum section: electronics / general

author: dmendesf
author_rank: Frequent Contributor
timestamp: March 30, 2025, 03:45:34 am
content: Hello everybodyI´m a seasoned STM32 programmer but totally new to RISC-V. For a revision of a cost sensitive product i´m thinking about using both CH32X035 and CH32V003. I can read the datasheet and see the peripherals I need (even bought cheap development kits at Aliexpress to be sure it works as intended) but there´s a requisite that for me is harder to judge by the datasheet and will take some non-trivial time to test so I decided to ask here: Any of these chips has any limitation that precludes writing a simple serial bootloader for them? Firmware must be field updated by a ESP32 via serial port...ThanksDaniel

author: brucehoult
author_rank: Super Contributor
timestamp: March 30, 2025, 05:19:30 am
content: I think what you're asking is essentially "Can a program rewrite parts of the flash, without special external voltages or things like that?"I think this may address that:https://github.com/cnlohr/ch32fun/blob/master/examples/flashtest/flashtest.cA useful site in general for CH32V examples.

author: dmendesf
author_rank: Frequent Contributor
timestamp: March 30, 2025, 06:22:51 am
content: Thank you for your answer but it's a bit more than that: interrupt vectors must be moved (or double jumps implemented... Maybe I'm forgetting something. Can the bootloader area be locked down so it is never overwritten? Small details that make robust (and non-convoluted) systems.Daniel

author: HwAoRrDk
author_rank: Super Contributor
timestamp: March 30, 2025, 01:02:35 pm
content: Both of these chips already has a factory-supplied bootloader thatmightbe suitable for your needs, avoiding the need to write your own.Each chip has a separate 'BOOT' flash area (3KB for '035, 2KB for '003 - see datasheet memory map) that contains the bootloader code. The CH32X035 bootloader is accessible via either USB or serial UART; the CH32V003 bootloader supports only serial UART. The factory bootloader is capable of erasing, writing, and verifying the user application flash (butnotreading it out), and reading and writing the configuration option bytes. The communication protocol, while not officially documented by WCH, is fairly simple and has some open-source implementations.However, there are some caveats:- For the CH32V003, there is no external means of controlling the bootloader (e.g. BOOTn strapping pins); you can only signal that the bootloader is entered at next reset by writing a couple of special values to a register and commanding a software reset. Thus, it's only really useful for in-app firmware updates. But this seems to be what you want to do, so...- My experience has been that it seems that you can only enter the bootloader of the CH32X035 frompower-onreset, and not a regular reset. I don't know why, such a restriction seems stupid to me; maybe I'm doing something wrong, but it just would not do so by simply hitting the reset button on the eval board I have.You can also do the same thing as above to command the bootloader is entered at next reset by software, though.- Serial UART communication generally runs only at 115,200 baud, so is a bit slow. The CH32X035 bootloader, IIRC, supports an additional 'set baud' command for faster rates, but the CH32V003 does not.The BOOT flash area is actually writable using WCH-Link debug adapter, so you could write your own bootloader and put it there instead of the factory one if you desire. The BOOT area is inherently non-writable from user application code, so you don't need to worry about write-protection.As for write-protection of the user flash area: you can set the WRPR0-3 values in the configuration option bytes to specify write protection of certain parts of the user flash. For the CH32X035, each bit represents a 2K sector of the flash; for the CH32V003 each bit is 1K, with WRPR2-3 unused. See reference manual "User Option Bytes" section.

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 30, 2025, 01:32:44 pm
content: Re-using the bootloader Flash area if the default bootloader doesn't fit the bill is a good idea. I would recommend reading and saving the original one first, when developing, just in case. You have a few KB available which should be plenty (1920 bytes exactly on the CH32V003, 3328 bytes on the CH32X035). Of course you'll need to write a proper linker script to build a bootloader, which is not a big deal for seasoned embedded developers, but worth mentioning, as I don't think there's any example project for a custom bootloader provided by WCH.

author: HwAoRrDk
author_rank: Super Contributor
timestamp: March 30, 2025, 02:22:25 pm
content: Quote from: SiliconWizard on March 30, 2025, 01:32:44 pmThere is:https://github.com/openwch/ch32v003/tree/main/EVT/EXAM/USART_IAP/CH32V00X_IAPBut stupidly, despite it being in the "CH32V003" repository, it seems they have set up their linker script for the CH32V002/4/5/6 that have larger 3K bootloader area (as opposed to 1920B for '003) and bigger RAM size:Code:MEMORY{FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 3328RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 4K}Apart from those size changes, there's not really any differences; both linker script and startup code are essentially the same. After all, when the bootloader is executing, it's also running from the aliased 0x00000000 base address, no different from main application code.

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 30, 2025, 03:00:21 pm
content: Ah, good. I don't think I had seen such an example for the other WCH MCUs I have used (CH32V307 & CH32L103), so had assumed similar for others.As to the linker scripts they provide, they are not the best anyway so I recommend checking them at the very least.One annoying thing is the way they "reserve" space for the stack makes the linker always report a RAM usage of 100%. Sure you can still see the amount used in the bss and data sections, but I find the % RAM report handy.I think their recommended IDE (which I don't use) may compute the RAM usage % on its own, which may be why they didn't bother with the linker script.I personally prefer creating a dedicate memory region for the stack, that's cleaner IMO, although not particularly common.Second thing they tend to do in linker scripts which I find odd is how they get the loading addresses (for sections which are stored in Flash and copied in RAM, such as 'data'). ld provides the LOADADDR() macro just for that, but at WCH, they instead create additional sections just to get the loading addresses, at least I've seen this in several of their linker scripts. That works, but that's just clunky.

author: dmendesf
author_rank: Frequent Contributor
timestamp: March 30, 2025, 04:07:10 pm
content: Thank you all for your valuable insights. Now it's time for me to get my hands dirty

author: westfw
author_rank: Super Contributor
timestamp: April 01, 2025, 12:40:34 am
content: QuoteThe 035 only has 64kB of memory, and the 003 only 16k. How fast do you need?Also, writing flash is pretty slow. On AVRs (which I'm more familiar with), max flash write speed turns out to be not too much faster than 115200bps (about 350kbps, actually. 3.7ms for a 128byte page. (maybe half that, since you need to erase the page first.) The CH32v003 looks like it takes a similar time for a 64byte page, so it won't actually program much faster than 115200bps. ("flash is flash, pretty much. Your fancy 32bit CPUs have flash that runs at about the same write speed as older 8bit chips.")(Of course, the default bootloadermighthave a horrible protocol that introduces additional slow-downs.)

author: HwAoRrDk
author_rank: Super Contributor
timestamp: April 01, 2025, 12:25:58 pm
content: Quote from: westfw on April 01, 2025, 12:40:34 amYes, it does.It only transfers 56 bytes at a time, which is less than the flash page size (64), so it has to buffer writes.