Kamuycikap - SentenceDataBase

日々の勉強の記録を気分で書き綴るブログ

RaspberryPi Picoをデバッガ(PicoProbe)で開発

Raspberry pi Picoをデバッガで開発する

500円という破格の金額で販売されているRaspberryPi Pico。
Raspberry Piと冠がついていますが、これマイコン(すでに死語?)です。

CPUには独自開発の「RP2040」が採用されており、開発メインマシンはRaspberry Pi 4が推奨されています。
Pi4に接続して開発する手法が多々紹介されているのですが、公式ドキュメントを読むと、Pi4以外の他OSのPC(WindowsLinuxMAC)からでもデバッグ開発できるようにできる仕組みが記載されています。

すでにWindows10でPicoをデバッグ開発する方法は多々公開されておりますので、この記事ではLinuxで環境を整える手法を公開します。

環境

OS:Linux(Ubuntu20、MXLinux19、Debian Buster)以上のバージョンであれば動く。。。と思う。
※当然ですが、Raspberry Pi OSでも問題なく動きました。Pi3でも快適に開発できています。

開発環境構築

結論から書きますと、インストール用のシェルスクリプトをダウンロードして実行するだけで終わっちゃいます。。。
公式ドキュメントには、チャプター分けて詳しく書かれていますが、ぶっちゃけChapter1のQuick Setup Picoだけでほぼ全部終わっちゃいます。

インストールスクリプトダウンロード

公式ドキュメントにあるコマンドでいけます。
HOMEディレクトリで実行です。

$ cd ~/
$ wget https://raw.githubusercontent.com/raspberrypi/pico-setup/master/pico_setup.sh
インストールスクリプトを実行

pico_setup.shというファイルが、HOMEディレクトリにあるはずです。
pico_setup.shを実行属性にしたのち、実行します。

$ chmod 755 ./pico_setup.sh
$ ./pico_setup.sh

すると、アレヤコレヤと処理が進み、HOMEディレクトリに「pico」ディレクトリができているはずです。
treeコマンドで確認してみたら、下記の構成になっていました。

pi@KinStation01:~ $ tree -d -L 1 ./pico
./pico
├── openocd
├── pico-examples
├── pico-extras
├── pico-playground
├── pico-sdk
├── picoprobe
└── picotool
一応コンパイルコマンド叩いてみる

実のところ、インストールスクリプトの処理の中でコンパイルもやっちゃってるので、あえてここでやる必要はないんですが、、、まぁ、コマンド検証ってことで。

まずは、サンプルディレクトリに入ります。

$ cd ./pico/pico-examples

本家ドキュメントのChapter3がLチカプログラムのコンパイルテストになってるんですが、pico_setup.shを動かしたことで、すでにできてしまっています。
pico_setup.shを動かさずに個別にサンプルをコンパイルする場合を想定して。。。。
本当は自分でbuildディレクトリを作成するのですが、前述の通りすでにできているので気にせずに入ります。

$ cd ./build

んで、コンパイルコマンドを実行します。
※本家ドキュメントでは、環境変数の設定が指示されていますが、、、なんとpico_setup.shはそれもやってくれていますw

$ cmake ..
$ make -j4

すると、pico-examplesディレクトリにある全てのフォルダに対してコンパイルがかけられ、これまた全てのコンパイル結果がbuildディレクトリ下に作られます。
特定のディレクトリだけコンパイルする方法はまた次の機会に。
※$ make -j4 の「-j4」は、Pi4使ってるなら必須。
  → 「Invoking make with -j4 will run four make jobs in parallel to speed it up. A Raspberry Pi 4 has 4 cores so -j4 is a
reasonable number.」
    「-j4を指定してmakeを呼び出すと、4つのmakeジョブが並行して実行され、速度が向上します。 Raspberry Pi 4には4つのコアがあるため、-j4は妥当な数。」

PicoProbe作成

無事にコンパイルができる事実を確認できましたので、手っ取り早くデバッガを仕立てます。
デバッガと書いていますが、なんのことはありません。
その正体はRaspberry Pi Picoです。

このように書くと混乱しそうですが、開発対象とは別にもう一枚Raspberry Pi Picoの基板を用意し、それをデバッガとして仕立てると言うことです。

Picoの開発を行うためにPicoを使うというのも面白いです。

Raspberry Pi PicoのBOOTボタンを押したまま、USBケーブルでパソコンと接続
USBメモリを接続したかのような画面がパソコン上に表示されるはずです。
そこに、./pico/picoprobe/build/にあるpicoprobe.uf2をドラッグ&ドロップします。

これだけで、そのPicoはPicoProbeと言う名のデバッガになりましたw

一般ユーザーでPicoProbeを使えるように設定

前項で作ったデバッガ「PicoProbe」を一般ユーザーで利用するために一工夫必要です。
何も考えず、所定のディレクトリに所定のファイルを作成して有効化します。

$ sudo nano /etc/udev/rules.d/99-picoprobe.rules

上記コマンドではnanoを利用していますが、エディタは何でも良いです。
下記の内容でファイル保存できればよいので。

# Raspberry Pi Pico probe
ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="0004", MODE="0666"

保存できたら、書いた設定を有効化します。

sudo udevadm trigger

PicoProbeでプログラム書き込み/デバッグ

ここまでで、デバッガ「PicoProbe」を使ってプログラムの書き込みとデバッグ実行ができる状態になっているはず。
早速トライ。

ハードウェアの接続

デバッグ対象となるPicoとPicoProbeを接続します。
ブレッドボードとジャンパー線でオッケー。

f:id:kamuycikap:20211104123718p:plain
Raspberry Pi Pico PicoProbe接続図
f:id:kamuycikap:20211104123511p:plain
Raspberry Pi Pico Pin配列

上図の通りに接続できたら、PCと上図左側のPico(PicoProbe)をUSBケーブルで接続します。
PicoProbe側のPicoのLEDが点灯するはずです。

openOCDの起動

まず、デバッグするためにLinux(GDB)とPicoの橋渡しをしてくれるプログラムを起動します。

$ cd ~/pico
$ cd ./openocd
$ src/openocd -f interface/picoprobe.cfg -f target/rp2040.cfg -s tcl

すると、配線間違いなどなければ、下記のように表示されるはず。

$ src/openocd -f interface/picoprobe.cfg -f target/rp2040.cfg -s tcl
Open On-Chip Debugger 0.10.0+dev-geb22ace-dirty (2021-02-28-13:17)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'swd'
Warn : Transport "swd" was already selected
adapter speed: 5000 kHz

Info : Hardware thread awareness created
Info : Hardware thread awareness created
Info : RP2040 Flash Bank Command
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : clock speed 5000 kHz
Info : SWD DPIDR 0x0bc12477
Info : SWD DLPIDR 0x00000001
Info : SWD DPIDR 0x0bc12477
Info : SWD DLPIDR 0x10000001
Info : rp2040.core0: hardware has 4 breakpoints, 2 watchpoints
Info : rp2040.core1: hardware has 4 breakpoints, 2 watchpoints
Info : starting gdb server for rp2040.core0 on 3333
Info : Listening on port 3333 for gdb connections
GDB起動→プログラム書き込み→実行

前項のターミナルはそのままに、新たにターミナルを開いてGDBを実行。
サンプルとしてLチカプログラムを書き込んでみます。

$ cd ~/pico/pico-examples/build/blink
$ gdb-multiarch blink.elf
GNU gdb (Raspbian 8.2.1-2) 8.2.1
Copyright (C) 2018 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 "arm-linux-gnueabihf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://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...done.
(gdb) 

ここまでで、プログラムの書き込み準備ができた状態。
書き込むため、まずはGDBからopenocdに接続

(gdb) target remote localhost:3333
Remote debugging using localhost:3333
0x100020fd in ?? ()
(gdb)

無事に接続できたようなので書き込み!

(gdb) load
Loading section .boot2, size 0x100 lma 0x10000000
Loading section .text, size 0x4040 lma 0x10000100
Loading section .rodata, size 0xde4 lma 0x10004140
Loading section .binary_info, size 0x20 lma 0x10004f24
Loading section .data, size 0x24c lma 0x10004f44
Start address 0x100001e8, load size 20880
Transfer rate: 9 KB/sec, 3480 bytes/write.
(gdb)

書き込み完了!
リセットして、

(gdb) monitor reset init
target halted due to debug-request, current mode: Thread 
xPSR: 0xf1000000 pc: 0x000000ee msp: 0x20041f00
target halted due to debug-request, current mode: Thread 
xPSR: 0xf1000000 pc: 0x000000ee msp: 0x20041f00
(gdb)

実行!

(gdb) continue
Continuing.

Target側のPicoに実装されているLEDがチカチカ点滅したら成功です。

ステップ実行とかしてみる

ここまでで実行できたので、Breakポイントはったりステップ実行したりしてみます。

まずは、動いている状態からCtrl+cで強制終了。

(gdb) continue
Continuing.
^Ctarget halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x00000178 msp: 0x20041f00

Thread 1 received signal SIGINT, Interrupt.
time_reached (t=...)
    at /home/pi/pico/pico-sdk/src/rp2_common/hardware_timer/include/hardware/timer.h:116
116	    uint32_t hi_target = (uint32_t)(target >> 32u);
(gdb) 

んで、もう一度リセットして仕切り直し。

(gdb) moniter reset init
Undefined command: "moniter".  Try "help".
(gdb) monitor reset init
target halted due to debug-request, current mode: Thread 
xPSR: 0xf1000000 pc: 0x000000ee msp: 0x20041f00
target halted due to debug-request, current mode: Thread 
xPSR: 0xf1000000 pc: 0x000000ee msp: 0x20041f00
(gdb)

main()にBreakポイントを貼ります

(gdb) b main
Breakpoint 1 at 0x1000035c: file /home/pi/pico/pico-examples/blink/blink.c, line 9.
(gdb) 

実行してmain()で停止。

(gdb) continue
Continuing.
Note: automatically using hardware breakpoints for read-only addresses.
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x00000178 msp: 0x20041f00

Thread 1 hit Breakpoint 1, main ()
    at /home/pi/pico/pico-examples/blink/blink.c:9
9	int main() {
(gdb) 

nextコマンドでステップ実行してみる。

Thread 1 hit Breakpoint 1, main ()
    at /home/pi/pico/pico-examples/blink/blink.c:9
9	int main() {
(gdb) next
14	    gpio_init(LED_PIN);
(gdb) next
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x00000178 msp: 0x20041f00
15	    gpio_set_dir(LED_PIN, GPIO_OUT);
(gdb) next
17	        gpio_put(LED_PIN, 1);
(gdb) next
18	        sleep_ms(250);
(gdb) next
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x00000178 msp: 0x20041f00
19	        gpio_put(LED_PIN, 0);
(gdb) 

LEDが点灯するところまで実行。
きちんとステップ実行できている。
すばらし!!

終わり方

detachコマンド実行してから、quitコマンド。

(gdb) detach
Detaching from program: /home/pi/pico/pico-examples/build/blink/blink.elf, Remote target
Ending remote debugging.
[Inferior 1 (Remote target) detached]
(gdb) quit

補足

初期化ファイルを作ってGDB起動時にloadまでやっちゃう

初期化ファイルを作成

ファイル名:pico.gdbinit

target remote :3333
mon reset init
load

GDB起動時のコマンド

$ gdb-multiarch -x pico.gdbinit blink.elf