Como subir y depurar tu codigo en una placa basada en RP2040 sin USB (Ubuntu)
![](/img/debug_OpenOCD/OpenOCD_Debugging.jpg)
Parte deste post foi escrito ca axuda dunha IA
Levo un tempo traballando nun robot micromouse baseado no micro RP2040 de raspberry, e queria axudar a quen coma min non ten moita idea de subir e depurar codigo sen usar o USB, eu voume axudar do debugger da mesma compañía o Raspberry Pi Debug Probe, pero se pode facer cunha placa Raspberry Pi pico ou calquera outra basada en RP2040 que teña un USB.
É importante deixar claros uns conceptos basicos do que imos facer, queremos poder:
-
Subir codigo: significa cargar o transferir o programa desenvolvido previamente á memoria do microcontrolador para que poida ser executado e controlar as súas funcións segundo as especificacións programadas.
-
Depurar o codigo: poder ler e escribir na memoria do microcontrolador, observar e modificar os rexistros internos, poñer breakpoints, realizar seguimento paso a paso e monitorizar o fluxo do programa durante a execución.
Hai deixar claro que este micro so se pode depurar mediante a interfaz de depuracion SWD e non se pode depurar co USB ou polo menos non se pode dunha maneira “chula” xa que abrir un porto serie e encher o codigo de prints está feo e me pon moi triste :(
O que necesitamos é:
- Raspberry Pi Debug Probe
- Placa basada no RP2040 co porto SWD accesible, unha Raspberry Pi Pico por exemplo.
- Cable, bateria ou que sexa que alimente a nosa placa por que o Debug Probe non alimenta a placa
Pre-requisitos:
Instalar as duas ferramentas software OpenOCD e gdb-multiarch.
OpenOCD
$ sudo apt install openocd
$ sudo apt install automake autoconf build-essential texinfo libtool libftdi-dev libusb-1.0-0-dev
Eu tiven que instalar esta ferramenta a maiores (non o pon na guia de raspi) :
$ sudo apt install pkg-config
Clonamos o repositorio de openocd para o micro RP2040
$ git clone https://github.com/raspberrypi/openocd.git --branch rp2040-v0.12.0 --depth=1 –no-single-branch
$ cd openocd
$ ./bootstrap
$ ./configure
$ make -j4
$ sudo make install
gdb-multiarch
Instalamos o paquete e listo
$ sudo apt install gdb-multiarch
Conectarnos co debugger
Para conectarnos ao nucleo do micro e poder subir codigo debemos conectar os cables da interfaz SWD do debuger á nosa placa e (SWD, SWCLK e GND), conectar o cable USB ao noso PC, darlle alimentacion á placa,no meu caso a traves dunha bateria e por ultimo executar o seguinte comando na terminal
$ sudo openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c "adapter speed 5000"
Deberiamos obter unha saida coma está, onde se ve que queda á escoita dunha conexion polo porto 3333 do noso pc.
Info : starting gdb server for rp2040.core0 on 3333
Info : Listening on port 3333 for gdb connections
Agora debemos deixar esta terminal e abrir outra, nesta nova terminal vamos ata onde teñamos o binario que queiramos subir.
user@userPC:~/Project/pico/pico-examples/build/blink$ ls -l
blink.bin
blink.dis
blink.elf
blink.elf.map
blink.hex
blink.uf2
CMakeFiles
cmake_install.cmake
elf2uf2
Makefile
user@userPC:~/Project/pico/pico-examples/build/blink$ gdb-multiarch
No meu caso na carpeta teño unha chea de archivos producto da compilacion ca ferramenta cmake
NOTA: É importante que se facedes coma min á hora de compilar co cmake lle poñades o flag de depuracion senon vai ser imposible recorrer liña por liña co debuger e poñer breakpoints
$ cmake -DCMAKE_BUILD_TYPE=Debug .. $ make -j4
Na carpeta executamos a ferramenta de de depuracion dbg-multiarch e lle pasamos o bianario en cuestion.
$ gdb-multiarch blink.elf
Nos mostrará algo asi
user@userPC:~/Project/pico/pico-examples/build/blink$ gdb-multiarch blink.elf
GNU gdb (Ubuntu 12.1-0ubuntu1~22.04) 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 "x86_64-linux-gnu".
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 blink.elf...
(gdb)
como vemos apareceu un pront no que podemos enviarlle instruccions ao debuger gdb, o primeiro que imos facer e conectarnos á nosa placa
(gdb) target remote localhost:3333
para comprobar que estamos conectados temos que ir a anterior terminal onde executaramos o openocd e ver se aparece unha mensaxe tal que asi
Info : dropped 'gdb' connection
Info : accepting 'gdb' connection on tcp/3333
Info : New GDB Connection: 1, Target rp2040.core0, state: halted
Subir e correr o codigo
Se todo vai ben volvemos a nosa consola gdb e xa podemos subir o codigo co comando load
(gdb) load
Loading section .boot2, size 0x100 lma 0x10000000
Loading section .text, size 0x1eb0 lma 0x10000100
Loading section .rodata, size 0xf4 lma 0x10001fb0
Loading section .binary_info, size 0x20 lma 0x100020a4
Loading section .data, size 0x18c lma 0x100020c4
Start address 0x100001e8, load size 8784
Transfer rate: 11 KB/sec, 1756 bytes/write.
(gdb) _
agora que temos o codigo no micro imos executalo dun xeito ordenado, o primeiro que facemos é resetear todo e ir ao principio do progrma co comando “monitor reset init” e despois arrancamos co comando “continue” ainda que tamen é valido “c”
(gdb) monitor reset init
(gdb) c
Continuando.
Agora xa sabemos subir o codigo, reiniciar o programa e paralo cando queiramos, a partir de aqui podemos empezar a facer moitas outras cousas, poñer breakpoints, mostrar e modificar o valor das variables, avanzar liña a liña ou vovler a un lugar en particular pero non é o obxetivo deste post, se queredes saber mais tedes a vosa disposicion a documentación de gdb ainda así vos deixo un par de comandos que utilizo con moita frecuencia.
(gdb) // Ctrl+C para parar a execución
(gdb) br main.cpp:12 //poñer un breakpoint no archivo main.cpp na liña 12.
(gdb) del br //elimina todos os breakpoints.
(gdb) p num_manzanas //ver o valor da variable num_manzanas.
(gdb) set num_manzanas=12 //asignar o valor 12 á variable num_manzanas.
Vos animo a tod@s a coñecer esta ferramenta de depuración que ainda que é moi engorrosa penso que é de moita axuda para saber como funciona a depuracion nos IDEs actuais.
Unha aperta :D