ワンボードマイコン RaspberryPi Pico と、その開発環境 Pico SDK が素晴らしすぎます。毎日これらと戯れてとても楽しいのですが、Pico SDK はほかのライブラリやプラットフォームに比べて情報が少なく、使い方を知るのに苦労します。この記事は、Pico SDK で RaspberryPi Pico のプログラミングを楽しむための最初の一歩を後押ししたいと思い作成しました。
Pico SDK のすすめ
RaspberryPi という名前で誤解しがちなのですが、Linux を搭載した RaspberryPi と Raspberry Pi Pico (以下 Pico) はまったくの別物です。両方とも Raspberry Pi Ltd. が提供しているボードですが、Pico は OS を持たない、ハードウェアの制御に特化したボードです1。
しかし性能はあなどれないです。2025 年現在、Pico には RP2040 を搭載した初代と、2024 年夏にリリースされた RP2350 搭載の Pico2 がありますが、初代のボードは133MHz の ARM コア (しかもデュアル)、264KByte の SRAM, 2MByte のフラッシュメモリ。Pico2 にいたっては CPU 150MHz (デュアル), 520KByte の SRAM, 4MByte のフラッシュメモリ、ハードウエア浮動小数点演算と、MS-DOS 時代のパソコン以上の性能です。これが 800 円程度で買えるのですから興奮してしまいますよね。今、手元に 10 枚ほどありますが、これらが作業机に転がっているとそれだけで創作意欲が高まります。
ところで、Pico のソフト開発には何を使いましょうか?
巷では MicroPython が一番人気があるようです。インタープリタ言語ですからコンパイルの手間もいりませんし、ユーザが多いので情報も豊富です。でも、インタープリタ言語の宿命として実行パフォーマンスが犠牲になってしまい、Pico が本来持っている性能を十分に発揮できません。インタープリタ自身の動作のために SRAM などの資源が消費されてしまうのも気になるところです。
次によく見かけるのは Arduino 環境を使ったプログラミングでしょうか。Arduino IDE をインストールすれば一通りの開発ができますし、ライブラリ管理機能を使って多くのライブラリを利用することができます。しかし Arduino のコンセプトは、様々な CPU やボードを共通した API でプログラミングできることを優先していて、CPU が持っている独自の機能を使いづらい傾向があります2。実行パフォーマンスも良いとは言えません。
Pico SDK は Pico/Pico2 専用の C 言語ライブラリです。CPU の設計元である RaspberryPi Ltd. が作っているだけあって、CPU が持つ機能をフルに使えるよう設計されています。また、パフォーマンスを最大限に引き出せる工夫が随所に施されていて、プロフェッショナルな仕事をしているなあと感心させられます。例えば以下のコードは:
int dma_channel = 3;
dma_channel_config config = dma_get_default_channel_config(dma_channel);
channel_config_set_read_increment(&config, true);
channel_config_set_write_increment(&config, true);
channel_config_set_dreq(&config, DREQ_SPI0_RX);
channel_config_set_transfer_data_size(&config, DMA_SIZE_8);
dma_set_config(dma_channel, &config, false);
インライン展開されて以下のコードになります。
*(volatile uint32_t *)(DMA_BASE + DMA_CH3_AL1_CTRL_OFFSET) = 0x00089831;
GPIO を最高速で On/Off させる以下のコードは:
int main()
{
gpio_init(15);
gpio_set_dir(15, true);
while (true) {
gpio_put(15, true);
gpio_put(15, false);
}
}
ループ部分のインストラクションを以下のように生成して:
loop: str r2, [r3, #20]
str r2, [r3, #24]
b loop
実際に Pico ボード (動作クロック 120MHz) で実行すると 30MHz (120MHz / (1 + 1 + 2 clock)) の信号を観測することができます (計算どおりに動いてくれるこの気持ちよさがたまらない!)。
ただ、実際に使うための情報が少ないです。詳細な情報を提供するドキュメントはありますし、全体的にかなり親切に書かれてはいます。ですが、肝心な箇所の説明が不十分だったり、雑な記述になっていたりして、ある程度の知識があることを前提にしているような雰囲気があります。
この記事は、そんな高いパフォーマンスを実現する Pico SDK の導入方法を、具体的なユースケースを念頭に置きながら紹介します。
手元に置きたいドキュメント
RaspberryPi Ltd. が提供している以下のドキュメントは何度も読み返すことになると思います。
-
Getting started with Raspberry Pi Pico-series
開発環境のセットアップの仕方や、デバグボードの配線の仕方などが説明されています。 -
Raspberry Pi Pico-series C/C++ SDK
Pico SDK で提供される関数などのドキュメントです。 -
RP2040 Datasheet, RP2350 Datasheet
SDK の関数が実際にどのような処理をしているか、ハードウェアの詳細なふるまいを知りたいときに参照します。PIO (Programmable I/O) の使い方は上記の SDK のドキュメントとこのデータシートの両方に重複して掲載されていますが、こちらの方が詳細に書かれています。
開発環境
Visual Studio Code
組込み系の開発環境というと、ターゲットボード用のコンパイラや、ライブラリ・ヘッダファイルのインストールと適切なパス設定、デバグツールの導入など、必要な作業がいろいろあって、経験のある人ほど躊躇してしまいそうです。Pico SDK の導入も少し前まではそのとおりだったのですが、Microsoft の Visual Studio Code (以下 VSCode) 用の Raspberry Pi Pico 拡張機能がリリースされたことで驚くほど簡単になりました。
まずは VSCode を https://code.visualstudio.com/download からダウンロードし、インストールしておいてください。
VSCode を使ったことのない人のために、いくつか知っておくべきことをここに記述しておきます。
基本的に VSCode はコマンドプロンプト、PowerShell または bash などのシェルで、プロジェクトが格納されたディレクトリに移って以下のように起動します。
code .
するとこのディレクトリの下に .vscode
というディレクトリが作成され、VSCode のワークスペースになります。ワークスペースには、コンパイルやデバグに必要な設定情報などが格納されます。また、ファイルのオープン状態もここに記録されるので、作業を再開したときにエディタが前と同じ状態になってくれてとても便利です。
VSCode の機能はほとんどすべて「コマンドパレット」と呼ばれるプロンプトからコマンドを入力することで実行できます。F1
または Ctrl
+Shift
+P
を押すとタイトルバーに以下のようなコマンドパレットが表示されます。
このテキストボックスはコマンドパレット以外にファイル切り替えやカーソル移動などにも使われます。先頭に >
が入力されているとコマンドパレットとして機能します。
以下の説明では VSCode の操作の説明をするのに、主にこのコマンドパレットのコマンド名を使っていきます。もちろん GUI 操作でもそれらの作業ができるのですが、「ウィンドウの一番上のボタンをクリックしてダイアログを出して...」などと書くよりも簡潔な説明ができます。
コマンド名がうろ覚えでも、コマンド名の一部を入力するとそれに合致したコマンドの一覧を表示してくれるので容易に目的のコマンドを探すことができます。コマンド名は、例えば Pico 関連のコマンドでしたら Raspberry Pi Pico:
、CMake 関連のコマンドなら CMake:
で始まるので、Pico:
だとか CMake:
などと入力することで利用可能なコマンドがわかります。
Raspberry Pi Pico 拡張のインストール
VSCode のコマンドパレットから >Extensions: Install Extensions
を実行すると利用可能な拡張機能が表示されます。検索ボックスに Pico
などと入力すると一覧の中に Raspberry Pi Pico
が出てくるので、それをインストールしてください。この時点では、Pico SDK のツール群やライブラリファイルなどはまだインストールされません。後述する Pico SDK プロジェクトの作成時に実際のインストール作業が行われます。
ほかにも CMake
, C/C++
, C/C++ Extension Pack
拡張機能なども必要だったり便利だったりするのでインストールしておきます。特に意識しなくても、プログラムのコードファイルやツールの設定ファイルを作成したり開いたりすると VSCode がそれに関連した拡張機能のインストールを自動的に勧めてくるので、必要に応じてインストールしていきます。
ところで、Pico SDK インストールに必要な操作はこれで完了です。簡単!
プロジェクトの作成と編集
プロジェクトの作成
Pico SDK のプロジェクトを作成するには、VSCode のコマンドパレットから >Raspberry Pi Pico: New Pico Project
を実行します。使用言語を聞かれるので C/C++
を選択すると以下の画面が表示されます。
設定内容は以下の通りです。最低限入力の必要がある項目は 太字 で書かれています。設定内容のほとんどはプロジェクト作成後に変更可能です。
- Basic Settings
- Name: プロジェクトの名前を入力します
- Board type: ボード種別を選択します
- Architecture (Pico2): Pico2 は ARM 以外に Risc-V アーキテクチャの CPU が組み込まれています。チェックしないでおきます
- Location: プロジェクトディレクトリを作る一つ上のディレクトリを選択します
- Select Pico SDK version: 使用する Pico SDK のバージョンです。デフォルトのままにしておきます
- Features
使用するライブラリを選択します。チェックしないでおきます - Stdio support
- Console over UART: デフォルト UART ピン (GPIO0, GPIO1) を使って stdio の関数たち (
printf()
やgetchar()
) のデータを送受信します。チェックしないでおきます - Console over USB (disbles other USB use): USB を使って stdio の関数たちのデータを送受信します。チェックしないでおきます
- Console over UART: デフォルト UART ピン (GPIO0, GPIO1) を使って stdio の関数たち (
- Code generation options
- Run the program from RAM rather than flash: 通常、プログラムはフラッシュメモリに書かれ、実行時に必要に応じて SRAM にコピーされます。このチェックをつけると、起動時にすべてのプログラムを SRAM にコピーして実行します。チェックしないでおきます
- Use project name as entry point file name: ひな形のソースファイルの名前をプロジェクト名と同じにします。チェックを外すと
main.c
またはmain.cpp
になります。チェックしたままにします - Generate C++ code: ひな形のソースファイルを C++ で出力します (拡張子が
.cpp
になります)。チェックしないでおきます - Enable C++ RTTI (Uses more memory): C++ の RTTI (Run-Time Type Information) 機能を有効にします。チェックしないでおきます
- Enable C++ exception (Uses more memory): C++ の例外処理を有効にします。チェックしないでおきます
- Debugger
- DebugProbe (CMSIS-DAP) [Default]: Debug Probe を使ってデバグをします。チェックしたままにします
- SWD (Pi host, on Pi5Pi 5 it requires Linux Kernel >= 6.6.47): Raspberry Pi を使ってデバグをします。チェックしないでおきます
[Create]
ボタンをクリックすると、プロジェクトを作成します。
Raspberry Pi Pico 拡張機能をインストールして初めてプロジェクトを作成したとき、VSCode ウィンドウの右下に Downloading and installing toolchain
というメッセージボックスがでてきて、しばらくそのままの状態が続きます (メッセージボックスが消えている場合は >Notifications: Show Notifications
を実行)。実はこの時点で Pico SDK を構成するファイル群をダウンロード・インストールしているのですが、サイズが巨大 (1.4 GByte) なので 20 分ほど待たされます。インストールして最初の一回だけなので、辛抱強く待ちましょう。進捗状況が Downloading and installing toolchain
メッセージの下の細いバーで表示されます。
プロジェクトが作成されると、そこのディレクトリをワークスペースにした別の VSCode が起動します。ビルドができるか早速試してしまいましょう。VSCode でビルドをするには、コマンドパレットから >CMake: Build
を実行するか [F7]
キーを押します。プロジェクト作成後、最初のビルドのときは Select a kit for hoge
というコンボボックスがでてくるので、Pico Using compilers: ...
を選択します。
エラーがなければ、ワークスペースディレクトリ直下に build
というディレクトリが作成され、実行ファイルや MAP ファイル、逆アセンブルファイルなどが生成されます。
Pico SDK の格納ディレクトリ
Pico SDK の格納ディレクトリは、Windows なら C:\Users\username\.pico-sdk
、Linux ならホームディレクトリ直下の $HOME/.pico-sdk
になります。
多くの場合、ビルドやデバグツールは VSCode から起動するので実行ファイルのパスを意識することはあまりないと思いますが、picotool
へのパス C:\Users\username\.pico-sdk\picotool\x.x.x\picotool
(x.x.x
はバージョン番号。2025 年 1 月現在 2.1.0
) は通しておくと便利かもしれません。
GitHub
Pico SDK は GitHub (https://github.com/raspberrypi) を通してコードファイルの配布をしています。Git ツールを https://git-scm.com/downloads からダウンロード・インストールしてください。
早速ですが、Git を使って Pico SDK に追加のライブラリのインストール (正確には「Git レポジトリのクローン」) をします。これらのライブラリは USB や Wi-Fi の機能を使う場合に必要です。
- コマンドプロンプトまたはシェルで Pico SDK のライブラリ格納ディレクトリに移動します。Windows なら
C:\Users\username\.pico-sdk\sdk\x.x.x
、Linux なら$HOME/.pico-sdk/sdk/x.x.x
です (x.x.x
はバージョン番号。2025 年 1 月現在2.1.0
) - 以下のコマンドを実行します
git submodule update --init
GitHub には Pico SDK を理解するための有用な情報が豊富に格納されています。以下のレポジトリを自分の作業ディレクトリにクローンしておくと便利です。
-
pico-examples
は Pico SDK を使ったサンプルプログラムを格納しています。API の具体的な使い方はこれを見ることでわかりますgit clone https://github.com/raspberrypi/pico-examples
-
pico-sdk
は Pico SDK のソースコードです。API の処理内容を調査したいときに参照します。インストールした.pico-sdk
の下にも同じものがあるのですが、ちょっとアクセスがしづらいので参照用に作業用ディレクトリにも置いておくと便利ですgit clone https://github.com/raspberrypi/pico-sdk
プロジェクトのファイル構成
プロジェクト名を hoge
にして Pico SDK のプロジェクトを作成すると、以下のディレクトリやファイルが作成されます。
-
.vscode
... VSCode のワークスペース情報が格納されます -
build
... ビルドした結果はこのディレクトリに出力されます -
.gitignore
... Git のバージョン管理から除外したいファイルやディレクトリをこのファイル内に記述します3 -
pico_sdk_import.cmake
... Pico SDK の設定ファイルで、CMakeLists.txt からinclude
されます -
CMakeLists.txt
... ビルド情報を記述した CMake 設定ファイルです -
hoge.c
... メインのソースファイルです
pico_sdk_import.cmake
は、このディレクトリが Rico SDK プロジェクトであることを VSCode に教える役目もあります。
.vscode
と build
は自動生成されるので、削除しても大丈夫です4。VSCode でこれらが存在しないディレクトリをワークスペースとして開くと、Do you want to import this projects as Raspberry Pi Pico project?
というメッセージボックスがでてくるので Yes
をクリックすると以下の画面が表示されます。
[Import]
ボタンをクリックすると .vscode
と build
が生成されて、このディレクトリを Pico SDK プロジェクトとして使えるようになります。
プログラムのビルド
ひな形として生成されたコードは以下のようになっていると思います。
#include <stdio.h>
#include "pico/stdlib.h"
int main()
{
stdio_init_all();
while (true) {
printf("Hello, world!\n");
sleep_ms(1000);
}
}
Pico ボードを買ってきて初めてプログラムを動かそうとしたとき、このコードを見てちょっととまどいました。printf
関数が呼ばれていますが、これはどこに文字を出力しているのでしょうか?
答えは、CMakeLists.txt
の設定内容によりますが、GPIO0 と GPIO1 をそれぞれ UART TX、UART RX とした UART 通信、もしくはボードに実装された USB 端子を Communication Device Class として機能させた UART 通信です。
GPIO を使った UART 通信の場合ですと USB-シリアル変換器やレベルシフタがないと PC と接続ができません (後述するデバグプローブを使うとこのポートに接続できます)。USB 端子を使った UART 通信は USB ケーブルさえあれば PC と接続できますが、そもそもどう設定すればそれができるのか、使い始めた当初はよく分かりません (実際はとても簡単)。シリアルターミナルも準備しなければいけませんし、そもそもボーレートなどの通信設定はどうなっている...? なんにせよ、動くかどうかもわからない初めてのプログラムなのに、設定や用意をしなければいけない不確実な要素が多いのです。
初めてのプログラムは王道の「L チカ」に限ります。ソースファイルを以下のミニマムなコードに置き換えてしまいます5。
#include "pico/stdlib.h"
int main()
{
gpio_init(15);
gpio_set_dir(15, GPIO_OUT);
while (true) {
gpio_put(15, true);
sleep_ms(500);
gpio_put(15, false);
sleep_ms(500);
}
}
Pico ボードの一番端にある GPIO15 に LED と抵抗 (100 Ω 程度) を接続します。手元の環境で実験してみると、Pico の GPIO は GND に短絡しても 最大 30mA 程度に電流が抑制される6 ようなので、最悪の場合、抵抗がなくても CPU や LED が破損することはなさそうです。
コマンドパレットから >CMake: Build
または F7
キーでビルドすると、build
ディレクトリに実行ファイルとして UF2 ファイル hoge.uf2
や ELF ファイル hoge.elf
が出力されます。UF2 ファイルと ELF ファイルは、それぞれターゲットボードへの書き込み方が異なります。
UF2 ファイルの書き込み
ターゲットの Pico ボードと USB ケーブルがあれば書き込みができる方法です。Pico ボード上にある BOOTSEL
ボタンを押し続けながらボードを USB 経由で PC に接続すると、Pico は BOOTSEL モードで立ち上がり、PC からはストレージとして認識されるようになります。Windows ですと D:
ドライブに割り当てられることが多いようですが、環境によって異なると思います。Explorer などで確認してください。
UF2 ファイルをこのストレージにコピーするとボード上の Flash メモリにその内容が書き込まれ、自動的にプログラムを開始します。
BOOTSEL モードで立ち上げるための方法ですが、PC に USB ケーブルを挿すことをきっかけにしてしまうと USB ケーブルを頻繁に着脱することになり、コネクタへのダメージが心配です。BOOTSEL モードへの移行は CPU をリセットしたときの BOOTSEL
ボタンの状態を見ているので、リセットボタンさえあればケーブルの着脱という面倒がなくなります。PICO ボードには 30 番ピンに RUN
という端子があり、これを GND に落とすとリセットがかかるようになっています。ここにタクトスイッチなどを配置しておけば、BOOTSEL
ボタンを押し続けながら RUN
に接続したタクトスイッチを押すことで BOOTSEL モードに移行できます。
ELF ファイルの書き込み
ELF ファイルをターゲットボードに書き込むには、Pico 用のデバグプローブが必要です。2,000 円ほどで購入できますが、ターゲットボードのほかにもう一枚 Pico ボードがあれば、それをデバグプローブにすることができます。以下にその方法を記述します。
-
https://github.com/raspberrypi/debugprobe/releases から
debugprobe_on_pico.uf2
(デバグプローブにするボードが Pico の場合) またはdebugprobe_on_pico2.uf2
(同じく Pico2 の場合) をダウンロードしてください。この UF2 ファイルを、前述した方法で Pico に書き込みます - デバグプローブにした Pico (左側) と、ターゲットボード Pico (右側) を以下のように接続します
プログラム書き込みやデバグに最低限必要なのは、電源ラインおよび DEBUG ポートの水色と紫色の配線です。DEBUG ポートの真ん中の GND は接続しなくても OK です。黄色と橙色の接続はprintf()
などの stdio 関数の入出力に使う UART 用です - VSCode で Pico SDK プロジェクトを開きます。コマンドパレットから
>Debug: Start Debugging
を実行するかF5
キーを押すと、プログラムをビルドした後、生成した ELF ファイルをターゲット Pico に書き込んでデバッガが起動します。main
関数の先頭でブレークがかかった状態になっているので、ここでまたF5
を押すとプログラムが走り始めます
接続時にエラーが出る場合は、まず配線に間違いがないかよく確認してください。とくに、ターゲットボードに電源が供給されているか注意してください。
ほかの要因として、選択しているボード種別が違っている可能性があります。後述する方法で切り替えてください。
設定の切り替え方
デフォルトの状態では、実行ファイルは DEBUG モードでビルドされます。また使用する SDK のバージョンやボード種別は Pioo SDK プロジェクト作成時に指定したものになります。これらの設定をプロジェクトを作成した後に随時切り替えるための方法を以下に示します。
-
Debug と Release の切り替え
コマンドパレットから>CMake: Select Variant
を実行すると Debug や Release、その他のビルドオプションを選択できます。ここで選択したあと>CMake: Configure
を実行してください。これを忘れると変更がビルドツールに反映されません -
Pico SDK バージョンの切り替え
コマンドパレットから>Raspberry Pi Pico: Switch Pico SDK
を実行します。Pico SDK は、新しいバージョンがでるとそれのインストールを勧めてくるので、知らず知らずのうちに複数のバージョンが混在することになります。プロジェクトを作成したときのバージョンと実際に使っているバージョンが異なるとコンパイル時にエラーになりますので、このコマンドで適切なバージョンを選択します -
ボード種別切り替え
コマンドパレットから>Raspberry Pi Pico: Switch Board
を実行します。Pico と Pico2 の両方を持っていると結構頻繁に切り替えることになると思います
Pico SDK バージョンとボード種別切り替えは VSCode のステータスバーをクリックすることで操作することもできます。
Hello, world! を実行する
L チカが無事に動いたところで、おあずけになっていた "Hello, world!" を実行してみます。
Pico SDK プロジェクトを作成するときに Stdio support の以下のチェックボックスをつけると Stdio の入出力がそれぞれのポートに接続されます。
-
Console over UART
... GPIO0 と GPIO1 をそれぞれ UART TX、UART RX とした UART 通信 -
Console over USB (disables other USB use)
... USB 端子を Communication Device Class として機能させた UART 通信
CMakeLists.txt
を編集して Stdio の設定を変えることもできます。以下の行で、Stdio を接続したいポートの数値を 1
にします。
pico_enable_stdio_uart(hoge 0)
pico_enable_stdio_usb(hoge 0)
PC でのシリアルコンソールの通信設定は「スピード 115200bps、データ長 8bit、パリティなし、ストップビット 1 ビット」です。
ちなみにどちらのポートも接続した場合は、printf()
や putchar()
などの出力関数を実行すると GPIO と USB 端子のどちらのポートにも文字が出力されます。また、getchar()
などの入力関数は両方のポートから入力を受け付けます。このことは以下のプログラムを Pico ボードで動かして GPIO の UART ポートと USB 端子経由のポートのそれぞれにシリアルコンソールを接続すると実際に確かめられます。
#include <stdio.h>
#include "pico/stdlib.h"
int main()
{
stdio_init_all();
while (true) {
putchar(getchar());
}
}
実際の開発ではどちらか一方のポートを使うことになるのですが、どちらを使うかはプログラムの書き込みに UF2 ファイルを使うか ELF ファイルを使うかで分かれると思います。
UF2 ファイルを使った場合は USB 端子経由でプログラムを書き込みますから、USB ケーブルが常に PC に接続されていると思います。USB のポートを Stdio に接続しておくと便利です。
ELF ファイルを使った場合はデバグプローブでプログラムを書き込みますが、デバグプローブに GPIO の UART を中継する機能がついているので、GPIO の UART ポートを Stdio に接続すると便利です。
次回予告
これまでの設定で Pico SDK を使う準備が整いました。あとはドキュメントを読むなりサンプルを動かすなりしてプログラムを作ることができると思います。
ところで、Pico SDK のプログラミングをサポートするライブラリ pico-jxglib を現在開発しています。次回の投稿ではそのライブラリの紹介をしたいと思っています。
-
リアルタイム OS を動かすことはありますが、Windows や Linux など高度な機能を備えた OS を動かす例はかなり特殊です。 ↩
-
Arduino が Pico に対応するため、Pico SDK を内部で使用しているようです。なので、Arduino 環境でもユーザが Pico SDK の機能を直接使うこともできます。 ↩
-
デフォルトで
build
が書かれていますが、個人的には.vscode
も追加したいところ ↩ -
トラブル解決のため、あえて削除することもあります。 ↩
-
ところで
main
関数の戻り値がint
なのに、return
文がないのは、この手の組込み系プログラムの慣例のようなのでそれに従っています。どうせ無視される値なのですが、いつも居心地の悪さを感じてしまいます。 ↩ -
gpio_set_drive_strength()
関数を使うと最大出力電流値を変えられます。最大に設定すると 60mA 程度出力されるようです。 ↩