As a first step I started porting the original CH32V003 examples by OpenWCH to PIO. And for most of them porting consists merely of copy&paste. You can find the ports on my Github repo.
The only example I’m struggling with is the bootloader example, as I lack understanding of both PIO and CH32V003 Here’s my current understanding:
after reset, depending on boot mode, either the start address of APP flash or that of IAP flash is mapped to reset address 0x00 (see RM v1.3 section 1.2)
as the interrupt vector table is located at 0x00, both APP and IAP can use ISRs without workaround
the IAP flash can only be written via debug interface, not from APP (see RM v1.3 section 16.2.2)
how can I instruct PIO to link the bootloader such that the storage address (for upload) starts at 0x1FFF F000, but that the address after re-mapping (for operation) starts at 0x0000 0000…? Or is this not required for some reason…?
And further reading the reference manual gives me the impression that you indeed have to set a register bit to either reboot to Bootloader memory (so 0x1fff f000 will be remaped to 0x0) or the app (regular code flash remapped to 0x0)
And that remapping & reboot has to be triggered via the functions described by you already.
The bootloader / IAP program has to be written once at the specified address though, like the chinese PDF says…
将 IAP 程序通过 WCH—LinkUtility 下载到 0x1FFFF000。
→ “Download the IAP program to 0x1FFFF000 via WCH-LinkUtility.”
While we do have the facilities for it to change the start linker address, that’s not needed then because in IAP / Bootloader mode, the memory is remapped and so the app will run from 0x0 and thus should be compiled / linked as if it were at 0x0.
do I understand correctly that both APP and IAP codes are linked for starting address 0x00, but are uploaded to 0x8000000 (APP) or 0x1FFFF000 (IAP)…? Actually that makes much more sense than my initial thought!
But then the next question: how do change the target upload address in PlatformIO for IAP? Apparently the default setting is set to 0x8000000 (APP)…? Thanks a lot in advance!
During an upload, OpenOCD is given the .elf file (upload_target = target_elf), from which it will automatically figure out the upload address based on the start addresses of the to-be-loaded sections, which are determined by the linker script of the application.
In PlatformIO we give it a unified linking script of
where the #flash_start template variables are substituted based on defaults or given platformio.ini values
meaning that, if you would add
board_upload.offset_address = 0x8000000
the application would be linked to be starting at 0x8000000 and the upload program would also try and write to this address.
Note that the default is 0x0 for the flash origin address, because 0x8000000 would be remapped to 0x0 for a normal app run (just like the bootloader would).
…that however results in the pecularity that the flash origin address (linker script) can’t be independently controlled from the upload address, with the current logic they’ll always match. However, if say we want to build + upload the IAP bootloader using PlatformIO, it might be okay to use board_upload.offset_address = 0x1FFFF000 because 1. it will cause the program to be uploaded to the correct address and 2. even if the MCU remaps 0x0 → 0x1FFFF000, I think the memory is also still available, or rather mirrored, at the original 0x1FFFF000, so it happens to work.
** Programming Started **
Info : device id = 0xaa42abcd
Info : flash size = 16kbytes
Warn : no flash bank found for address 0x1ffff000
Warn : no flash bank found for address 0x1ffff878
** Programming Finished **
** Verify Started **
Error: checksum mismatch - attempting binary compare
embedded:startup.tcl:1162: Error: ** Verify Failed **
in procedure 'program'
in procedure 'program_error' called at file "embedded:startup.tcl", line 1223
at file "embedded:startup.tcl", line 1162
*** [upload] Error 1
I noticed that the build log reports a total codesize of ~69kB - mainly due to debug code. But according to the DS the “System Flash” has only 1920B. Can that be the problem?
Can you use the WCH-LinkUtility instead like the chinese docs say? If you have MounRiver IDE installed, it’s C:\MounRiver\MounRiver_Studio\ExTool\SWDTool\WCH-LinkUtility.exe, otherwise, https://file.io/DweYK7WotV7q
hi again,
I haven’t Windows installed (anymore). Therefore I tried wlink. After some issues I can now use it to upload code to System Flash. Here’s the output of uploading a small (dummy) binary:
IMHO that is because the IAP binary (2176B) is larger than the System Flash size (1920B). To me the below verbose build output seems to indicate that the debug code is responsible for most of that. Is there any way to omit debug code? And while we’re at it, maybe also tell PIO that for this project the flash size is only 1920B, not 16kB…?
No the .debug sections do not contribute to the .bin file, they’re only debug info (because I do activate -g in release builds so that .elf have some symbol info…)
Only these ones are relevant. Flash is filled with .init, .vctor, .text, and that’s bigger than 1920 bytes.
However, if I compile the project it uses exactly 1920 bytes.
RAM: [== ] 22.9% (used 468 bytes from 2048 bytes)
Flash: [==========] 100.0% (used 1920 bytes from 1920 bytes)
Section .text seems to be responsible for the size difference. Does Linux use an older version of compiler toolchain? Or do I need to add a “special option” to platform.ini?
The numbers in both your and my case don’t really add up to 1920B and 2172B, respectively. Which sections actually end up in flash?
How do you tell PIO that System Flash is only 1920B?
after optimizing the example a bit I could add a mode indication by LED (fast blinking). The APP example blinks the same pin slowly. That way I always know which code is actually running
then I seemingly bricked the device:
while playing around with the IAP example I commented the USART code and the mode switching. I figured I can always flash via debug interface
switching to IAP mode worked as expected (LED blinks fast), but now WCH-LinkE can no longer connect (Error: WCH-Link underlying protocol error: 55 [01]). Power off/on also has no effect, device remains in IAP mode. And since mode switching is commented, I cannot exit IAP mode
To my understanding that means:
boot mode information is indeed stored in flash (see initial post). Else information would be lost after power off
debug not possibly in IAP mode indicates that on µC side debug seems to be via code included in normal applications, which is omitted in IAP example. Is this why a special linker file is required? Or is there another information why the debugger can connect in APP mode, but not in IAP mode?
PS: any idea if/how I can recover my device? I don’t mind the 10ct, but replacing the µC is a pain
Another person also thought they had bricked their ch32v003, but with a bit of timing, you can hold down the RESET button of the board (or power it off), press “Upload”, then when the uploader seems to hang or connect, release reset (or give power). Might need multiple tries.
thanks for the hint, but even after trying very often I wasn’t able to recover my CH32V003. Specifically I tried with WCHLink-Utility, WLINK, OpenOCD - but to no avail
Seems like I have to replace the µC
PS: can you confirm my suspicion that debugging on µC side is via SW that is linked into the code? If not, why can debugger not connect to a device which is in IAP mode?
I’m trying to upload code via Platformio ->Upload and getting an error:
Summary
Configuring upload protocol…
AVAILABLE: isp, minichlink, wch-link
CURRENT: upload_protocol = wch-link
Uploading .pio\build\genericCH32V003F4P6\firmware.elf
Open On-Chip Debugger 0.11.0+dev-02415-gfad123a16-dirty (2023-01-03-10:00)
Licensed under GNU GPL v2
For bug reports, read OpenOCD: Bug Reporting
debug_level: 1
Warn : Transport “sdi” was already selected
Ready for Remote Connections
*** [upload] Error 1
What could be the problem? Through the WCH Link Utility it is stitched without problems.
Chip ch32f008f4p6
VSCode 1.79.2
OS Windows_NT x64 10.0.0.17763