🦁

microruby (picoruby) + R2P2をビルドする - Raspberry Pi Pico 2 W編

に公開

はじめに

先日の記事ではRaspberry Pi Pico W用のpicoruby + R2P2をビルドしてみたが、今回はRaspberry Pi Pico 2 W用のMicroruby + R2P2を試してみる。

準備するもの

  • Raspberry Pi Pico 2 WまたはWH
  • Wifi環境

ビルド環境は前回と同様Ubuntu-24.04 (WSL上のものでも良い)。

ダウンロード

pico-sdkpico-extrasR2P2をgit cloneしてくる。ここでは以下のような配置にする。

$HOME/pico
       +- pico-sdk/
       +- pico-extras/
       +- R2P2/

R2P2のバージョンは、これを書いているときの最新master (dd30803228f828b1368f2bd3c3bc66bc1ff6d1ca) で、最新のタグである0.4.1から4つ追加コミットがある。対応するpico-sdkとpico-extrasのバージョンはR2P2のRakefileに書かれており、2.1.1らしいのでこれをcheckoutする。またR2P2とpico-sdkにはsubmoduleがあるのでそれもダウンロードしておく。まとめると以下のような感じになる。

$ mkdir $HOME/pico
$ cd $HOME/pico
$ git clone https://github.com/raspberrypi/pico-sdk.git
$ git -C pico-sdk checkout 2.1.1
$ git -C pico-sdk submodule update --init --recursive
$ git clone https://github.com/raspberrypi/pico-extras.git
$ git -C pico-extras checkout sdk-2.1.1
$ git clone https://github.com/picoruby/R2P2.git
$ git -C R2P2 checkout dd30803228f828b1368f2bd3c3bc66bc1ff6d1ca
$ git -C R2P2 submodule update --init --recursive

必要なパッケージ

前回から追加で入れたパッケージはないが、前回の段階ですでにあれこれ試した後なので、結局どれが必須なのかは相変わらず分かっていない。とりあえず以下は入れておこう。

  • ruby (CRuby): aptパッケージではなくrbenvで3.4.5を入れたが、aptでも多分大丈夫だろう。
  • cmake
  • gcc-arm-none-eabi
  • gcc-arm-linux-gnueabihf
  • zip: ないと途中のどこかでエラーになった気がする

どこかで失敗するところがあったら以下も入れてみる

  • libnewlib-arm-none-eabi
  • libstdc++-arm-none-eabi-newlib
  • pkg-config
  • libusb-dev

コード変更

コードを修正する必要はまったくないが、それだと公式ビルドと区別がつかないので、起動時のロゴに以下のような変更を入れた。mruby/cを使うPicorubyとmrubyを使うMicrorubyがあるので両方変更しておいた。

ビルド

ビルドはrakeコマンドで行うが、結論を先に書くと以下のようなスクリプト(run-rake.sh)をR2P2ディレクトリ直下におき、./run-rake.shすればよい。

#!/bin/bash

export PICO_SDK_PATH="$HOME/pico/pico-sdk"
export PICO_EXTRAS_PATH="$HOME/pico/pico-extras"
export SKIP_TEST=1

rake mruby:pico2:debug

手元の環境では3分ちょっと。ThinkPad X1 Carbon Gen7という2019年製PCなので、最近のPCならもっと短いはず。無事終わればbuild_pico2_w/以下にR2P2_PICO2_W-FLASH_MSC-0.4.1-20250721-dd30803.uf2ができているはず。

もうちょっと詳細

タスクの種類

rake --tasksでビルドタスクの一覧が見られる。クリーンアップ用のタスクを除くと以下が出てくる。つまり、pico, pico_w, pico2, pico2_wという4種類のボードそれぞれに対してmruby版, mrubyc版があり、さらにそれぞれdebug版とproduction版がある。今回はpico2_w, mruby版, debugでビルドした。他もいくつか試したが、全部がビルドできるわけではないようだ。

rake mruby:pico2:debug          # Build for pico2 with mruby VM (debug)
rake mruby:pico2:production     # Build for pico2 with mruby VM (production)
rake mruby:pico2_w:debug        # Build for pico2_w with mruby VM (debug)
rake mruby:pico2_w:production   # Build for pico2_w with mruby VM (production)
rake mruby:pico:debug           # Build for pico with mruby VM (debug)
rake mruby:pico:production      # Build for pico with mruby VM (production)
rake mruby:pico_w:debug         # Build for pico_w with mruby VM (debug)
rake mruby:pico_w:production    # Build for pico_w with mruby VM (production)
rake mrubyc:pico2:debug         # Build for pico2 with mrubyc VM (debug)
rake mrubyc:pico2:production    # Build for pico2 with mrubyc VM (production)
rake mrubyc:pico2_w:debug       # Build for pico2_w with mrubyc VM (debug)
rake mrubyc:pico2_w:production  # Build for pico2_w with mrubyc VM (production)
rake mrubyc:pico:debug          # Build for pico with mrubyc VM (debug)
rake mrubyc:pico:production     # Build for pico with mrubyc VM (production)
rake mrubyc:pico_w:debug        # Build for pico_w with mrubyc VM (debug)
rake mrubyc:pico_w:production   # Build for pico_w with mrubyc VM (production)

環境変数

pico-sdk、pico-extrasのパスを環境変数PICO_SDK_PATH, PICO_EXTRAS_PATHで指定する。前はBOARD, WIFIでボードの種類やWifiの有無を指定したような記憶があるが、Rakefileを見るとrakeのタスクに応じて自動的に設定されるようだ。

SKIP_TEST

上のスクリプトではSKIP_TEST=1を指定しているが、これはテストのエラーを避けるため。これを指定しないとrakeはまずテストを実行するが、steepがないためエラーになる。gem install steepで入れておけば続けられるが、今度は各種パッケージがインストールされていないというエラーになる。これについても cd lib/picoruby; bundle installすればインストールできるが、それでも以下のような感じのエラーがつらつらと出て止まってしまう。

ちゃんと直した方が良さそうだけど面倒なのでテストはスキップした。

実行

テストの失敗はさておき、ビルドができたら動かしてみる。

できあがったutf2をボードに入れるには、ボード上のBOOTSELボタンを押しながらPCと接続する。INDEX.HTMINFO_UF2.TXTを含むフォルダが見えるので、ここに先ほどの.uf2をドラッグアンドドロップする。コピーされればウィンドウが勝手に閉じられるので、今度はBOOTSELボタンを押さずに再度接続する。

接続したらTera Termを起動して"File" -> "New Connection"、"Serial"を選択してPortを選ぶ。分からなければボードを接続しない状態で選択可能なポートを確認して、再度接続してみる。新しく見えているポートがRaspberry Pi Pico 2 Wのはずだ。ここではCOM9になっている。

うまくいけば以下のようなロゴが見えるはずだ。

シェルのプロンプト($>)は見えるがロゴが見えない場合はターミナルの設定を確認する。メニューバーから"Setup" -> "Terminal..."を選び、"New-line"のところを見る。CRになっているとロゴがうまく見えないかもしれない。手元の環境ではReceiveを"AUTO", Transmitを"LF"にしている。

内蔵LED Lチカ

無事表示されたらirbと入力してirbを起動し、以下を入力。pin.write 1でLEDが点灯、pin.write 0で消灯できれば成功。

CYW43.init
pin = CYW43::GPIO.new(CYW43::GPIO::LED_PIN)
pin.write 1
pin.write 0

pin.write 1したところ

外部LED Lチカ

今回もまた秋月電子で買った抵抗内蔵LEDを使う。普通のLEDなら抵抗も入れよう。

Pico 2 Wのピン配置は以下のようらしいので、GP5 (7番)とその隣のGND (8番) を使うことにする。

irbへの入力は以下のとおり

pin = GPIO.new(5, GPIO::OUT)
pin.write 1
pin.write 0

ストレージの利用と問題発生

コードがある程度長くなると毎回irb上で打つのは面倒なので、そういうときは.rbを保存して実行する。PCに接続すれば外部ストレージとして見えているはずなので、以下のようなファイルを作って/home以下にblink.rbのような名前で保存する。あとはR2P2のシェルから./blink.rbとすれば1秒ごとに点滅するはずだ。

pin = GPIO.new(5, GPIO::OUT)
loop do
  pin.write 1
  sleep 1
  pin.write 0
  sleep 1
end

でもここで問題発生。ケーブルを外して再度接続するとファイルは残っているものの中味が壊れているようで動かない。Notepad++で開いてみると以下のようになってしまっている。今回の独自ビルド版のみでの事象ではなく公式バイナリでも起きるでの、ボードのどこかが壊れているのかもしれない。

Wifi接続とHTTPクライアント

気を取り直して、せっかくのWifi対応版なのでHTTPを試してみよう。コードは以下のようになる。HTTPSではない生HTTPのサイトはいまどきほとんどないので今回も阿部寛のページを使わせてもらう。

CYW43.init("JP")
CYW43.enable_sta_mode
ssid = "xxxx"        # WifiのSSID
pw = "yyyy"          # Wifiのパスワード
CYW43.connect_timeout(ssid, pw, 0x00400004)
c = Net::HTTPClient.new("abehiroshi.la.coocan.jp")
c.get("/")

うまくいけばShift_JISで書かれた、Homepage Builderで作られたらしきページが取得できる。

もう少し解説

CYW43.initの引数にcountry codeを指定している。内部で呼ばれるのはpico-sdkのcyw43_arch_init_with_countryのはずだが、国を指定すると何が変わるのかは書いていないので分からない。引数を指定しなくても動いた。

enable_sta_modeはWifiをステーションモード(子機としてアクセスポイントに接続する)にする。

CYW43.connect_timeoutでWifiに接続する。以前はconnect_blockingもあったはずだが今はなくなっているようだ。3番目の引数の数値はWifiの暗号化方式だか認証方式みたいなやつ。pico-sdkのドキュメントのここらへんにあるが、一応スクリーンショット。

まとめ

ということで今回はRaspberry Pi Pico 2 W用のMicrorubyを自前でビルドしてみた。ストレージに問題があったり、それ以外にもいくつか不安定なところ・よくわからないところがあったので、今後もう少し追ってみる(かもしれない)。

  • 再起動時にストレージ内のファイルが壊れる問題
  • irbを使っていると時々固まる
  • HTTPSのサイトの使い方
  • 無印Pico2やPico Wでのビルド
    • mrubycはビルドできたがmrubyはできなかった

Discussion