Power-Off Reset: How to Unbrick the CH32V003 in a SOP-8 Package
I continue to explore CH32V microcontrollers. Today, I have the tiny CH32V003J4M6 in a SOP-8 package on my desk.
This is the smallest package with a bare minimum of pins — 2 are for power, leaving 6 available for use. It doesn’t even have a hardware reset pin (NRST).
Like other microcontrollers in the CH32V00x series, it is programmed via a single SWIO wire (pin 8). And here lies an interesting problem: if you initialize this pin in your firmware for other tasks, it stops working as SWIO. After that, programming the chip using the standard method becomes impossible.
For example, the following code prints “Hello world” to the UART:
#include <ch32v00x.h>
#include <debug.h>
void NMI_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void HardFault_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
int main(void) {
SystemCoreClockUpdate();
Delay_Init();
USART_Printf_Init(9600);
while (1) {
printf("Hello world from CH32V003\r\n");
Delay_Ms(1000);
}
return 0;
}
void NMI_Handler(void) {}
void HardFault_Handler(void)
{
while (1)
{
}
}I’m using PlatformIO with the ch32v support package. The first time, this code flashes without any issues, but when I tried to update the firmware a second time, I got an error:
The WCH-LinkE no longer sees the microcontroller. And none of the
minichlink options helped me. So, I had to grab a Windows
PC and run the official WCH-LinkUtility.
In the Series field, you need to select CH32V003, and then go to the Target menu.
There is an option called “Clear All Code Flash-By Power off” — which is exactly what we need right now. This option cuts off and reapplies power to the microcontroller, managing to send the memory erase command before the firmware itself boots up. After this, the microcontroller is completely clean and waiting to be flashed again.
I got curious about what exactly the programmer transmits to the CH32V003, so I captured a logic trace of VDD/SWIO. Here is what the process looks like:
You can also download the dump using these links: CSV, DSView.
Lifehack: To avoid falling into this trap again, you
can add a Delay_Ms(2000) before initializing the UART. With
this delay, resetting via minichlink -u works flawlessly
for me. Alternatively, if you have fast hands, you can apply power to
the microcontroller and instantly trigger the flashing process — this
also does the trick.







Comments
Post a Comment