Ви не увійшли.
Хм, цікаві досліди
спробую відтворити.
Там ще є логування в uart, відключене через #if 0
Треба подивитись, може там є щось цікаве.
Вирішив теж спробувати цей 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.
Прошилось і навіть щось запрацювало.
А, бачу, воно вже з -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" працює, покрокове виконання працює.
Через файл gdbinit
А, ну якщо там є target remote / extended-remote, і gdb запускаєте з '-x gdbinit', то має зʼєднуватись.
Не знаю, чи лежить він там у вас як ~/.config/gdb/gdbinit і ваш gdb-multiarch автоматично виконує його при старті, чи потрібно в командному рядку кожний раз передавати.
Походу його не навчили цьому
Код для ресету там є: src/RVDebug.cpp:95. А
"monitor" command not supported by this target.
- це про команду "monitor", яка не supported, поки target не визначений. Тому логічно припустити, що gdb просто нікуди не підключений в цей момент.
а що debug не працює - незручно
По факту він-то працює. На брекпоінті зупинився ж якось. Регістри та машинний код показує? Ну а змусити значення змінних показувати, коли вони у регістрах - це навіть на рідній хостовій системі не завжди вдається.
Ну gdb-multiarch має ж якось взнати, що є ttyACM0, на якому його будуть слухати.
Через файл gdbinit ![]()
Магічний пристрій і є монітор, який реалізує протокол gdb-сервера.
Походу його не навчили цьому ![]()
Ну reset то таке.. можна і руками.. а що debug не працює - незручно ![]()
У нас є gdb-multiarch, є ttyACM0
Ну gdb-multiarch має ж якось взнати, що є ttyACM0, на якому його будуть слухати.
є магічний пристій, що слухає ttyACM0 і смикає CH32V003 за SDIO.
Магічний пристрій і є монітор, який реалізує протокол gdb-сервера. В "класичній" конфігурації цю роль виконує openocd, який в свою чергу вже спілкується з залізом по іншом протоколу, наприклад, по JTAG.
А ви gdb з монітором зʼєднали?
Складно ![]()
У нас є gdb-multiarch, є ttyACM0, є магічний пристій, що слухає ttyACM0 і смикає CH32V003 за SDIO.
ніт, "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).
$CC -g -O0
Так, уже побачив, відредагував.
А "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щось недороблене ![]()
Трохи дивує що заливається не .bin, а .elf.
Gdb бере elf на вхід. З нього ж таблицю символів читає для дебага, і дебажні символи, якщо є, і цільову архітектуру для multiarch.
Сирий бінарик прошити можна командою restore.
Десь під капотом повинна бути магія objcopy?
Та яка там магія. Заголовок, секції з атрибутами, таблиця символів. Avrdude ж теж elf шʼє.
Ага, трохи роз"ясняється. picorvd - заливає прошивку правильно, але в кінці не робить reset.
А "monitor reset" працює?
ardulink, походу, робить reset через живлення
WCH-LinkE теж вміє живленням смикати. Корисно коли нема NRST.
Note: automatically using hardware breakpoints for read-only addresses.
Дивно, в README picorvd пишуть же:
The CH32V003 chip does not support any hardware breakpoints.
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
gdb-multiarch -x gdbinit -ex 'load' -ex 'detach' -ex 'quit' bin/blink.elfТрохи дивує що заливається не .bin, а .elf. Десь під капотом повинна бути магія objcopy?
А якщо той же бінарик зашити заздалегідь робочим програматором?
Зашивається, працює
Через ardulink, зроблений з arduino, і пише і читає. Ок ![]()
Ага, трохи роз"ясняється. picorvd - заливає прошивку правильно, але в кінці не робить reset. ardulink, походу, робить reset через живлення
Якщо ребутнути через power - blink запускається. Але з debug - облом ![]()
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) Щось там недороблено ![]()
blink наче заливає, але рівень на пінах не міняється.
На пінах цільового CH32? А якщо той же бінарик зашити заздалегідь робочим програматором?
Впевніться, що дивитесь на тому ж піні, яким цей blink дригає. На різних платах LED на різних пінах може бути, це ж не ардуіно.
Що хотів сказати автор issue.. Не та версія компілятора? gdb? А яка потрібна?
А х.з., у нього треба питати. Мабуть тулчейн мається на увазі, бо в xpack і компілятор, і gdb.
Теоретично, на момент написання того комента уже був gdb 13-ї версії, а може й 14-ї. А platformio досі ставить 12.1.
Жаль що до кінця ту штуку не доробили
Я б не покладав сподівань на проект, в якому приклад blink лінкується з libgcc.a, що лежить в цьому ж репозиторії.
хттпс://github.com/aappleby/picorvd
Надибав таке. Виглядає непогано, і rp2040 в хазяйстві є ![]()
Але не працює ![]()
blink наче заливає, але рівень на пінах не міняється.
При спробі debug - відтворюється хттпс://github.com/aappleby/picorvd/issues/8
Що хотів сказати автор issue.. Не та версія компілятора? gdb? А яка потрібна? ..
Жаль що до кінця ту штуку не доробили ![]()
Ну коли замість програматора за 300 грн UART за 50 - в принципі непогано..
Няп тут про bootloader, який переводиться в режим dfu підтяжкою одної ноги. Для 8-ногого контроллера 3 ноги віддати для програмування це по багатому
Ну 2 з них - UART, як і в ардуіні. Атмегу ж теж можна хоч по ISP, хоч одним проводом по debugWIRE прошивати, але не всі хотять додаткові провода, хотять бутлоадер і аплоад з IDE. В деяких випадках так зручніше.
Колись хотів детально розібратись, які там є доступні варіанти прошивки окрім SWIO, але руки не дійшли. З WCH-LinkE запрацювало, цього було достатньо. Але надибав такий опис: WCH CH32V003 Factory Bootloader - The Missing Manual.
Follow this document to flash the USART IAP boot-loader using WCH-LinkE hardware
Няп тут про bootloader, який переводиться в режим dfu підтяжкою одної ноги. Для 8-ногого контроллера 3 ноги віддати для програмування це по багатому
можна, звичайно, вивернутись, вкрутити резисторів.. але wch-linke все одно потрібен.