#1 2026-07-24 15:04:42

jokeR
Учасник
Зареєстрований: 2024-12-12
Повідомлень: 221

CH32V003 as arduino

Купив собі колись кілька плат з CH32V003F4P6 на розпродажі, і програматор, і нарешті дійшли ручки іх помацати wink
І вияснилось, що програматор не той wink Я купив wch-link, а треба wch-linkE wink

Але не все так фатально. В інтернетах є проект емулятора minichlink на arduino wink
Береться хттпс://github.com/Community-PIO-CH32V/Ardulink-pio, зашивається звичайним способом в Arduino (я взяв Uno). Для інших варіантів треба вказати правильну плату, з правильною частотою резонатора.

Тепер arduino стає Ardulink Programmer. І platformio може з ним працювати (mounriver-studio, на жаль, ні).

Якщо в platformio.ini вписати

[env:ch32v003f4p6_evt_r0]
platform = ch32v
board = ch32v003f4p6_evt_r0
framework = arduino
upload_protocol = minichlink
upload_port = /dev/ttyACM0
upload_flags = "-c ${UPLOAD_PORT}"

то все прошивається, правда повільно.

З"єднання таке:
Arduino - CH32
GND        -          GND
8 - 1K резистор - SWD
9             -          V

Класичний blink

#include <Arduino.h>

#define LED_PIN PD0

void setup() {
    pinMode(LED_PIN, OUTPUT); }
void loop() {
    digitalWrite(LED_PIN, HIGH);
    delay(250);
    digitalWrite(LED_PIN, LOW);
    delay(250);
}

працює, але не без особливостей. Internal LED тут припаяний до PD1, він же SWD, і, схоже, не можна його просто взяти і використати як GPIO.

Неактивний

#2 2026-07-24 16:08:05

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 888

Re: CH32V003 as arduino

jokeR пише:

CH32V003F4P6

Бавився з ними трохи, а також з восьминогими CH32V003J4M6. Правда, не через ардуіно фреймворк, а з ch32v003fun.
Якби їм ще зовнішній Vref зробили, взагалі ціни би їм не було. І засмутила відсутність SPI у J4M6.   

jokeR пише:

він же SWD, і, схоже, не можна його просто взяти і використати як GPIO.

Так, не можна. Мало того, якщо спробувати використати, можна залочити чіп у непрацездатний стан. І якщо F4P6 розлочити доволі просто, то щоб розлочити J4M6 без NRST піна довелось потанцювати з бубном.

jokeR пише:

Я купив wch-link, а треба wch-linkE wink

wch-linkE сам по собі на CH32V305 зроблений)

Остання редакція dimich (2026-07-24 16:17:49)

Неактивний

#3 2026-07-24 17:47:16

jokeR
Учасник
Зареєстрований: 2024-12-12
Повідомлень: 221

Re: CH32V003 as arduino

У 8 ногих дрібноконтролерів свій шарм wink Так, теж прошивається.

board = genericCH32V003J4M6

wch-linkE сам по собі на CH32V305 зроблений)

Інший контроллер, і ціна інша hmm

Неактивний

#4 2026-07-24 17:55:45

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 888

Re: CH32V003 as arduino

jokeR пише:

У 8 ногих дрібноконтролерів свій шарм wink Так, теж прошивається.

Наскільки розумію, кристал у всіх CH32V003 абсолютно однаковий, просто в різних корпусах.

Неактивний

#5 2026-07-25 09:45:53

jokeer
Гість

Re: CH32V003 as arduino

Тепер би ще придумати до чого приспособити той wch-link wink

#6 2026-07-25 17:02:26

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 888

Re: CH32V003 as arduino

jokeer пише:

Тепер би ще придумати до чого приспособити той wch-link wink

Ну як мінімум як USB-UART адаптер має працювати smile А можна заморочитись і спробувати перешити його додатково під інший протокол, зробити 1-Wire / debugWIRE адаптер, чи I²C, чи повільний напівдуплексний SPI. Дивлячить на якому МК і як він там зроблений. А AVR ISP, мабуть, без хірургічного втручання не вийде, бо 4 лінії потрібно.

Неактивний

#7 2026-07-25 19:29:54

nickjust
Учасник
Зареєстрований: 2024-06-13
Повідомлень: 59

Re: CH32V003 as arduino

ch32v003 весч.....вже більше 10 проектів зробив  ...на 8ногій ...теж купив wch-link, а потім докупляв з буквою Е
прогер можна зробити на CH32V003F4P6 та ch340   - проект на гітхабі NHC_WCH_SDI

Софт на ардуіно,прогер WCH-LINKUTILITY 2.90

Остання редакція nickjust (2026-07-25 19:33:16)

Неактивний

#8 2026-07-26 08:42:06

jokeer
Гість

Re: CH32V003 as arduino

Хттпс://github.com/NgoHungCuong/1-Wire-CH32V003 ?
Щось сложне. Няп це ліба під ch32f103

#9 2026-07-26 16:58:29

nickjust
Учасник
Зареєстрований: 2024-06-13
Повідомлень: 59

Re: CH32V003 as arduino

_https://github.com/74th/ch32v003-uart-programmer

_https://github.com/Dieu-de-l-elec/AngstromIO-devboard

Остання редакція nickjust (2026-07-26 16:59:54)

Неактивний

#10 2026-07-26 22:12:10

jokeer
Гість

Re: CH32V003 as arduino

Ну.. такоє.. якщо в мене є програматор, який по 3 проводах може залити bootloader.. і працювати як debugger.. навіщо заливати програму через uart і 4 проводи?

#11 2026-07-26 22:46:17

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 888

Re: CH32V003 as arduino

jokeer пише:

Ну.. такоє.. якщо в мене є програматор, який по 3 проводах може залити bootloader.. і працювати як debugger.. навіщо заливати програму через uart і 4 проводи?

Мені здається, сенс приведених лінків у тому, що Ardulink-pio - не єдине можливе рішення працювати з CH32V003 при відсутності WCH-LinkE.
А з Ardulink-pio прошивщик хіба не пише у віртуальний UART, який по USB пише в USB-UART адаптер, який в свою чергу пише в атмегу, яка уже по 3х проводах взаємодіє з цільовим МК? Тут від ардуіно просто зручність, що USB-UART та контролер на одній платі.
Це якщо взяти МК, який реалізує USB девайс, то можна позбутись UART'а із ланцюжка. Але тоді прошивщик має вміти взаємодіяти з vendor-specific USB девайсом.

Неактивний

#12 2026-07-27 09:27:51

jokeer
Гість

Re: CH32V003 as arduino

Follow this document to flash the USART IAP boot-loader using WCH-LinkE hardware

Няп тут про bootloader,  який переводиться в режим dfu підтяжкою одної ноги. Для 8-ногого контроллера 3 ноги віддати для програмування це по багатому wink можна, звичайно, вивернутись, вкрутити резисторів.. але wch-linke все одно потрібен.

#13 2026-07-27 14:54:55

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 888

Re: CH32V003 as arduino

jokeer пише:

Няп тут про bootloader,  який переводиться в режим dfu підтяжкою одної ноги. Для 8-ногого контроллера 3 ноги віддати для програмування це по багатому wink

Ну 2 з них - UART, як і в ардуіні. Атмегу ж теж можна хоч по ISP, хоч одним проводом по debugWIRE прошивати, але не всі хотять додаткові провода, хотять бутлоадер і аплоад з IDE. В деяких випадках так зручніше.
Колись хотів детально розібратись, які там є доступні варіанти прошивки окрім SWIO, але руки не дійшли. З WCH-LinkE запрацювало, цього було достатньо. Але надибав такий опис: WCH CH32V003 Factory Bootloader - The Missing Manual.

Неактивний

#14 2026-07-27 15:53:01

jokeer
Гість

Re: CH32V003 as arduino

Ну коли замість програматора за 300 грн UART за 50 - в принципі непогано..

#15 2026-07-28 16:19:43

jokeR
Учасник
Зареєстрований: 2024-12-12
Повідомлень: 221

Re: CH32V003 as arduino

хттпс://github.com/aappleby/picorvd
Надибав таке. Виглядає непогано, і rp2040 в хазяйстві є wink
Але не працює sad
blink наче заливає, але рівень на пінах не міняється.
При спробі debug - відтворюється хттпс://github.com/aappleby/picorvd/issues/8
Що хотів сказати автор issue.. Не та версія компілятора? gdb? А яка потрібна? ..
Жаль що до кінця ту штуку не доробили sad

Неактивний

#16 2026-07-28 20:06:13

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 888

Re: CH32V003 as arduino

jokeR пише:

blink наче заливає, але рівень на пінах не міняється.

На пінах цільового CH32? А якщо той же бінарик зашити заздалегідь робочим програматором?
Впевніться, що дивитесь на тому ж піні, яким цей blink дригає. На різних платах LED на різних пінах може бути, це ж не ардуіно. 

jokeR пише:

Що хотів сказати автор issue.. Не та версія компілятора? gdb? А яка потрібна?

А х.з., у нього треба питати. Мабуть тулчейн мається на увазі, бо в xpack і компілятор, і gdb.
Теоретично, на момент написання того комента уже був gdb 13-ї версії, а може й 14-ї. А platformio досі ставить 12.1.

jokeR пише:

Жаль що до кінця ту штуку не доробили sad

Я б не покладав сподівань на проект, в якому приклад blink лінкується з libgcc.a, що лежить в цьому ж репозиторії.

Неактивний

#17 Вчора 10:03:43

jokeR
Учасник
Зареєстрований: 2024-12-12
Повідомлень: 221

Re: CH32V003 as arduino

gdb-multiarch -x gdbinit -ex 'load' -ex 'detach' -ex 'quit' bin/blink.elf

Трохи дивує що заливається не .bin, а .elf. Десь під капотом повинна бути магія objcopy?

А якщо той же бінарик зашити заздалегідь робочим програматором?

Зашивається, працює

Через ardulink, зроблений з arduino, і пише і читає. Ок wink

Ага, трохи роз"ясняється. picorvd - заливає прошивку правильно, але в кінці не робить reset. ardulink, походу, робить reset через живлення wink Якщо ребутнути через power - blink запускається. Але з debug - облом sad

GNU gdb (xPack GNU RISC-V Embedded GCC x86_64) 12.1
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=x86_64-pc-linux-gnu --target=riscv-wch-elf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from bin/blink.elf...
0x000001e4 in busywait (x=600000) at blink.cpp:4
4	   for (volatile int i = 0; i < x; i++) {
(gdb) break 10
Breakpoint 1 at 0x212: file blink.cpp, line 10.
Note: automatically using hardware breakpoints for read-only addresses.
(gdb) break 11
Breakpoint 2 at 0x214: file blink.cpp, line 13.
(gdb) c
Continuing.

Program received signal SIGTRAP, Trace/breakpoint trap.
0x000001e4 in busywait (x=<error reading variable: Cannot access memory at address 0xfffffff4>) at blink.cpp:4
4	   for (volatile int i = 0; i < x; i++) {
(gdb) 

Щось там недороблено sad

Остання редакція jokeR (Вчора 13:46:52)

Неактивний

#18 Вчора 17:28:47

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 888

Re: CH32V003 as arduino

jokeR пише:

Трохи дивує що заливається не .bin, а .elf.

Gdb бере elf на вхід. З нього ж таблицю символів читає для дебага, і дебажні символи, якщо є, і цільову архітектуру для multiarch.
Сирий бінарик прошити можна командою restore.

jokeR пише:

Десь під капотом повинна бути магія objcopy?

Та яка там магія. Заголовок, секції з атрибутами, таблиця символів. Avrdude ж теж elf шʼє.

jokeR пише:

Ага, трохи роз"ясняється. picorvd - заливає прошивку правильно, але в кінці не робить reset.

А "monitor reset" працює?

jokeR пише:

ardulink, походу, робить reset через живлення wink

WCH-LinkE теж вміє живленням смикати. Корисно коли нема NRST.

jokeR пише:

Note: automatically using hardware breakpoints for read-only addresses.

Дивно, в README picorvd пишуть же:

The CH32V003 chip does not support any hardware breakpoints.

jokeR пише:

0x000001e4 in busywait (x=<error reading variable: Cannot access memory at address 0xfffffff4>) at blink.cpp:4

Скоріш за все той аргумент x зник ще на етапі компіляції. Але чому gdb в неіснуючу памʼять лізе, замість того щоб сказати value optimized out - то вже х.з. 
Взагалі, щоб більш-менш адекватний рантайм дебаг отримати, потрібно збирати з -Og, або хоча б -fno-omit-frame-pointer.
UPD: А, бачу, воно вже з -O0 компілиться. Але ж агрумент все одно через регістр передається: https://godbolt.org/z/o5YYEjYEK

Остання редакція dimich (Вчора 17:45:10)

Неактивний

#19 Вчора 17:51:41

jokeR
Учасник
Зареєстрований: 2024-12-12
Повідомлень: 221

Re: CH32V003 as arduino

А "monitor reset" працює?

ніт, "monitor" command not supported by this target.

потрібно збирати з -Og,

$CC -g -O0 -ffunction-sections -static-libgcc -lgcc -march=rv32ec_zicsr -mabi=ilp32e -I/usr/include/newlib -nostdlib -I. -Wall -c ch32v003fun.c -o obj/ch32v003fun.o

щось недороблене sad

Неактивний

#20 Вчора 18:12:29

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 888

Re: CH32V003 as arduino

jokeR пише:

ніт, "monitor" command not supported by this target.

А ви gdb з монітором зʼєднали?

After that run "gdb-multiarch {your_binary.elf}" and type "target extended-remote /dev/ttyACM0" to connect to the debugger (replace ttyACM0 with whatever port your Pico shows up as).

jokeR пише:

$CC -g -O0

Так, уже побачив, відредагував.

Неактивний

#21 Вчора 20:07:42

jokeR
Учасник
Зареєстрований: 2024-12-12
Повідомлень: 221

Re: CH32V003 as arduino

А ви gdb з монітором зʼєднали?

Складно wink
У нас є gdb-multiarch, є ttyACM0, є магічний пристій, що слухає ttyACM0 і смикає CH32V003 за SDIO.

Неактивний

#22 Вчора 20:18:51

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 888

Re: CH32V003 as arduino

jokeR пише:

У нас є gdb-multiarch, є ttyACM0

Ну gdb-multiarch має ж якось взнати, що є ttyACM0, на якому його будуть слухати.

jokeR пише:

є магічний пристій, що слухає ttyACM0 і смикає CH32V003 за SDIO.

Магічний пристрій і є монітор, який реалізує протокол gdb-сервера. В "класичній" конфігурації цю роль виконує openocd, який в свою чергу вже спілкується з залізом по іншом протоколу, наприклад, по JTAG.

Неактивний

#23 Вчора 20:54:35

jokeR
Учасник
Зареєстрований: 2024-12-12
Повідомлень: 221

Re: CH32V003 as arduino

Ну gdb-multiarch має ж якось взнати, що є ttyACM0, на якому його будуть слухати.

Через файл gdbinit wink

Магічний пристрій і є монітор, який реалізує протокол gdb-сервера.

Походу його не навчили цьому sad

Ну reset то таке.. можна і руками.. а що debug не працює - незручно sad

Неактивний

#24 Вчора 21:46:47

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 888

Re: CH32V003 as arduino

jokeR пише:

Через файл gdbinit wink

А, ну якщо там є target remote / extended-remote, і gdb запускаєте з '-x gdbinit', то має зʼєднуватись.
Не знаю, чи лежить він там у вас як ~/.config/gdb/gdbinit і ваш gdb-multiarch автоматично виконує його при старті, чи потрібно в командному рядку кожний раз передавати.

jokeR пише:

Походу його не навчили цьому sad

Код для ресету там є: src/RVDebug.cpp:95. А

"monitor" command not supported by this target.

- це про команду "monitor", яка не supported, поки target не визначений. Тому логічно припустити, що gdb просто нікуди не підключений в цей момент.

jokeR пише:

а що debug не працює - незручно sad

По факту він-то працює. На брекпоінті зупинився ж якось. Регістри та машинний код показує? Ну а змусити значення змінних показувати, коли вони у регістрах - це навіть на рідній хостовій системі не завжди вдається.

Неактивний

#25 Сьогодні 21:54:37

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 888

Re: CH32V003 as arduino

Вирішив теж спробувати цей picorvd. Довелось обробити напильником, щоб зібрати під сучасним Arch.

По-перше, в pico_sdk_import.cmake замінив PicoSDK на 2.3.0, бо з 1.5.1 виникала помилка через версію cmake. Ще і з нею розбиратись не хотілось, тому просто бампнув тег на останній, там версію cmake уже пофіксили.

По-друге, в example/build замінив префікс тулчейна на riscv64-elf-, та шлях до хедерів newlib на /usr/risc64-elf/include, де воно в мене і лежить.

Також поправив blink.cpp, щоби блимало PC4, а не PD0 та PD4. Бо LED у мене на PC4, а на PD4 SWIO.
Прошилось і навіть щось запрацювало.

dimich пише:

А, бачу, воно вже з -O0 компілиться. Але ж агрумент все одно через регістр передається: https://godbolt.org/z/o5YYEjYEK

Тут трохи не додивився: аргумент-то передається в регістрі, але в самій функції потім кладеться в стек.
При blink зібраному з "-ggdb -Og" навіть значення аргумента показує правильно.

$ riscv32-elf-gdb ./bin/blink.elf 
Reading symbols from ./bin/blink.elf...
(gdb) target extended-remote /dev/ttyACM0
Remote debugging using /dev/ttyACM0
0x0000019e in busywait (x=x@entry=300000) at blink.cpp:8
8          for (volatile int i = 0; i < x; i++) {
(gdb) p x
$1 = 300000
(gdb) info frame
Stack level 0, frame at 0x200007f0:
 pc = 0xd28 in busywait (blink.cpp:8); saved pc = 0xdb4
 called by frame at 0x200007fc
 source language c++.
 Arglist at 0x200007f0, args: x=x@entry=300000
 Locals at 0x200007f0, Previous frame's sp is 0x200007f0
(gdb) bt
#0  0x00000d28 in busywait (x=x@entry=300000) at blink.cpp:8
#1  0x00000db4 in main () at blink.cpp:35

При зупинці по брекпоінту перестає, "Breakpoint 1, busywait (x=<error reading variable: Cannot access memory at address 0xfffffff0>) at blink.cpp:8"
А от якщо при збірці blink прибрати garbage collection секцій (при цьому розмір blink зростає майже до 4 кб), то початкове вхідне значення показує правильно, а поточне відповідає значенню регістра, в якому передавався аргумент:

(gdb) break 8
Breakpoint 1 at 0xd24: file blink.cpp, line 8.
Note: automatically using hardware breakpoints for read-only addresses.
(gdb) continue 
Continuing.

Breakpoint 1, busywait (x=32800, x@entry=300000) at blink.cpp:8
8          for (volatile int i = 0; i < x; i++) {
(gdb) info registers
ra             0xda4    0xda4 <main()+108>
sp             0x200007f0       0x200007f0
gp             0x20000800       0x20000800
tp             0x804e06a4       0x804e06a4
t0             0x1a0    416
t1             0x40014281       1073824385
t2             0x5b763111       1534472465
fp             0x0      0x0 <InterruptVectorDefault>
s1             0x40011000       1073811456
a0             0x8020   32800
a1             0x4002200c       1073881100
a2             0x8000d40        134221120
a3             0x50000  327680
a4             0x10040  65600
a5             0x90000  589824
pc             0xd2e    0xd2e <busywait(int)+12>

"monitor reset" працює, покрокове виконання працює.

Неактивний

Швидке повідомлення

Введіть повідомлення і натисніть Надіслати

Підвал форуму