あれ、このPico何書き込んであったかな?老人の忘却力とて、先週書き込んだプログラムが何だったのか思い出せない、ということは不可避なんであります。しかし流石Raspberry Pi、素晴らしいツールが用意されていました。picotool。ラズパイPicoのFlashの中のオブジェクトの情報を取り出せるツールです。
※「鳥なき里のマイコン屋」投稿順Indexはこちら
まずは picotoolのGitHubページへのリンクを貼り付けておきます。
なお、ラズパイPicoの開発用母艦としてラズパイ4(Raspberry Pi OS)を使用しております。以下のpicotoolの動作はLinux上でのものです。多分、Windows上でも似たような感じで動かせるのではないかと。動かしてないけど。。。
picotoolは、ラズパイPico用のRaspberry Pi Pico C/C++ SDK上で生成されたバイナリオブジェクトから情報を取り出すためのツールと言って良いかと思います。オブジェクトファイルから情報を取得できるだけでなく、実機のFlashメモリからも情報を取得できます。また、Flashメモリを読み出してオブジェクトファイルとしてセーブしたり、ファイルをFlashに書き込むこともできます。
Linux上のbinutilでもオブジェクトファイルから各種情報を取り出すことができますが、この picotool は一味違います。binutilと異なるのは ラズパイPico 特有の各種情報を「埋め込んでおける」点にあります。1例はこんな感じ。stdioがUSBに向いているとか、ピンが何に使われているとかまで分かります。
$ picotool info -a freqTST0.uf2 File freqTST0.uf2: Program Information name: freqTST0 version: 0.1 features: USB stdin / stdout binary start: 0x10000000 binary end: 0x100084d8 Fixed Pin Information 2: PWM OUTPUT A 3: PWM OUTPUT B 20: EXT CLOCK IN 21: EXT CLOCK OUT 25: On-board LED Build Information sdk version: 1.1.2 pico_board: pico boot2_name: boot2_w25q080 build date: Aug 9 2021 build attributes: Debug
上記はファイルに対しての処理ですが、同じことを実機のFlashメモリ内に既に書き込まれているオブジェクトに対しても行うことができます。このpicotoolを使うにあたっては一つ条件があります。BOOTSELモードでの接続です。
BOOTSELモードでラズパイPicoを母艦に接続
picotoolを走らせる母艦がRaspberry Pi 4でもパソコンでも、ラズパイPicoをBOOTSELボタンを押しながらUSB接続すればBOOTSELモードに入ります。BOOTSELモードで接続するとホストからはドライブとして認識されます。Raspberry Pi 4上では以下のような感じに見えます。
このドライブに uf2形式のオブジェクトファイルを書き込めばFlashに書き込めますが、今回はpicotoolなのでこのドライブの存在は忘れて、コマンドラインから picotool を使います。基本情報だけの取り出しなら以下のような感じ。
$ sudo picotool info Program Information name: freqTST0 version: 0.1 features: USB stdin / stdout
ラズパイPicoの実機にアクセスする場合、Linux上では sudo 必須と思います。なお、BOOTSELモードのラズパイPicoの実機が接続されていない状態で上記コマンドを実行すると、
$ sudo picotool info No accessible RP2040 devices in BOOTSEL mode were found.
という感じでエラーになります。また、接続していても、sudoを忘れると以下のように報告されました。結構親切。
$ picotool info No accessible RP2040 devices in BOOTSEL mode were found. but: Device at bus 1, address 4 appears to be a RP2040 device in BOOTSEL mode, but picotool was unable to connect
BOOTSELモードで接続されている状態であれば、実機ラズパイPico のフラッシュからのファイル吸い出しも以下のように可能です。
$ sudo picotool save fromflash.uf2 Saving file: [==============================] 100% Wrote 68096 bytes to fromflash.uf2
吸い出したファイルと、書き込んだ元ファイルを比較してみましたが、ファイルサイズ、内容とも一致しました。
オブジェクトファイルに書き込まれる情報の元
有用な情報を提供してくれる picotoolですが、読み取っている情報はオブジェクトファイル内に埋め込まれているか、解析して得た情報のようです。その中でもSDKレベルの情報のソースは以下の2つがあります。
-
- CMakeLists.txt 内に記述されている情報
- プログラムのソースコード内に記述されている情報
第1のCMakeLists.txt内の関連する記述部分の例は以下です。
pico_set_program_name(freqTST0 "freqTST0") pico_set_program_version(freqTST0 "0.1") ~省略~ pico_enable_stdio_usb(freqTST0 1)
プロジェクト作成時に自動もしくは手動でCMakeLists.txtファイルを作成すると思いますが、そのときに記述している上記のような行から、プログラムの名前やバージョン、そしてSTDIOがUSBに向いているといった情報が取り出されているようです。
しかし、何番ピンを何に使っている、といったプログラム動作に特有、そして忘却力に切実な情報は該当のソースコード内にプログラマが明示的に記述してやる必要があります。
明示的に記述しないとpicotollに聞いても以下のようにつれないお返事です。
Fixed Pin Information none
記述しておけば、こんな感じ。ブレッドボードへの配線に安全安心?
Fixed Pin Information 2: PWM OUTPUT A 3: PWM OUTPUT B 20: EXT CLOCK IN 21: EXT CLOCK OUT 25: On-board LED
前回のソースコードに、picotool で読み取れるピンの記述を追加する場合、ヘッダファイルを1つインクルードして、bi_で始まるマクロを使って記述する必要があります。追加修正部分はこんな感じ。
#include "pico/binarry_info.h" #define PWMOUTA (2) #define PWMOUTB (3) #define GPIN0 (20) #define GPOUT0 (21) #define LED (25) // ~途中省略、以下main()関数内に追加~ bi_decl(bi_1pin_with_name(LED, "On-board LED")); bi_decl(bi_1pin_with_name(PWMOUTA, "PWM OUTPUT A")); bi_decl(bi_1pin_with_name(PWMOUTB, "PWM OUTPUT B")); bi_decl(bi_1pin_with_name(GPIN0, "EXT CLOCK IN")); bi_decl(bi_1pin_with_name(GPOUT0, "EXT CLOCK OUT"));
一種、バイナリファイル内の付加情報で、実行には不必要な部分ではありますが、これで忘却力に対抗できるのはありがたい。勿論、マクロ1個定義すれば負荷情報をすべてストリップすることにも対応しているようです。メモリ消費量やセキュリティなどが気になったら付加しないようにもできる、と。とりあえずPinを何かに使ったら書いておいた方があとあと身のためかも。
なお、上記のようにマクロを追加しても、実際に実行するオブジェクト部分には更新が入らなかったです。タイムスタンプは先週プログラムを作ったときのままでした。