VSCode拡張機能`Raspberry Pi Pico`でC/C++開発環境構築が楽になった
Pico向けC/C++開発マニュアル
Pico向けのC/C++開発のドキュメントがあって、日本語版はかなり古くて2021年末のものですが、ラズパイ4で開発ビルドするケースとLinux/Mac/Windowsで環境構築する話が記載されてます。
日本語版(古い)
英語版
リンク集
で、日本語版の古い情報で、Windowsでの開発環境構築で苦戦していたのですが、英語版にVSCodeの拡張機能についての記載が冒頭にありました。
要するに、「これ使っとけ」ということです。実際に使ったらホントにこれで良かったです。
Windows環境+VSCode + Raspberry Pi Pico拡張機能
まず、自分の開発環境と方針について
- とりあえずWindows環境でやりたい
- VSCode上でビルドもデバッグもしたい
- BOOTSEL押して書き込みはメンドクサイ。SWD経由でスマートに書き込みしたい。
1と2については、上記の拡張機能で実現可能。
3については、自分はもう一台のPicoをDebug Probe化することで対応できました。拡張機能からDebug Probe経由でフラッシュしたり、デバッグ実行して、ブレークポイントでステップ実行もできてますし、シリアルコンソールでUART出力の確認もできました。
拡張機能のインストール
選択してインストールするだけです。
アイコンが追加されるので、選択すると、下図のようにメニューが表示されます。
サンプルから新規プロジェクト作成
新規プロジェクトは以下のとおりです。(インポートはやったことないので省略)
コマンド | 内容 |
---|---|
New Project | プロジェクト新規作成 |
New Project From Example | サンプルを選択してコピーして開始 |
サンプルは、以下のリポジトリの内容です。自分がやりたいことに近いサンプルを選ぶと、CMakeの設定とか参考になると思います。
まずは、New Project From ExampleでとりあえずLチカを実際やるところまで進めてみます。
サンプルをプルダウンから選びます。今回はblinkを選択
プロジェクトのコピー先の親ディレクトリやSDKバージョン、Debuggerを選択します。Debuggerについては、DebugProbeを選択。(ラズパイでGPIO接続する場合は、**SWD(Pi host)**かもしれないけど未確認)
プロジェクトが作成されると、別のウィンドウでVSCodeが起動して、プロジェクトがルートになってます。
出力内容は、基本サンプルと同じだけど、.vscode以下のビルド、デバッグ設定とかが拡張機能によってインストール環境に合わせて設定されています。
buildフォルダは起動時にcmakeが実行された結果が出力されていて、ビルドするとココにuf2やelfなどのモジュールが出力されます。
CMakeLists.txtの内容もサンプルとほぼ一緒ですが、githubのリポジトリにあるサンプルだと共通のファイルと個々のサンプルのファイルに分かれていたけど、こちらは1個で完結してます。
開発マニュアルで手動でCMakeLists.txtを作成するときの内容とほぼ一緒です。
# Generated Cmake Pico project file
cmake_minimum_required(VERSION 3.13)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Initialise pico_sdk from installed location
# (note this can come from environment, CMake cache etc)
# == DO NEVER EDIT THE NEXT LINES for Raspberry Pi Pico VS Code Extension to work ==
if(WIN32)
set(USERHOME $ENV{USERPROFILE})
else()
set(USERHOME $ENV{HOME})
endif()
set(sdkVersion 2.0.0)
set(toolchainVersion 13_2_Rel1)
set(picotoolVersion 2.0.0)
include(${USERHOME}/.pico-sdk/cmake/pico-vscode.cmake)
# ====================================================================================
set(PICO_BOARD pico CACHE STRING "Board type")
# Pull in Raspberry Pi Pico SDK (must be before project)
include(pico_sdk_import.cmake)
project(blink C CXX ASM)
# Initialise the Raspberry Pi Pico SDK
pico_sdk_init()
# Add executable. Default name is the project name, version 0.1
add_executable(blink
blink.c
)
# pull in common dependencies
target_link_libraries(blink pico_stdlib)
if (PICO_CYW43_SUPPORTED)
target_link_libraries(blink pico_cyw43_arch_none)
endif()
# create map/bin/hex file etc.
pico_add_extra_outputs(blink)
# add url via pico_set_program_url
プロジェクトフォルダを開いた状態で、拡張機能のメニューを表示すると、選択できるメニューが増えてます。開発ツールおなじみの内容です。
コマンド | 内容 |
---|---|
Debug Project | デバッグ実行 |
Compile Project | ビルド |
Run Project | プロジェクト実行 |
Configure CMake | cmakeファイル作成 |
Configure CMakeは、buildフォルダ以下のMakefileを作成します。試しにbuildフォルダ丸ごと削除して実行すると再作成してくれます。(cmakeコマンド実行と同じ)
Compile Projectを実行すると、ビルドが開始されて、モジュールが生成されるはず。
ninja: Entering directory `C:\work\blink/build'
[61/61] Linking CXX executable blink.elf
* ターミナルはタスクで再利用されます、閉じるには任意のキーを押してください。
blink.uf2とかblink.elfが作成されてます。
次はデバッグ実行ですが、その前にもう一台のPicoを使ってDebugProbe化しておきます。
もう一台のPicoを使ってDebugProbe化
ソースやモジュールが以下にあります。1回きりなので、ビルド済みを使って書き込んでおきます。
注意しないといけないのは、Raspberry Pi PicoをDebugProbe化する場合は下図のdebugprobe_on_pico.uf2を使います。debugprobe.uf2は製品版向けなので間違えると動作しないと思います。
BOOTSELを押しながらUSB接続して上記モジュールをコピーして完了。(省略)
DebugProbe化したPicoとターゲットのPicoの接続について、開発マニュアルにある絵を転載します。
Raspberry Pi Pico (Pico2もピンレイアウトは同じ)
DebugProbeとPicoの接続は下図です。PCとUSB接続するのは左のDebugProbe側です。
DebugProbe | ターゲットPico |
---|---|
GP2 | SWCLK |
GP3 | SWDIO |
UART1 TX | UART0 RX |
UART1 RX | UART0 TX |
VSYS | VSYS |
GND | GND |
書き込むだけなら、UART間の接続は不要だと思います。この接続があると、プログラムでprint出力がPC側のターミナルで表示できます。
実際の接続例です。VSYSのところにダイオードがありますが、この実験の前にRaspberry Pi5と接続していたときに入れていたものです。Pico同士の接続では、マニュアルにはないので直接繋いでも良いと思います。
デバッグ実行
Probe化したPicoとの接続が完了したら、デバッグ実行してみます。PCとUSB接続したら、Debug Projectを実行します。
Pico Debug Codex-Debugを選択
しばらくすると、デバッグモードに切り替わって、mainの先頭で一時停止してます。
Debugツールバーでステップオーバー(F10)などして動作できてること、ウォッチで変数の値が見えてればOKです。裏でOpenOCDが動作してますが、ボタン一つで起動して連動できていて、とても便利です。
シリアルモニターでprint文のモニタリング
Lチカできたら、次はシリアルモニタにprint文字列を表示したいと思います。上記のLチカプログラムに設定と処理を追加していきます。
まず、CMakeLists.txtを開いて、標準入出力(STDIO)のインターフェースとしてUARTを有効にして、Configure CMakeを実行します。
CMakeやMakefileが更新されてない場合は、build丸ごと削除してConfigure CMakeでも良いと思います。
pico_enable_stdio_uart(blink 1)
ソース側にはstdioのヘッダとprintf()を追加してビルドします。
#include <stdio.h>
:
int main() {
stdio_init_all();
int rc = pico_led_init();
hard_assert(rc == PICO_OK);
while (true) {
pico_set_led(true);
printf("LED ON!\n");
sleep_ms(LED_DELAY_MS);
pico_set_led(false);
printf("LED OFF!\n");
sleep_ms(LED_DELAY_MS);
}
}
シリアルモニターのタブでDebugProbeのUSBポートを選択(COM7、環境によって異なる)したら監視を開始したら、Debug Projectで実行します。
続行(F5)で、プログラムを続行させると、下図のように、モニタにprintf文字列が出力されます。
プログラムのフラッシュ
上記のデバッグを実行すると、プログラム(点滅とシリアルモニターへの出力)が実行されますが、停止するとどちらも止まってしまいます。
デバッグが終了すると、プログラムが消されるのか、そもそも一時的にもターゲットには書き込んでないのかもしれないです。(たぶんopenocd実行時の引数でそうなっている)
プログラムをフラッシュときは、Ctrl+Shift+PまたはF1でコマンドパレットを開いて、tasks run taskでタスクを実行を選択して、
Flashを選択すると、SWD経由で書き込みできます。(BOOTSEL押したりしなくてOK)
成功すると、Verified OKになって、プログラムがフラッシュメモリへの書き込みが成功したら、リセット後にプログラムが開始します。
** Programming Started **
Warn : Function FUNC_BOOTROM_STATE_RESET not found in RP2xxx ROM. (probably an RP2040 or an RP2350 A0)
Warn : Function FUNC_FLASH_RESET_ADDRESS_TRANS not found in RP2xxx ROM. (probably an RP2040 or an RP2350 A0)
Info : RP2040 Flash Probe: 33554432 bytes @0x10000000, in 8192 sectors
Info : Padding image section 1 at 0x100049a4 with 92 bytes (bank write end alignment)
Warn : Adding extra erase range, 0x10004a00 .. 0x10004fff
** Programming Finished **
** Verify Started **
** Verified OK **
** Resetting Target **
shutdown command invoked
これで、Pico単体で電源ONされるとプログラムが開始するようになります。
拡張機能のおかげで、VSCodeだけでスムーズに開発できるようになっているので、特にWindows環境でのPicoのC/C++プログラミングは、ハードル下がったと思います。
Discussion