Raspberry Pi AI Cameraをさわってみた

こんにちは、あっきぃです。

先日発売されたRaapberry Pi AI Cameraのサンプルをミドクラ様からお借りできましたので、さわってみたレポートをお送りします。

製品のようす

カメラ本体。カメラセンサーはソニーのIMX500という、2020年頃に登場したセンサーを使用しています。

一見すると今までのカメラモジュールと同じように見えますが、AI Cameraは、搭載されているIMX500カメラセンサー自体がAI処理を実行して結果を返すため、映像と結果を受け取ることも、結果だけ受け取ることもできます。後者を活用すれば、通信帯域を節約しながら物体検出を行ったり、プライバシーに配慮しながらデータを軽量に保存することも可能になります1。ちなみに、右側のパーツはレンズ部分に付属する保護カバー?のようです。使うときは外して使用するようです。

カメラセンサーの下にチップが見えていますが、これはRaspberry Pi PicoでおなじみRP2040チップです。以下は製品画像の引用2ですが、センサーの下はこうなっているようです。

こちらは特筆することはないのですが、カメラセンサーの裏側も。

パッケージと付属物はこちら。白いドーナツ状のパーツは、Camera Module2にも付属していた。レンズのフォーカス調整用リングです。カメラケーブルはPi 5で登場した、今までより硬めのケーブルが、Pi 5とZero系向けのものと、それ以外の従来モデル向けのものの2種類付属しています。

導入してみよう

今回はドキュメントのチュートリアルをそのまま試すだけとしたため、手順は以下のページを参照ください。

https://www.raspberrypi.com/documentation/accessories/ai-camera.html

とはいえ、OSを最新にアップデートして(カーネル、libcamera、Picamera2などをIMX500のバージョンに上げる必要があります)、imx500-allパッケージを導入するだけで遊び始められるため、比較的かんたんです。

動かしてみる

実際に動かしてみましょう。まずはRaspberry Pi 5を使用して、いろいろなサンプルを動かしてみました。カメラは、カメラケーブルにマスキングテープで針金(ケーブルを束ねるのに使われているネジネジのやつ)を貼り付けて、フレキシブルなケーブルにするハックと、スマホスタンドの組み合わせで固定しました。

まずはシンプルな物体検出のサンプル。最近はあまり見かけないような気もする、Raspberry Pi公式マスコットのクマ「Babbage Bear」が、きちんと「teddy bear」として認識されていますね。皆さんご存知でしょうか?Pimoroniで現在もふつうに購入できるので、気になる方はこちらです。

少し見づらいですが、ディスプレイの左下でhtopコマンドを実行しています。Raspberry Pi自体に負荷がそれほどかかっていない=カメラがAI処理をやっています。

こちらはスクリーンショットでちゃんと撮影してかつ、Picamera2バージョンの物体検出サンプルです。AI Cameraももちろん、Picamera2で開発できるのが利点の一つです。こちらのほうがhtopの結果が見やすいですね。ちなみに、左上のデモ実行の出力を見ると、Network Firmware Uploadという出力が見えますが、コマンドを実行すると、カメラにデータを転送する処理があり、起動までに30秒〜1分ほど時間がかかります。

こちらは人間のモーション検出デモ。これも先のデモも含め、AI Kitで同様のデモが実行できますが、ほぼ同じことがカメラだけでできています。おかしなポーズをとってもちゃんと認識していますね。

これはセグメンテーションのデモ。検出したものの物体に色をつけてくれるものですが、暗めの緑で色付けをされて、呪いにかかった人間のエフェクトっぽいなと思ったので、そんなポーズにしてみました。夜に試していたときの写真なので、実際に疲れているのですが。

他のモデルでも動かしてみる

AI Cameraのリリースの記事では、AI CameraはPi Zeroをふくむすべてのモデルで動作しますと言及されています。

The AI Camera can be connected to all Raspberry Pi models, including Raspberry Pi Zero, using our regular camera ribbon cables.

実際に、先日のMaker Faire Tokyo 2024のKSYブースでは、Raspberry Pi Ltdから来ていたMattさんがAI Cameraのデモを持参して展示していて、ここではPi Zero(おそらく2W)が使用されていました。

というわけでわたしもPi Zero 2Wで環境を再現してみました。ディスプレイはPimoroniのHyperPixel4を使用しました。

裏面。こちらのカメラの固定には簡易的に、厚紙とマスキングテープを使用しています。

MicroSDカードのセットアップは、あらかじめRaspberry Pi 5で済ませて、動作も確認してからPi Zero 2Wに移しました。が、どうやらこれではPiZero 2W上のRaspberry Pi OSがカメラを自動認識できないようです。ドキュメントのチュートリアルでも、「少し手を加えれば」という一文があるので、どうやら手を加える必要がありそうです。

With minor changes, you can follow these instructions on other Raspberry Pi models with a camera connector, including the Raspberry Pi Zero 2 W and Raspberry Pi 3 Model B+.

ドキュメントには記載がありませんが、はカメラを手動でも認識できるようにすれば良いので、つまり、/boot/firmware/config.txtに設定を追記すればOKです。

# この設定をコメントアウトする
# Automatically load overlays for detected cameras
#camera_auto_detect=1 

# ファイル末尾の[all]以下に追記
[all]
dtoverlay=imx500

# これはHyperPixel4用の設定
dtoverlay=vc4-kms-dpi-hyperpixel4

設定後にOSを再起動をしたら無事に認識してくれたので、試してみた結果がこちら。

動画で!

もちろん、PiZero 2WはRAMが512MBしかないため、デスクトップが起動するまで待たされたりしますが、起動してしまえば、動画のように物体検出の結果がすぐにでてきます。

AI KitとAI Cameraどちらにしよう?

公式のリリースでも言及されていますが、AI Kitはパフォーマンスの代わりにPi 5限定である一方、AI Cameraはカメラと一体になっているため用意するものがこれ一個で済んで、Pi 5以外のほぼすべてのRaspberry Piで使えます。

個人的には、手軽な入門としては、後者のほうが手軽そうな印象をもちました。

入手するには?

AI Cameraは各リセーラーを通じて販売される見込みです。観測している範囲では、KSYさんと、イギリスのPimoroniは未入荷です。スイッチサイエンスだけ昨晩に販売がありましたが、初回入荷分は少量だったようで、一瞬で完売してしまったようです(わたしはなんとか間に合って購入できました)。1万3千円ほどするのに、皆さん判断が早い……!!

そう言った状況のため、例によって当面入手が難しいと予想されます。AI Cameraが欲しい方は、リセーラーさんの入荷通知機能や、Pre-Orderを活用してみてください。

  1. https://www.sony.com/ja/SonyInfo/News/Press/202005/20-037/ ↩︎
  2. https://www.raspberrypi.com/products/ai-camera/ ↩︎

Raspberry Pi 4のリビジョンと消費電力の話

昨日はちょっと久々のRaspberry Pi JAM Tokyoでした。天気が悪くてどうなるかと思いましたが、ピークが前にずれたおかげで、移動してる間に雨がやんだのでなんとかなりました。よかったーー。

ミドクラさんのスペースの入口にJAMのロゴが入りました。すごい……!

参加人数は天気などの都合で参加できなくなってしまった人もいたぶん減ってしまいましたが、たこ焼きパーティをしながらラズパイの話とかとかラズパイじゃない話とかで盛り上がりました。

Raspberry Pi 4のリビジョンの話

昨日の発表はPi 5とかOSの近況をやったのですが、当日追加でつっこんで話したPi 4の話題をブログにもまとめなおしてみます。Pi 4は最初の発表から3回ほどリビジョンが変わっていて、現在はRev.1.5です。ざっくり以下の内訳です。Rev.1.3がないのは不明ですが、ボツにでもなったのでしょう……?。

  • Rev.1.1(2019/6〜): 最初。PD電源が使えない問題があった初期リビジョン。日本未発売なので大多数の日本人ユーザーには関係ない
  • Rev.1.2(2019/10〜12): PD電源が使えるように修正されたリビジョン。ここから日本で発売されるようになった。 
  • Rev.1.4(2020/5, 2021/1〜): 8GB RAM登場以降のデザイン。Dialogのsub-PMICが搭載され、TVSダイオードが移動した。2021/1〜はおそらく他のRAMのモデル?
  • Rev.1.5(2021/10〜): 現行。PMIXがMxLからDialog DA9090に変更された

カッコ内はおもに変更履歴のTransition Dateから引用(1.4の2020/5は8GB RAM登場時)ですが、現行リビジョンは2021年10月から移行ということになっていて、実はもう2年半くらい経過しているので、多分これを持っている人も多そうな気がしますが、半導体不足真っ只中だったので、そうでない可能性もあるような気がしています。どうでしょう。

変更履歴はRaspberry Pi Production Information Portal(PIP)で誰でも確認できます。

https://pip.raspberrypi.com/categories/560-pcn

また、手持ちのPi 4のリビジョンはcat /proc/cpuinfoコマンドで確認できます。

最新リビジョンが欲しい

わたしの場合、出たらすぐに買ってしまうので、最新リビジョンは持っていないことに気づきました。パーツが変わっても動作に変更はないはずですが、もしかして電力の効率が変わって省エネになってたりしたら嬉しいよななどと思ってしまい、しばらく悶々とした結局、我慢できずに買ってしまいました。

ヤフオクで1週間くらい出物を探し回り、マークしてたやつが値下げ再出品されたタイミングで即決落札して、ヤフオクのクーポンとPayPayのポイントを駆使しました。おかげで散財が軽減されました(セルフ暗示)。届いたのがこちら。赤枠部分がPMIC、MxLからDialogになっているのがわかります。

ところで、ヤフオクで物色するために見分け方を研究しまくっていたせいで、先日話題になっていた、ロシアで使われていたというPi 4も、瞬時に「こいつはRev.1.4以降…」と見分けられてしまいました。ちなみに、TVSダイオードがHDMI0の左にいなければRev.1.4以降です。

https://togetter.com/li/2385032

半導体不足でメイカー向けに流れなくてヒーヒー言ってるそばでロシアにRPiが戦争用途に流れてしまっていたのは遺憾(製品の規約でも元から禁止されている)です。ロシアには、やはりというか中国から流されているのがイギリス有料ニュース記事で指摘されていたようです。500万ドル分らしいので、4GB RAM(55ドル)と仮定して利益云々無視した単純な割り算をすれば約9万台となり、なかなかひどいお話です(なお、ウクライナ側も使っていたりするようで……?)。

https://forums.raspberrypi.com/viewtopic.php?t=368865

消費電力を見る

話を戻し「もしかして電力の効率が変わって省エネになってたりしたら嬉しいよな」を確かめるべく電力を測ってみます。USB電流計測器のUT70にPi 5の公式電源を入力して、OUTからPi 4に接続して、MicroSDからOSを起動します。起動が終わって落ち着いた頃の電流をチェックしていきます。

なお、OS側では、電源LEDオフと、無線の無効化の設定を投入しています。設定してない状態で比較すればよかったですね……。設定方法は私のブログのほうで触れています。

また、EEPROMのバージョンも全部そろえてあります。

Rev.1.2

これだけRAMが4GBですが(このリビジョンに8GBモデルはない)それは見なかったことにしつつ、結果は358mAでした。

Rev.1.4

8GBがでてすぐに買ったやつです。結果は353mA。誤差かもしれないけど、Rev.1.2よりも5mAくらい低いかも?

Rev.1.5

これも8GB RAMです。なんと285mA!?50〜60mAも差があるのですが、なんですかこれは?

ついでにRev.1.1

昔Pimoroniで2GB RAMを買ってみたら、まだ在庫のRev.1.1があったらしく来ちゃったやつもいちおう試してみます。技適はないことになっているので、ここでは念のため暗箱に投入します。特例出すよりこっちのが出すだけで早いので……。なお、今回からミドクラ様からユーザー会に貸与いただいた暗箱を使用しています。ありがとうございます。そしていきなり個人的な興味のために使ってしまいすみませんでした。

雑に箱の中にiPhoneをつっこんで、動画をとることでUT70の値を読むことにしました。

結果は390mA。1.5とは100mAも差がついてしまいました。さすがにこの結果をもってPi 4同士で買い替えることはないと思うのですが、Rev.1.1ユーザーはちょっと心揺れてしまいそうな結果です。

Rev.1.5ならSoCの温度も低い気がする

この消費電力ならと、アイドル時のRev.1.5のSoCに指を乗せると、やはりというか全然ぬるいことに気が付きました。初期のアツアツはどこへやら。SoCに指を載せては「熱くて触れない!」などと言われがち(どうしてそんなことを?)ですが、そんな一部な方にもぜひ触ってみて欲しいです。ちなみに45.7℃でした。やっぱりぬるめ。

$ vcgencmd measure_temp
temp=45.7'C

まとめ

1万円ちょっとでただ知的好奇心を満たしました。なんとなく想像だけで買ってみたものの、想定外に消費電力が減っていたのでビビりました。しかし散財である。

リビジョンアイドル時の電流(mA。無線と電源LEDを無効化した状態)
1.1390
1.2358
1.4353
1.5285
表でまとめ。

DA9090に変更後にそのような支店で見ている人がいるか探そうとしたら、フォーラムで「DA9090が壊れやすく、入手性がMxLよりも悪いため修理もできない」と騒いでいる、おそらく少数の人を見かけました。入手性はさておき、本当に壊れやすいならとっくに対策が入っているはずですから、無視して良いと思われます。

買ったPi 4は、デスクの上で動いているPi 2Bを置き換えるのに使おうと考えているところです。上に張ったカリカリチューニングのブログに書きましたが、Pi 2Bは現状340mAで動いているので、50〜60mAの節電をしながらRAMを8倍にできそうです。

Raspberry Pi Connectがでた(どこからでもラズパイにリモートデスクトップ!)

Raspberry Pi Ltdから、Raspberry Pi Connectなるサービスがベータ扱いで公開されました。

https://www.raspberrypi.com/news/raspberry-pi-connect/

あらかじめRaspberry Pi IDを取得して、Raspberry Pi OSのデスクトップ環境にRaspberry Pi Connectをセットアップしておけば、Raspberry Pi IDを使用して世界中のどこからでもWebブラウザ経由でリモートデスクトップ接続ができるというサービスです。

インストールや設定手順はドキュメントが公開されているので、興味がある人はここを参照してセットアップしてみてください。

https://www.raspberrypi.com/documentation/services/connect.html

ただし、ベータ版のため、予期せぬ不具合等が起こる場合もあるかもしれないとのこと。なにかあった場合はフォーラムで報告してみると良いでしょう。

手元で動かしてみた様子はこちら。LAN内で試しているのでさすがに動画再生もスムーズです(音声は非対応です)。

再生しているのはJeff Geerling氏のRaspberry Pi Connectレビュー動画。多分この私の記事より情報があるのでこちらをおすすめします。

自分でVPNを用意せずに手軽にリモート接続ができるので、自宅に1台セットアップしておいて、自宅LAN内の踏み台環境なんかに使うと便利そうです。最新のRaspberry Pi OSなら構築できるので、モデルはあまり問いませんが、Pi 5+NVMe SSDな環境ならアイドル4W、上のように動画を再生してActive Coolerがゆるゆると回っている状態で5〜8Wと、PCと比較すればまあ省電力なデスクトップ環境にできるので、どこでも自宅Pi 5環境に接続できるというのはアリっぽい気がします。

当然、Raspberry Piのインターネット環境はRaspberry Piの設置場所によるので、海外旅行中に日本でしか見られないサイトを見る、あるいはその逆、なんて使い方もできそうですね。

ちょっと可能性を感じるおもしろげなこのサービス、一度試してみると良いと思います。

(追記) 家から出るとやはり遅い

会社から自宅のRaspberry PiにConnectしてみたところ、画面が表示されないか、表示されてもほぼ操作できない状態になりました。Jeffの動画でも触れられていましたが、これはロンドンの中継サーバーを中継してしまっているので遅くなってしまうようです(鍵アイコンにカーソルを合わせると表示されます)。中継サーバーが増えれば改善されるかもしれませんが、そうすると無料でサービス維持ができるかどうか……?という話題にもなってきそう。

会社から自宅にVPN接続した状態でConnectすると、こちらは中継サーバーを使用しないpeer-to-peer接続になり、快適に使用できました。これはちょっとおもしろい挙動のような気がしました。

あと、Jeffの動画を全部ちゃんと見ていなくて気づいてなかったのですが、動画中に私のYoutubeアイコンが映り込んでいました😆(メンバーシップのユーザー一覧でした)

Raspberry Pi Pico Version of IchigoJam

Programming Club Networkさまから、IchigoJamのRaspberry Pi Picoバージョンについて、寄稿いただきました。

IchigoJAM P: https://pcn.club/sp/ijp/


軽快な Raspberry Pi Pico 、これで IchigoJam BASIC が動いたら楽しそう!

そこで IchigoJam BASIC を RP2040 に移植!

ブレッドボードで回路を組んで、

Picoにファームウェアを焼いて、

合体!モニタはDVI、キーボードはUSB。

10 LED1:WAIT30:LED0:WAIT30
30 GOTO10

もちろん、Lチカできるし、

かわくだりゲームだって

BASIC で動いちゃう。

ロボットに搭載すれば、

BASICで自在に動かせるよ!

ファームウェアは今夏リリース予定、お楽しみに!

RP1チップをJTAGでデバッグしてみよう

はじめに

こんにちは、tnishinagaです。
今回はRP1のJTAGデバッグ方法を見つけたので、ご紹介します。

注意

本記事ではRP1が想定していない操作を行うため、本内容の実施によりRP1含めRaspberry Pi 5が故障する可能性があります。
十分ご注意の上、実施される際は自己責任のもとでお願いします。

要約

overview in english

RP1とリバースエンジニアリング

RP1はRaspberry Pi 5に搭載されているサウスブリッジ的なチップです。
Pi 5のIOのほぼすべてをこのRP1が担っているため、RP1を自由に制御できればPi5を自由に制御できると言えるのではと勝手に思っています。

このRP1のペリフェラルマニュアルは公開されていますが、中で動いているコードや一部仕様については非公開となっています。
そのため自由に扱うにはリバースエンジニアリングが必要であり、私を含め国内外で数人が取り組んでいるようです。

リバースエンジニアリングでは、人間がコンピューターの状態をなんとかして知る手段の確保が重要です。
その中でもとくにJTAGデバッガーが利用可能になると、プロセッサの制御を自由に行えて大変嬉しいです。
どこかに使えるJTAG端子は生えていないでしょうか?

RP1のJTAGを探す旅

RP1のペリフェラルマニュアルを読んでみると、6ページのFigure2にARM DEBUGと書かれた部分があり、少なくともプロセッサコアからJTAG端子が出ているとわかります。

画像はRP1のペリフェラルマニュアル, pp.6, Figure2より引用

また、特殊電子回路株式会社のなひたふさんの解析結果より、Pi 5のUSB端子の下にあるフレキシブルケーブル用のパターンからRP1のJTAG端子が出ていることが確認されています。

実際に自分も0.5mmピッチのフレキシブルケーブルと端子を購入してJTAGデバッガーとつなげて様子を見てみたところ、Raspberry Pi Trading LtdのTAPが見つかりました。

~/p/t/r/pi5_jtag ❯❯❯ openocd -f interface/ftdi/olimex-arm-usb-tiny-h.cfg -c 'transport select jtag'
Open On-Chip Debugger 0.12.0
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
jtag
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Warn : An adapter speed is not selected in the init scripts. OpenOCD will try to run the adapter at the low speed (100 kHz)
Warn : To remove this warnings and achieve reasonable communication speed with the target, set "adapter speed" or "jtag_rclk" in the init scripts.
Warn : libusb_detach_kernel_driver() failed with LIBUSB_ERROR_ACCESS, trying to continue anyway
Info : clock speed 100 kHz
Warn : There are no enabled taps.  AUTO PROBING MIGHT NOT WORK!!
Info : JTAG tap: auto0.tap tap/device found: 0x20001927 (mfg: 0x493 (Raspberry Pi Trading Ltd), part: 0x0001, ver: 0x2)
Warn : AUTO auto0.tap - use "jtag newtap auto0 tap -irlen 5 -expected-id 0x20001927"
Warn : gdb services need one or more targets defined

これがRP1のCortex-M3コアのTAPと考えてDAPの接続等を試行しましたが、うまくいきませんでした。
Arm Debug Interfaceでは命令ビット長は4または8bitと決められていますが、OpenOCDがAutoProbeで見つけた命令ビット長は5bitなので、合っていません。
よって、Cortex-M3以外の何らかのTAPが見えていると考えられます。

※Arm Debug Interfaceの仕様やデバッグの詳細については手前味噌ですがこちらの資料をご覧ください。

隠しコマンド、発見

TAPID 0x20001927へのDAP接続試行を何度か試していたところ、たまに違うTAPIDが見つかる事がありました。

# 当時のログを再現
Info : JTAG tap: auto0.tap tap/device found: 0x4ba00477 (mfg: 0x23b (ARM Ltd), part: 0xba00, ver: 0x4)
Info : JTAG tap: auto1.tap tap/device found: 0x4ba00477 (mfg: 0x23b (ARM Ltd), part: 0xba00, ver: 0x4)
Warn : AUTO auto0.tap - use "jtag newtap auto0 tap -irlen 4 -expected-id 0x4ba00477"
Warn : AUTO auto1.tap - use "jtag newtap auto1 tap -irlen 4 -expected-id 0x4ba00477"

最初はTAPのStateがおかしくなったのかなと思っていたのですが、よく見るとTAP IDのManufacturer ID Code部がArm Ltdとなっています。
もしやと思って出てきたTAPに対しDAPの接続を試したところ、Cortex-M3のDebug Unitが見えました。

そしてさらに調査を行ったところ、以下の操作を行うことでRP1のCortex-M3のTAPが見えるようになることを見つけました。

  • IRに0x1dをセットする
  • DRに0を128bit送る

どうやら隠しコマンドを見つけてしまったようです。
もしかすると他にも似たような隠しコマンドがあるかもしれません。

RP1にJTAG接続する方法

ここでやり方をまとめましょう。

ハードウェアの準備

Raspberry Pi 5のUSB下にあるフレキケーブル端子のパターン、またはテストポイントからJTAGに使う以下の線を引き出してください。
(端子とテストポイントの対応はなひたふさんのブログ記事を参考)

  • TDI : TP53
  • TDO : TP54
  • TCK : TP55
  • TMS : TP56
  • GND : GPIO端子等
  • 3.3V: GPIO端子等

引き出したらJTAGデバッガーと接続します。
私の使用したARM-USB-TINY-Hというデバッガーと接続するための回路図を共有しますので、ARM JTAG 20のピン配置を確認しつつ接続を行ってください。

ARM JTAG 20のピン配置はなひたふさんの解説がわかりやすくてオススメです。

私はつなぎ間違えが怖いので基板を作りました。

隠しコマンドの発行

JTAGデバッガーをつなぎ、OpenOCDを入れたマシンに以下のスクリプトを保存し、実行します。
これで次回のOpenOCD実行時からCortex-M3のTAPが見えるようになります。

# SPDX-License-Identifier: GPL-2.0-or-later
# Toshifumi Nishinaga<tnishinaga.dev@gmail.com>

# rp1_init.cfg
transport select jtag
adapter speed 1

jtag newtap cpu0 cpu -expected-id 0x20001927 -irlen 5

init

pathmove IRSHIFT
irscan cpu0.cpu 0x1d 

pathmove DRSHIFT
drscan cpu0.cpu 8 0
openocd -f interface/ftdi/olimex-arm-usb-tiny-h.cfg -f rp1_init.cfg

Cortex-M3コアへの接続

先ほどと同様に、以下のファイルを作ってからopenocdを実行してください。

# rp1.cfg
# This file is based on target/bcm2711.cfg
# SPDX-License-Identifier: GPL-2.0-or-later
# Toshifumi Nishinaga<tnishinaga.dev@gmail.com>

transport select jtag
adapter speed 100

jtag newtap cpu0 cpu -expected-id 0x4ba00477 -irlen 4
jtag newtap cpu1 cpu -expected-id 0x4ba00477 -irlen 4

dap create cpu0.dap -chain-position cpu0.cpu
dap create cpu1.dap -chain-position cpu1.cpu

# cpu0
target create cpu0.ap mem_ap -dap cpu0.dap -ap-num 0
target create cpu0 cortex_m -dap cpu0.dap -ap-num 0 -dbgbase 0xe000e000
# cpu1
target create cpu1.ap mem_ap -dap cpu1.dap -ap-num 0
target create cpu1 cortex_m -dap cpu1.dap -ap-num 0 -dbgbase 0xe000e000
openocd -f interface/ftdi/olimex-arm-usb-tiny-h.cfg -f rp1.cfg

以下のようなログが出たら成功です。

~/p/t/r/pi5_jtag ❯❯❯ openocd -f interface/ftdi/olimex-arm-usb-tiny-h.cfg -f rp1.cfg
Open On-Chip Debugger 0.12.0
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
3758153728
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Warn : libusb_detach_kernel_driver() failed with LIBUSB_ERROR_ACCESS, trying to continue anyway
Info : clock speed 100 kHz
Info : JTAG tap: cpu0.cpu tap/device found: 0x4ba00477 (mfg: 0x23b (ARM Ltd), part: 0xba00, ver: 0x4)
Info : JTAG tap: cpu1.cpu tap/device found: 0x4ba00477 (mfg: 0x23b (ARM Ltd), part: 0xba00, ver: 0x4)
Info : [cpu0] Cortex-M3 r2p1 processor detected
Info : [cpu0] target has 6 breakpoints, 4 watchpoints
Info : [cpu1] Cortex-M3 r2p1 processor detected
Info : [cpu1] target has 6 breakpoints, 4 watchpoints
Info : gdb port disabled
Info : starting gdb server for cpu0 on 3333
Info : Listening on port 3333 for gdb connections
Info : gdb port disabled
Info : starting gdb server for cpu1 on 3334
Info : Listening on port 3334 for gdb connections

あとはgdbでTCP 3333や3334番につなぐとRP1を自由に操作できます。

(gdb) tar remote :3334

(gdb) i r
r0             0x676e6f6c          1735290732
r1             0x77207265          1998615141
r2             0x696b726f          1768649327
r3             0x1                 1
r4             0x34                52
r5             0x100029b0          268446128
r6             0x34                52
r7             0x20003990          536885648
r8             0x200057d0          536893392
r9             0x10002010          268443664
r10            0x200057d8          536893400
r11            0x200057d4          536893396
r12            0x0                 0
sp             0x10002980          0x10002980
lr             0x100002dd          268436189
pc             0x100003ae          0x100003ae
xPSR           0x81000000          -2130706432
msp            0x10002980          0x10002980
psp            0x0                 0x0
primask        0x0                 0
basepri        0x0                 0
faultmask      0x0                 0
control        0x0                 0

試しにRP1のcore1に接続してレジスタを眺めたところ、PCがProc Local ISRAMの領域を指している様子が伺えました。

以上です。
Happy Hacking!

Raspberry Pi 5をハードウェアデバッグしてみよう

はじめに

はじめまして。 tnishinagaです。
この度ご縁があって、こちらのブログに寄稿させていただく事になりました。
よろしくお願いいたします。

要約

  • Raspberry Pi 5のハードウェアデバッグはJTAGからSWDを使う方法に変わりました
  • Raspberry Pi Debug ProbeとOpenOCDを使えばハードウェアデバッグできます

BareMetalで遊びたい! Raspberry Pi 5

この度Raspberry Pi 5が日本で発表されました。
ここで私を含めシステムプログラマが気になるのは「Raspberry Pi 5で自作OS開発などのベアメタル開発ができるのか」ではないでしょうか。

早速入手したRaspberry Pi5を用いてハードウェアデバッグ方法について調べてみたので、今回はその方法を共有します。

おことわり

とくに言及がない限り、本内容はすべて「オープンな情報」および「リバースエンジニアリングで得た情報」を用いて調査して書かれています。
Raspberry Pi財団等の公式見解ではないため、誤りがあったり、今後の仕様変更で記載した方法を利用できなくなることがあります。
あらかじめご了承ください。

ハードウェアデバッグの方法

Raspberry Pi 5からのハードウェアデバッグは、Raspberry Pi 4までと比べて以下の点が変わっていました。

  • デバッグインターフェイスがJTAGからSWDに変わった
  • デバッグ用端子が出ている場所が40pin GPIOからUART/デバッグ用コネクタに変わった
    • UARTとハードウェアデバッグ機能は排他
    • Raspberry Pi Debug Probeがあれば簡単に接続可能
  • デバッグ・CTIのアドレスが変わった
    • OpenOCDの設定ファイルに変更が必要

デバッグの仕組みがSWDに変わったので、Raspberry Pi 4まで利用していたJTAGデバッガーは使えなくなりました。
一方、Raspberry Pi Debug Probeは一般的なデバッガーの中では比較的安価ですし、接続もケーブル1本でよくなりました。
そのため、全体的なデバッグの敷居は低くなった印象です。

必要なもの

今回Raspberry Pi 5のデバッグには以下の製品を利用しました。

SWD接続できるデバッガーであれば何でもよいのですが、接続に使うJSTコネクタを用意するのがちょっとだけ大変なので上記Probeの利用をオススメします。

セットアップ

デバッグまでの事前準備として、以下を行います。

  • config.txt の修正
  • Raspberry PiとDebug Probeの接続
  • OpenOCDのインストールと設定ファイルの作成

Raspberry Pi側の準備

Raspberry Pi ImagerなどでRaspberry Pi OS(64bit)をmicroSDカードに書き込んでください。
その後、第1パーティション(Raspberry Pi OS上からは /boot/firmware/ 以下)の config.txt の末尾に以下の行を追記してください。

enable_jtag_gpio=1

この設定を入れることでRaspberry Pi 5のUART端子の機能が起動時にSWDへ変わり、デバッガーをつなげるようになります。

接続

以下の画像を参考に、Raspberry Pi 5のUART端子(HDMI端子の間)とDebug ProbeのSWD端子(右側のDと書かれたほう)をコネクタで繋いでください。

OpenOCDのインストール

Debug Probe制御のためOpenOCDを利用します。
以下を参考にご自身のPCにOpenOCDをインストールしてください。

https://openocd.org/pages/getting-openocd.html

本記事ではOpenOCD 0.12.0を用いて動作を確認しています。
もしうまく動かない場合は、こちらのバージョンを使って動作を確認してください。

設定ファイルの作成

OpenOCDを使ってデバッグを行う際は、デバッグターゲットの設定ファイルが必要です。
ROM infoから得られる情報を用いてRaspberry Pi 5に搭載されているBCM2712用の設定ファイルを作ったので、以下を適当な場所に保存してください。
(OpenOCDに含まれる target/bcm2711.cfg をベースに作成したので、このファイルのライセンスは元ファイルと同じくGPL2.0で提供します)

# bcm2712.cfg
# SPDX-License-Identifier: GPL-2.0-or-later
# OpenOCD target config file
# This file is based on target/bcm2711.cfg
# I have checked that it works with Open On-Chip Debugger 0.12.0 
# using the Raspberry Pi Debug-Probe interface

transport select swd
adapter speed 1000

if { [info exists CHIPNAME] } {
    set  _CHIPNAME $CHIPNAME
} else {
    set  _CHIPNAME bcm2712
}

if { [info exists CHIPCORES] } {
    set _cores $CHIPCORES
} else {
    set _cores 4
}

if { [info exists USE_SMP] } {
    set _USE_SMP $USE_SMP
} else {
    set _USE_SMP 0
}

if { [info exists DAP_TAPID] } {
    set _DAP_TAPID $DAP_TAPID
} else {
    set _DAP_TAPID 0x2ba00477
}

# swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_DAP_TAPID
swd newdap $_CHIPNAME cpu -expected-id $_DAP_TAPID
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu

# MEM-AP for direct access
target create $_CHIPNAME.ap mem_ap -dap $_CHIPNAME.dap -ap-num 0

# these addresses are obtained from the ROM table via 'dap info 0' command
set _DBGBASE {0x80010000 0x80110000 0x80210000 0x80310000}
set _CTIBASE {0x80020000 0x80120000 0x80220000 0x80320000}

set _smp_command "target smp"

for { set _core 0 } { $_core < $_cores } { incr _core } {
    set _CTINAME $_CHIPNAME.cti$_core
    set _TARGETNAME $_CHIPNAME.cpu$_core

    cti create $_CTINAME -dap $_CHIPNAME.dap -ap-num 0 -baseaddr [lindex $_CTIBASE $_core]
    target create $_TARGETNAME aarch64 -dap $_CHIPNAME.dap -ap-num 0 -dbgbase [lindex $_DBGBASE $_core] -cti $_CTINAME

    set _smp_command "$_smp_command $_TARGETNAME"
}

if {$_USE_SMP} {
    eval $_smp_command
}

# default target is cpu0
targets $_CHIPNAME.cpu0

以上で準備は完了です。

ハードウェアデバッグ

ここからは実際にOpenOCDを立ち上げてデバッグを行ってみます。

OpenOCDの起動

さきほど取得したファイル等を用いてOpenOCDを起動し、Raspberry Pi 5に接続します。
Raspberry Pi 5の電源を入れて数秒待った後(※)、以下のコマンドをPC上で実行してください。
(※: 最初しばらくはブートローダーのログ出力のために使われるので、SWD機能に変わるのを待つ必要があります)

openocd -f interface/cmsis-dap.cfg -f bcm2712.cfg

うまく接続ができれば、以下のようなログが出てきます。

~/p/t/r/pi5_jtag ❯❯❯ openocd -f interface/cmsis-dap.cfg -f bcm2712.cfg
Open On-Chip Debugger 0.12.0
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : Using CMSIS-DAPv2 interface with VID:PID=0x2e8a:0x000c, serial=SERIAL_NUMBER
Info : CMSIS-DAP: SWD supported
Info : CMSIS-DAP: Atomic commands supported
Info : CMSIS-DAP: Test domain timer supported
Info : CMSIS-DAP: FW Version = 2.0.0
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : SWCLK/TCK = 0 SWDIO/TMS = 0 TDI = 0 TDO = 0 nTRST = 0 nRESET = 0
Info : CMSIS-DAP: Interface ready
Info : clock speed 1000 kHz
Info : SWD DPIDR 0x2ba01477
Info : bcm2712.cpu0: hardware has 6 breakpoints, 4 watchpoints
Info : bcm2712.cpu1: hardware has 6 breakpoints, 4 watchpoints
Info : bcm2712.cpu2: hardware has 6 breakpoints, 4 watchpoints
Info : bcm2712.cpu3: hardware has 6 breakpoints, 4 watchpoints
Info : gdb port disabled
Info : starting gdb server for bcm2712.cpu0 on 3333
Info : Listening on port 3333 for gdb connections
Info : starting gdb server for bcm2712.cpu1 on 3334
Info : Listening on port 3334 for gdb connections
Info : starting gdb server for bcm2712.cpu2 on 3335
Info : Listening on port 3335 for gdb connections
Info : starting gdb server for bcm2712.cpu3 on 3336
Info : Listening on port 3336 for gdb connections

GDBの接続

OpenOCDが正常に立ち上がった場合、OpenOCDがtelnetとGDBのサーバーを起動します。
このサーバーに各種デバッガーで接続すると、デバッグを行えます。

例としてGDBの接続方法をご紹介します。
aarch64向けのgdb(aarch64-elf-gdbgdb-multiarch)を起動した後、以下のコマンドを実行してOpenOCDのGDBサーバー接続してください。

target remote :3333

あとは自由にデバッグを行えます。
たとえば Ctrl + C を実行してコアをhaltしたあと、i r でレジスタの中身が見られます。

(gdb) i r
x0             0xffffb001f2910000  18446656121143885824
x1             0xffff8001ffac3a70  18446603344805640816
x2             0xffffd0000d4d84c0  18446691297374602432
x3             0xffffd0000d18c008  18446691297371144200
x4             0x1                 1
x5             0xffffd0000d4d1000  18446691297374572544
x6             0x1db3292f5         7972492021
x7             0x0                 0
x8             0xffffd0000d4c3c98  18446691297374518424
x9             0xffffd0000c0df61c  18446691297353659932
x10            0x1a90              6800
x11            0x1ef               495
x12            0x2                 2
x13            0x0                 0
x14            0x1                 1
x15            0x0                 0
x16            0xffffd0000cc076a0  18446691297365358240
x17            0x0                 0
x18            0x0                 0
x19            0x0                 0
x20            0xffffd0000d4d0998  18446691297374570904
x21            0xffffd0000d4d0878  18446691297374570616
x22            0xffffd0000d1b4e38  18446691297371311672
x23            0xffffd0000cf72108  18446691297368940808
x24            0x0                 0
x25            0x0                 0
x26            0xffffd0000d4d84c0  18446691297374602432
x27            0x0                 0
x28            0x12789fc           19368444
x29            0xffffd0000d4c3d40  18446691297374518592
x30            0xffffd0000cc03464  18446691297365341284
sp             0xffffd0000d4c3d40  0xffffd0000d4c3d40
pc             0xffffd0000cc0344c  0xffffd0000cc0344c

おわり

以上でハードウェアデバッグ方法のご紹介を終わります。
この内容がみなさまのお役に立てれば幸いです。

参考資料

Raspberry Pi 5の各種NVMe SSDボードを試す

あっきぃです。

日本ではRaspberry Pi 5の発売はまだですが、先週末には日本の技適に関する証書PDFがRaspberry Piのポータルにアップロードされ、進捗が見えてきています。残念ながらこのPDFをもって日本で買ったり使ったりして良いことにはなっておらず、製品(またはパッケージ等)にマークと番号が印字されたものが販売開始されて初めて適法に利用できるようになるため、もう少しの辛抱です。

https://pip.raspberrypi.com/categories/894-approvals

さて、今回はRaspberry Pi 5のNVMe SSD用アクセサリーボードの話題。PCI Expressポートを使用したNVMe SSDの接続用アクセサリーボードについて、公式から販売が予告されていますが、まだ発売はされていません。しかし、すでにサードパーティベンダーからはいくつものNVMe SSDの接続用アクセサリーボードが発売されています。何種類か入手して試してみましたので、それぞれの使用感をレポートしていきます。

3種類のボード

今回紹介するのはこちらの3種類です。

各ボードについて、それぞれ詳しく見ていきましょう。

コンパクトながら2280サイズに対応するX1001

GeekwormのX1001は、Pi 5上に搭載するタイプのボードです。GPIO接続は不要かつGPIO部分が空いているため、HATボードの接続等のGPIOポートアクセスが可能です。固定用のネジ穴は3つで、スペーサーをつけると3本足で立つ、少しふしぎな形になります。

NVMe SSDは2230、2242、2260、2280のサイズに対応しますが、SSDの固定のダボは2280で固定になっていて外せないため、写真のように2280サイズ以外のSSDを使う場合には、別のアダプター等に付属している固定ネジが必要になります。また、動作中はACTのLEDランプが点滅します。

HAT形状のHAT Drive! Top

2023年9月末に設立されたばかりという、ポーランドのPineBerry Piが販売するHAT Drive Top!は、HATサイズにまとまったコンパクトなボードです。コンパクトな分、対応するNVMe SSDのサイズは2230、2242のみとなります。通電中の電源ランプとACTランプを搭載しています。

Raspberry Piへの接続は、PCIeケーブルのみでも動作しましたが、GPIOポートに接続するための延長ピンソケットが付属しており、これを使用して他のHATボードなどとセットで搭載することができます。なお、延長ピンソケットの抜き差しは慣れるまでは少し大変な印象でした。

Pi 5の下に配置!NVMe Base

イギリスのPimoroniが販売するNVMe Baseは、先述の2つとは違い、Pi 5の下に搭載するタイプのボードです(ちなみに、Pineberry PiやGeekwormも同様にボトムに配置するタイプのボードがあるようです)。

SSDのサイズはX1001と同じく2230、2242、2260、2280に対応します。SSDの固定は付属のネジとナットを使用して固定します。

ボードの裏面は波紋のような模様が特徴的。また、FPCケーブルのカーブも面白い設計ですね。

組み立てたあとの様子。ボードが下にあるため、Pi 5の全ポートにアクセス可能なのが便利です。一方、SSDの交換については都度ネジを外す必要があるのが、用途によっては面倒に感じるかも知れません。また、公式ケースやPimoroniのPiBowとは組み合わせられないのも惜しいところです。NVMe Baseに対応したPiBowケースの登場に期待したいです。

Raspberry Pi 5でNVMeブートをするための手順

Pi 5でNVMeブートをするには、事前にPi 5のEEPROM上の設定に対してブート順序の変更が必要なため、MicroSDカードでOSを起動して、rpi-eeprom-configコマンドを実行して設定作業を行います。

コマンドを実行するとエディターに設定が表示されるため、以下の2つのパラメータについて設定します。

$ sudo rpi-eeprom-config --edit

[all]
# BOOT_ORDERを変更。fより右に6を含める
BOOT_ORDER=0xf416

# 追記する
PCIE_PROBE=1

BOOT_ORDERパラメータは、6がfよりも右に含まれるように書き換えます。Raspberry Piの起動時には、数字の右側から起動が試行されます。0xf416の場合は、NVMe、MicroSD、USBの順に試して、起動メディアがなければまたNVMeから再試行していきます。各数字の意味の詳細は公式のドキュメントを参照してください。

https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#BOOT_ORDER

PCIE_PROBEパラメータは、次期HAT(おそらくHAT+)の仕様をサポートしないボードのためのパラメーターで、設定するとCM4と同様のPCIe x1検出方法になります。この設定はX1001とNVMe Baseの場合は不要です。HatDrive! Topの場合のみGPIO接続時にパラメータが必要ですが、GPIOに接続しない場合は不要です(今後のHatDrive!の設計変更によってはGPIO接続時でも不要になる可能性があります)。

https://github.com/raspberrypi/rpi-eeprom/releases/tag/v2023.12.06-2712

設定後はファイルを保存して終了し、一度OSを再起動します。再起動後はOSをシャットダウンしておきます。

NVMe SSDへのOSの用意

NVMe SSDにRaspberry Pi OSをインストールするには、作業PCにNVMe SSDを接続するために、USBに変換するためのエククロージャが必要です。Amazon等で販売されているので、1つ用意しておくと良いでしょう。

USB変換を使用してPC等に接続するとUSBストレージとして認識するので、MicroSDカードのときと同様に、Raspberry Pi Imager等を使用してRaspberry Pi OSを書き込みます。

OSを書き込んだ後、再度PCに接続してブートパーティションをマウントし、/boot/config.txtをエディターで開いて、以下の設定をファイルの末尾に追記します。

[all]
dtparam=pciex1
dtparam=pciex1_gen=3

dtparam=pciex1は、PCI Expressの外部コネクターを有効にするためのオプションです(なくても動作しますが一応記述します)。有効化すると、ポートがPCI Express 2.0 x1として利用できるようになります。

しかし、公式にはサポートされていないものの、dtparam=pciex1_gen=3を追加することで、PCI Express 3.0 x1として利用できるように強制できます。ただし、起動できなかったり、不安定になる場合もあるようなので、不具合が生じた場合はこのパラメータと除いてみてください。

起動!

OSが用意できたらボードをPi 5に搭載して起動します。ユーザー会では引き続き電波暗箱を使用しているため、箱にボードを入れての試験となります。基本的にボードに因る性能差異はなかったため、HatDrive! Topで検証した内容を掲載します。PCIe 3.0×1で問題なく利用できたため、SSDの性能をより引き出すことができました。

まずはhdparmを使用したシーケンシャルリードのテスト。800MB/sという、ラズパイらしからぬ性能が出ています。

akkie@nvmepi1:~ $ sudo hdparm -t /dev/nvme0n1

/dev/nvme0n1:
 Timing buffered disk reads: 2454 MB in  3.00 seconds = 817.58 MB/sec

続けてddコマンドでシーケンシャルライトのテスト。こちらも700MB/s弱の性能を叩き出していて、やはりラズパイらしからぬスピードです。

akkie@nvmepi1:~ $ dd if=/dev/zero of=a.zero bs=1M count=10000
10000+0 records in
10000+0 records out
10485760000 bytes (10 GB, 9.8 GiB) copied, 15.0922 s, 695 MB/s

Raspberry Piのストレージをテストしてサイトに掲載するスクリプトを提供しているPi Benchmarksのスクリプトを使用したテスト結果は以下の通り。DDの書き込み方法が異なるためか、あるいは熱による性能低下によるものかは不明ですが、こちらは359MB/sにダウンしてしまいました。ランダムの読み書き性能は150〜200MB/sと、なかなかの数字となりました。

     Category                  Test                      Result     
HDParm                    Disk Read                 798.84 MB/sec            
HDParm                    Cached Disk Read          675.10 MB/sec            
DD                        Disk Write                359 MB/s                 
FIO                       4k random read            126419 IOPS (505679 KB/s)
FIO                       4k random write           59883 IOPS (239532 KB/s) 
IOZone                    4k read                   198011 KB/s              
IOZone                    4k write                  144889 KB/s              
IOZone                    4k random read            57412 KB/s               
IOZone                    4k random write           167898 KB/s              

                          Score: 37236 

まとめ

色々なNVMeボードについて特徴を解説し、実際にボードをRaspberry Pi 5で利用するための手順について解説しました。

公式のNVMe HATボードがまだ登場していませんが、すでにサードパーティベンダーから、今回紹介したような、使い方やNVMe SSDのサイズに応じた様々なボードを選べるようになっているため、お好みで用意してみてはいかがでしょうか。

NVMe SSDを利用することで、MicroSDカードよりも高信頼かつ高速なRaspberry Piの環境が構築できます。サーバー用にRaspberry Pi 5を検討している方は、NVMe SSDの採用も合わせて検討すると良いでしょう。

Raspberry Pi PicoとWIZnetのEthernetモジュールでWebサーバーを立てて謎APIを作って遊ぼう

こんにちは、あっきぃです。この記事はRaspberry Pi Advent Calendar 2023の15日目の記事です。

WIZnetさんからサンプルをいただいたので、今回はそちらを使って少し遊んでみます。レビューのほうは別の方がする予定となっているため、私からはとにかくなんか遊ぶ感じの話題をお届けします。ちなみにいただいたのは以下の3種類(下のHATは2つ)。WIZnetさん、ありがとうございます!

今回遊ぶ内容的にはどれを使用しても同じですが、今回はEthernet HATの方を使用しました。こちらの場合別途Raspberry Pi Picoが必要になりますが、EVB-Picoよりも全長が少し短くなってコンパクトになります。また、EVB-Picoと比べるとボード上の通電LEDがPicoで覆い隠せるため、実運用に投入するとLEDが眩しくて邪魔という問題が緩和できます。まあ、EVB-PicoのEVBはEValuation Boardの略だと思うので、実運用に適しているのかは不明ですが……。

なお、WIZnet製品は、スイッチサイエンスで購入できます。

https://www.switch-science.com/collections/all/cat:%E3%83%A1%E3%83%BC%E3%82%AB%E3%83%BC%2F%E3%83%96%E3%83%A9%E3%83%B3%E3%83%89_WIZnet

今回はCircuitPythonを使用して、Raspberry Pi Picoが接続されているPCのマウスカーソル操作をWeb API化して、リモート操作できるようにしてみます。

CircuitPythonを使う時、Macユーザーは注意

Macユーザー向けにナウな注意として、現在のmacOS Sonoma(14.2時点で問題は継続中)では、macOSの不具合によって、CircuitPythonを接続してすぐにスクリプトの読み書きをすると、I/Oエラーが発生してデータが破損するなどのおそれがあります。以下のページにあるシェルスクリプトを使用して再マウントすることで問題を回避できます。

https://learn.adafruit.com/welcome-to-circuitpython/troubleshooting#macos-sonoma-14-dot-x-disk-errors-writing-to-circuitpy-3160304

ネットワークに接続する

WIZnetのデバイスを扱うには、adafruit_wiznet5kモジュールを使用します。CircuitPythonのライブラリバンドルに収録されているので、ここからadafruit_winzet5kモジュールをデバイス上のlibディレクトリにコピーして使用します。

WIZnetのデバイスを使ってDHCPでアドレスを取得するまでのコードは、以下のようになります。このコードをデバイス上の/code.pyとして保存します。

import board
import busio
import digitalio
import time
from adafruit_wiznet5k.adafruit_wiznet5k import WIZNET5K

# SPIの初期化
SPI_SCK = board.GP18
SPI_TX = board.GP19
SPI_RX = board.GP16
SPI_CSn = board.GP17
W5500_RSTn = board.GP20
cs = digitalio.DigitalInOut(SPI_CSn)
spi_bus = busio.SPI(SPI_SCK, MOSI=SPI_TX, MISO=SPI_RX)

# デバイスをリセットする
ethernetRst = digitalio.DigitalInOut(W5500_RSTn)
ethernetRst.direction = digitalio.Direction.OUTPUT
ethernetRst.value = False
time.sleep(1)
ethernetRst.value = True

# 接続する
eth = WIZNET5K(spi_bus, cs, is_dhcp=True)
print("MAC Address:", [hex(i) for i in eth.mac_address])
print("My IP address is:", eth.pretty_ip(eth.ip_address))

実行結果は以下の通り。デバイスはMACアドレスは持っていないため、”dead beef feed”になっています。MACアドレスを指定することは可能なため、複数動かすなどの場合には適宜変更すると良さそうです。

code.py output:
MAC Address: ['0xde', '0xad', '0xbe', '0xef', '0xfe', '0xed']
My IP address is: 192.168.29.127

Code done running.

Webサーバーにする

CircuitPythonでWebサーバーを作成するにはadafruit_httpserverモジュールを使うのが簡単です。ただ、WIZnetのボード向けのCircuitPythonにはhashlibモジュールが内蔵されていないため、現在のモジュールのバージョンでは、インポート時にエラーが発生します。そのため、ライブラリバンドルからではなく、Githubリポジトリから最新のコードを取得して、adafruit_httpserver/response.pyにあるimport hashlibの行をコメントアウトする必要があります。この問題は報告をして、現在やり取りをしているところです。 (追記)修正されたようです。リリースもされたため最新のバージョンが使用可能です。

https://github.com/adafruit/Adafruit_CircuitPython_HTTPServer/issues/73

ライブラリの方に一手間が発生してしまいましたが、気を取り直して、上記のIPアドレスを取得するコードに、次のコードを書き加えると、Webサーバーが起動するようになります。

import adafruit_wiznet5k.adafruit_wiznet5k_socket as socket
from adafruit_httpserver import Server, Request, Response

socket.set_interface(eth)
server = Server(socket)

@server.route("/")
def root(request: Request):
    print("GET /")
    return Response(request, "Hello!")

server.serve_forever(str(eth.pretty_ip(eth.ip_address)))

実行時に表示されたIPアドレスにアクセスすると、Hello!の文字が表示されました。

マウスを操作する

個人的にCircuitPythonを気に入っている理由の一つに、USB HIDデバイスとして使えるという点が上げられます。MicroPythonにはないので、私がCircuitPython推しなのはこの一点が大きいです。

USB HIDとして使えるようにするには、adafruit_hidモジュールを使用します。code.pyにコードを書く……前に、以下の内容を記述したboot.pyを用意する必要があります。

import usb_hid

usb_hid.enable((usb_hid.Device.MOUSE,))

Webサーバーが動くようになったcode.pyは一旦リネームして退避しておき、あたらしいcode.pyには以下のコードを用意します。

import time
import usb_hid
from adafruit_hid.mouse import Mouse

mouse = 0
while not mouse:
    try:
        mouse = Mouse(usb_hid.devices)
    except:
        pass
    time.sleep(1)

for i in range(0, 8):
    mouse.move(x=20, y=20)
    time.sleep(0.25)

boot.pyの反映はソフトリセットではできないため、code.pyの保存までできたら、ケーブルを抜き差ししてハードリセットします。(macOS Sonomaユーザーは上に書いた再マウントのWorkaroundを忘れずに!)。

抜き差し直後に、マウスカーソルをよく見ると、右下に少しだけカクカクと移動していきます。hidモジュールはクリックなどの操作ももちろんできるので、マクロ的な操作も作ることができます。

マウス移動をWeb APIにする

WIZnetのデバイス初期化、Webサーバー起動、マウス操作を組み合わせて、マウスカーソル移動をWeb APIにしてみます。

マウス操作のテストコードのうち、import timeとfor文以外をコピーして、退避したWebサーバーのコードをcode.pyにリネームし直し、コピーしたコードをcode.pyの最初の方にでも貼りつけておきます。

/にアクセスしたときは、マウスカーソルを操作するボタンを配置したHTMLを返すように変更します。また、マウスカーソルを上下左右に20px移動するAPIとして、/mouse/up・/mouse/down・/mouse/left・/mouse/rightを作成します。

Hello!を返すためのコードのかたまり(4行)を消して、以下のコードを追加します。

indexhtml = """<!DOCTYPE html><html><head><meta name="viewport" content="width=device-width,initial-scale=1"><meta charset="utf-8"><title>Web mouse cursor API</title><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous"><script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script><script>function s(p){fetch(p).then(function(r){return r.text()}).then(function(t){document.getElementById('r').innerText=t;});}</script></head><body><main class="px-3 col-6 mx-auto text-center"><h1 class="mt-2">Web mouse cursor API</h1><div class="container"><div class="row"><button class="btn btn-primary mt-3 mb-3" onclick="s('/mouse/up');">👆</button></div><div class="row d-flex justify-content-between"><button class="btn btn-primary col-5 mt-3 mb-3" onclick="s('/mouse/left');">👈</button><button class="btn btn-primary col-5 mt-3 mb-3" onclick="s('/mouse/right');">👉</button></div><div class="row"><button class="btn btn-primary col-12 mt-3 mb-3" onclick="s('/mouse/down');">👇</button></div></div><div id="r" class="m-3"></div></main></body></html>"""

@server.route("/")
def root(request: Request):
    print("GET /")
    return Response(request, indexhtml, content_type="text/html")

@server.route("/mouse/<direction>")
def move_mouse(request: Request, direction: str):
    print("GET /mouse/%s" % direction)
    if direction == "up":
        mouse.move(x=0, y=-20)
    elif direction == "down":
        mouse.move(x=0, y=20)
    elif direction == "left":
        mouse.move(x=-20, y=0)
    elif direction == "right":
        mouse.move(x=20, y=0)
    else:
        return Response(request, "invalid parameter")
    return Response(request, "moved mouse cursor to %s side" % direction)

マウスの操作APIについては@server.route("/mouse/<direction>")のようにパラメータを変数に取ることができるので、これを活用しました。あとはパラメータに応じてマウスカーソルを移動させて、メッセージを返します。

完成

Web画面を開くと、以下のような画面が表示され、ボタンをクリックするとマウスカーソルが移動します。

スマートフォンなど、デバイスを接続していない別の端末からアクセスして操作するとちょっと楽しいと思います(楽しさの感じ方は人によります!)。

なお、同じネットワーク内にいる他人にアドレスがバレると、いたずらされる可能性があるので、程々に遊んだら片付けるのが安全でしょう。ちなみに私はインターネットに公開してURLをSNSで共有し、10分くらいマウス操作を開放して遊びました。操作している人たちは私のPCのカーソルがどうなっているか見えてもいないのに、なぜかとても楽しそうだったので何よりです。

まとめ

WIZnetのEthernet拡張を使用してWebサーバーを立ち上げて、マウスカーソル移動をWeb API化する例を紹介しました。

Raspberry Pi Picoでネットワーク接続と言えば、現在ではPico Wがあるため、無線LANでいいという考え方もできます。ただ、無線LANが不安定な環境だったり、そもそも無線LANがない環境で使いたい場合などには、やはり有線LANがあると嬉しいですよね。

WIZnetのEthernetモジュールは、ライブラリが揃っていて扱いやすい印象です。今回したCircuitPython以外に、MicroPythonでも使用可能です。難点は、MACアドレスを持っていないので自分で定義が必要な点と、EVB-Picoボードでは通電LEDが目障りになりがちな点でしょうか……。通電LEDは、いざとなればテープや引っ付き虫などで隠してしまっても良さそうです。

今回作成したコードは、諸々整えた状態で以下に公開してあります。

https://github.com/Akkiesoft/akkiesoft-pico/tree/main/CircuitPython/web_mouse

実は、ほぼ同じノリでマクロキーボードAPIというものを以前作っているのですが、こちらで使用していたadafruit_wsgiモジュールでは通信速度が非常に遅く、今回adafruit_httpserverモジュールで書いてみたら高速で転送できるようになったので、マクロキーボードAPIもそのうち書き直したいですね。

Raspberry Pi 5の電源回りを確かめてみる

あっきぃです。

Raspberry Pi 5が出たら多分騒ぎになるのかな……?と思っていた電源周りが、やはり騒ぎになっているようです。

最小要件が5V/3Aなのはまだ良いのですが、推奨要件(USBとか諸々電気を使う場合)の5V/5AのUSB-C PD電源という点がなかなかのクセモノになりそうです。

5V/5Aに対応したPD電源アダプターは世の中にほぼ存在せず(オフィシャル電源アダプターもカスタムPDOというもので実装しているようです)、USB PD3.1のEPRに沿えば5V/5Aの出力が可能になるように見えます(※)。PDについては私も詳しくなく、検索などで追って徐々に理解している段階です。

※参照元はこちら。ただ、他の記述を見つけられず、本当なのかどうか……?
https://www.graniteriverlabs.com/ja-jp/technical-blog/usb-power-delivery-specification-3-1

とは言え、5V/5Aが必須なわけではなく、あくまで推奨の話だと思いたいですよね。もちろん、USB SSDを接続したり、将来的にリリースされるM.2 HATを搭載したりすれば、5V/5Aが必要なのは想像できますが、一旦置いといて、ここでは最小要件の3Aでどこまで問題なく使用できるかを確認してみたいと思います。合わせて、消費電力や、発熱、サーマルスロットリングや電圧低下の起こり具合についても見ていきます。

構成

前回の性能検証の記事を書いた時点で作ればよかったのですが、ドタバタしていましたので、ここで改めて検証の構成を解説します。

日本では技適の取得が完了していないため、検証を行うには、シールドボックスに投入して電波を十分に減衰させるか、「技適未取得機器を用いた実験等の特例制度」を用いて180日間内で検証する方法があります(※)。ユーザー会では、以前よりスイッチサイエンスさんからお借りしているシールドボックスがありますので、シールドボックスに入れて検証を行っています。

※検証後は廃止手続き(電波の発射を防止するために必要な措置を講じる、つまり電源を入れないようにする。額縁に入れて飾るとかでしょうかね?)が必要です。また、技適取得前に入手したものについては技適マークが無いため、今後技適の取得が完了したとしても利用可能にはならない点にも注意が必要です。基本的には技適の取得が完了して国内リセーラーが発売するまで購入は待ちましょう。

シールドボックス内外の接続は以下の図の通りです。

Raspberry Pi 5をシールドボックスに入れてながら使用するための電源・USB・ネットワークなどの接続図

電源は、市販のUSB-AC電源(Anker 735)と、USB PDに対応したケーブルを使用しました。ボックス外は、ワットモニターに接続して消費電力が計測できるようにします。

ネットワークは、ボックス内でUSB3.0-LAN変換アダプターを使用して接続し、ボックス外に出るためのUSB端子に接続します。ただし、ボックスのUSB端子はUSB2.0のため、性能は480Mbps内に制限されます。ボックス外で、Raspberry Pi 4で作ったネットワークブリッジにUSB接続し、LANに接続可能としています。iperf3での実測は200Mbps程度でしたが、ログインしたりテストに必要なパッケージを取得する程度ならなど十分でしょう。もしGbEのテストをするときは、ボックス内にPi4などを追加で投入してテストすれば対応可能です。

ボックスのもう一つのUSB端子には、Rspberry Pi Debug Probeを接続しています。これを用いることで、OS起動前の情報が取得できますし、OS起動後もシリアル通信でログインして操作することが可能です。

まずは小さいヒートシンクだけでSDカード起動してみる

いままでのRaspberry Piなら許された、適当な小さいヒートシンクと、MicroSDカード(Samsung EVO Plus 64GB)の組み合わせで起動してみます。シールドボックスの様子はこちら(Debug Probeが光っていますが、これは端末からの給電のためで、Raspberry Pi 5にはまだ通電していません)。

シールドボックに、MicroSDカードを挿入したRaspberry Pi 5、USB-LANアダプター、Raspberry Pi Debug Probe、USB-AC電源を入れ、接続を済ませた様子。

シリアル接続しながら通電を開始すると、以下のようなメッセージが表示されます。

RPi: BOOTSYS release VERSION:3094eda5 DATE: 2023/09/21 TIME: 17:58:43
BOOTMODE: 0x06 partition 0 build-ts BUILD_TIMESTAMP=1695315523 serial ******** boardrev d04170 stc *******
AON_RESET: 00000003 PM_RSTS 00001000
RP1_BOOT chip ID: 0x20001927
PM_RSTS: 0x00001000
part 00000000 reset_info 00000000
PMIC reset-event 00000000 rtc 00000004 alarm 00000000 enabled 0
uSD voltage 3.3V
Initialising SDRAM 'Micron' 32Gb x2 total-size: 64 Gbit 4267
DDR 4267 1 0 64 152
RP1_BOOT chip ID: 0x20001927

RP1_BOOT chip ID: 0x20001927
RP1_BOOT: fw size 25968
PCI2 init
PCI2 reset
PCIe scan 00001de4:00000001
RP1_CHIP_INFO 20001927

RPi: BOOTLOADER release VERSION:3094eda5 DATE: 2023/09/21 TIME: 17:58:43
BOOTMODE: 0x06 partition 0 build-ts BUILD_TIMESTAMP=1695315523 serial ******** boardrev d04170 stc *******
AON_RESET: 00000003 PM_RSTS 00001000
 status
USB_PD CONFIG 0 41
Boot mode: SD (01) order f4
SD HOST: 200000000 CTL0: 0x00800f02 BUS: 400000 Hz actual: 390625 HZ div: 512 (256) status: 0x1fff0000 delay: 276
SD HOST: 200000000 CTL0: 0x00800f02 BUS: 400000 Hz actual: 390625 HZ div: 512 (256) status: 0x1fff0000 delay: 276
OCR c0ff8000 [313]
CID: 001b534d454331533530d5186366a166
CSD: 400e00325b590001dd7f7f800a400000
SD: bus-width: 4 spec: 2 SCR: 0xeeeeeefe 0xeeeeefef
SD CMD: 0x333a0010 (51) 0x59b40000 0x1fff0206
Failed to open device: 'sdcard' (cmd 333a0010 status 1fff0206)
Retry SD 1
SD HOST: 200000000 CTL0: 0x00800000 BUS: 400000 Hz actual: 390625 HZ div: 512 (256) status: 0x1fff0000 delay: 276
SD HOST: 200000000 CTL0: 0x00800f00 BUS: 400000 Hz actual: 390625 HZ div: 512 (256) status: 0x1fff0000 delay: 276
OCR c0ff8000 [2]
CID: 001b534d454331533530d5186366a166
CSD: 400e00325b590001dd7f7f800a400000
SD: bus-width: 4 spec: 2 SCR: 0x02058083 0x00000000
SD HOST: 200000000 CTL0: 0x00800f04 BUS: 50000000 Hz actual: 50000000 HZ div: 4 (2) status: 0x1fff0000 delay: 2
MBR: 0x00002000, 1048576 type: 0x0c
MBR: 0x00102000,124116992 type: 0x83
MBR: 0x00000000,       0 type: 0x00
MBR: 0x00000000,       0 type: 0x00
Trying partition: 0
type: 32 lba: 8192 'mkfs.fat' ' bootfs     ' clusters 261116 (4)
rsc 32 fat-sectors 2040 root dir cluster 2 sectors 0 entries 0
FAT32 clusters 261116
[sdcard] autoboot.txt not found
Trying partition: 0
type: 32 lba: 8192 'mkfs.fat' ' bootfs     ' clusters 261116 (4)
rsc 32 fat-sectors 2040 root dir cluster 2 sectors 0 entries 0
FAT32 clusters 261116
Read config.txt bytes     1229 hnd 0xfef7
[sdcard] pieeprom.upd not found
usb_max_current_enable default 0 max-current 3000
Read bcm2712-rpi-5-b.dtb bytes    71797 hnd 0xcb56
dt-match: compatible: raspberrypi,5-model-b match: brcm,bcm2712
dt-match: compatible: brcm,bcm2712 match: brcm,bcm2712
PM_RSTS 00001000
Selecting USB low current limit

Raspberry Pi 5内の各デバイスの初期化に関するメッセージや、ブートデバイスを探して起動しようとするメッセージが見られます。そして最後の「Selecting USB low current limit」が、5V/5A電源を検出できず、USBポートの供給は600mAまでとして起動しますよ、というメッセージですね。

起動中にワットモニターが表示した消費電力は、3〜6Wの範囲でした。

このあとのシリアルの出力はOSに変わり、少しするとOSのログインプロンプトが出力されます。

NOTICE:  BL31: v2.6(release):v2.6-239-g2a9ede0bd
NOTICE:  BL31: Built : 14:26:57, Jun 22 2023
[    0.902716] spi-bcm2835 107d004000.spi: no tx-dma configuration found - not using dma mode

Debian GNU/Linux 12 pios5 ttyAMA10

pios5 login: 

起動が完了したあとの消費電力は3.3W〜3.5Wくらいで安定しました。つまり0.66Aくらいですね。また、しばし放置してから vcgencmd measure_temp コマンドでCPU温度を取得すると56度ほどでした。空気がこもるシールドボックス内での測定のため、通常の室内などではもう少し低く推移する可能性が考えられます。

yes >/dev/null & を4つ投入して、CPUを全部100%にしてみます。消費電力を観察しつつCPU温度も確認したところ、10Wまで消費電力が上昇しますが、CPU温度が85度に達したところで、消費電力が7.5〜8Wくらいまで下がりました。サーマルスロットリングが働いたことがわかります。また、電圧低下も時々発生していました。アイドル時の56度からyesコマンドを実行してサーマルスロットリングが働くまでの時間は、40秒ほどでした。

Alasdair Allan氏(Raspberry Pi Ltdの方)が公開している、スロットルを確認するスクリプトでも、電圧低下・スロットル・周波数のキャッピングが発生したことが確認できました。

https://gist.github.com/aallan/0b03f5dcc65756dde6045c6e96c26459

$ ./throttled.sh 
Status: 0xf0008
Undervolted:
   Now: NO
   Run: YES
Throttled:
   Now: NO
   Run: YES
Frequency Capped:
   Now: NO
   Run: YES

ヒートシンクのみ、SDカードブートの環境では、アイドル時の消費電力3.3W・CPU温度56度、負荷をかけると消費電力10W・CPU温度は最大85度(以降はサーマルスロットリングで温度維持を優先した周波数以下などが発生)となりました。

小さいヒートシンクにファンを加えてSDカード起動

本来はオフィシャルのケースもしくはActive Coolerがあればよかったのですが、あいにくこちらのサンプルは無いため、先述の小さいヒートシンクで対応しています。ここにPimoroniのFan Shimを追加して、ヒートシンクを空冷しながら動かすとどうなるか確かめます。

Pimoroni Fan Shimを接続したRapberry Pi

まずはアイドル状態。ファンの動作が増えるため、消費電力は3.8W前後に変化します。一方、CPU温度は40度前後で安定しました。

続けてyesコマンドで負荷をかけます。1分ほどかけて65度近くまで上昇しますが、その後は上昇が緩やかになります。2分程で電圧低下とスロットルが検知されますが時々瞬間的に起こるだけのようで、周波数のキャップは発生せずに温度上昇を緩やかに続け、最終的に70度で一旦安定しました。消費電力は10W前後を維持していたため、スロットリングによる性能低下は防げていそうです。おそらく、これ以降は続けてもシールドボックス内の温度上昇次第になりそうなので負荷かけは停止しました。

ヒートシンク+ファンと、SDカードブートの環境では、アイドル時の消費電力3.8W・CPU温度40度、負荷をかけると消費電力10W・CPU温度は70度前後となりました。

ヒートシンク+ファンでUSB SSDブート

USB SSDブートにするとどうなるか確かめます。NVMe SSDをUSBに変換するケースに入れたものをUSB3.0ポートに接続して起動します。M.2 HATが発売されたら、USB3.0ではなく直接PCI Expressで接続できるようになりますね。USBとPCIeでの速度の違いを確かめたりするのが楽しみです。

MicroSDの代わりにNVMe SSDをUSB変換したデバイスから起動しようとするRaspberry Pi 5

通電すると、シリアル通信で以下のメッセージが表示されました。

***
USB boot requires high current (5 volt 5 amp) power supply.
To disable this check set usb_max_current_enable=1 in config.txt
or press the power button to temporarily enable usb_max_current_enable
and continue booting.
See https://rptl.io/rpi5-power-supply-info for more information
***

USBブートの場合、3Aのモードでの起動はサポートされないため、以下のいずれかの対応が必要になります。

  • 5V/5Aの電源を接続する(Raspberry Pi 公式の推奨)
  • usb_max_current_enable=1 を /boot/config.txt に投入して無視する
  • 電源ボタンを1回押して、今回だけ無視する

シールドボックスを開けてボタンを押すのはよろしく無いので、一旦電源を切り、config.txtに設定を投入しました。再度起動すると、起動時のメッセージに、以下のようにメッセージが表示され、無理やりUSB SSDブートが開始します。ただ、やはり無理矢理なので、起動時にさっそく電圧低下が表示されてしまいました。

usb_max_current_enable forced to 1
(中略)
[    6.112188] hwmon hwmon2: Undervoltage detected!

Debian GNU/Linux 12 pios5 ttyAMA10

pios5 login: 

起動が終わってアイドル状態の消費電力は5.3Wほどでした。ここでやっと1Aを超えましたね。CPU温度はファン付きのため38.9度前後でした(設定変更などでボックスを開け閉めしたため下がった様子)。

yesコマンドで負荷をかけます。すると、消費電力は先程より低く9W前後、温度上昇もやや緩やかでした。先程のスクリプトを実行すると、電圧低下とスロットルがオンになりっぱなしになっていました。周波数キャップにはなっていないものの、さすがに電圧不足が出たままになってしまうようです。

./throttled.sh 
Status: 0x50005
Undervolted:
   Now: YES
   Run: YES
Throttled:
   Now: YES
   Run: YES
Frequency Capped:
   Now: NO
   Run: NO

yesコマンドを停止すると、電圧低下もスロットルもすぐにオフに変化しました。

5Aを供給していない環境で、警告を無視してUSBブートした環境では、負荷が高い処理をかけると電圧低下になりやすいことがわかりました。

動作自体が極端に不安定になるわけではないですが、aptでパッケージを入れる程度でも電圧低下が発生するため、USB SSDブートをしたい場合は公式の電源(5V/5A電源)が必須と言えそうです。

まとめ

MicroSDカードから起動する場合は、5V/3A出力の電源アダプターでもおおむね問題なく動作しました。

USB SSDから起動する場合は、3Aで無理やり起動すること自体は可能ですが、電圧低下が発生しやすいため、公式の推奨通り公式の電源アダプターが必要そうです。

消費電力は、アイドル時であれば3.3Wなど、それほど気になる消費電力ではありませんでした。また、負荷をかけてもSDカード環境であれば10W(2A)程度などで済むようでした。

また、温度に関しては、ヒートシンクのみであればおそらく60度以下で動作します。むき出しの状態かつ常に手に握りしめながら使うなどしなければおそらく問題はありません。ただ、負荷が大きくかかり続ける環境等では厳しくなる可能性があるため、安定動作させるにはファンがあると安心でしょう。

もちろん、カメラなどのデバイス、GPIOやDSI接続などのディスプレイや、センサーなどのモジュールなどを搭載した場合、また、ソフトウェアでシステムにかかる負荷などによっては、5V3Aでは電圧が不足するなどの可能性が考えられます。これらを考慮すると公式の電源アダプターが必要になる場合も考えられそうです。USBに関しては、セルフパワータイプのハブを使ったらどうなるかなどは検証してみても良いかもしれませんね。

あともうひとつ、Raspberry Pi 4と同様にブートローダーEEPROMイメージをアップデートできる仕組みがあるため、今後の改良次第では電源周りにも挙動の改善が見られる可能性はあるかもしれません。

https://github.com/raspberrypi/rpi-eeprom

公式の電源アダプターと言われても……PSEマークの取得は?

電源アダプターにも技適のように、PSEマークという認証マークが存在します。このマークが無ければ国内での販売はできません。

これまで歴代のRaspberry Piにも公式の電源アダプターが存在しましたが、残念ながらPSEマークを取得したものは存在しません。代わりに、リセーラー各社が独自の電源アダプターを用意、販売してきました。今回こそは公式のものが発売されないとまずそうに見えますが、果たして発売されるでしょうか……?個人的には、ある意味で技適の件よりもどきどきハラハラしながら見守る次第です。

Raspberry Pi 5 実機レビュー(ベンチマーク編)

あっきぃです。一つ前の記事では外観の変化についてレビューをしました。

こちらの記事では実際に動かして性能を確かめていきます。

いつものとおり、スイッチサイエンスさんからお借りしている電波暗箱におさめて検証をしています。

今回、UART機能を活用すべく、暗箱内のUSB配線は、ラップトップを通じてインターネットに出るためのUSB-LANと、コンソール作業用のDebug Probeを接続して、作業を実施しました。

UnixBench

Raspberry Pi 5のUnixBenchの結果は以下のとおりです。起動OSストレージはUSB SSDを使用してUSBからブートしています。なお、冷却についてはヒートシンクとファンを使用していますが、電波暗箱内に熱がこもってしまうため、冷却についてもう少ししっかり対応すれば結果が変化する可能性がある点についてはご了承ください。

------------------------------------------------------------------------
Benchmark Run: 木  9月 28 2023 14:21:25 - 14:49:24
4 CPUs in system; running 1 parallel copy of tests

Dhrystone 2 using register variables       35871623.6 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                     7000.8 MWIPS (9.9 s, 7 samples)
Execl Throughput                               3747.6 lps   (30.0 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks        488963.5 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks          138385.0 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks       1100853.5 KBps  (30.0 s, 2 samples)
Pipe Throughput                              414920.4 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                  88485.3 lps   (10.0 s, 7 samples)
Process Creation                               6307.9 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                   8814.3 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                   2210.1 lpm   (60.0 s, 2 samples)
System Call Overhead                         302151.7 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0   35871623.6   3073.8
Double-Precision Whetstone                       55.0       7000.8   1272.9
Execl Throughput                                 43.0       3747.6    871.5
File Copy 1024 bufsize 2000 maxblocks          3960.0     488963.5   1234.8
File Copy 256 bufsize 500 maxblocks            1655.0     138385.0    836.2
File Copy 4096 bufsize 8000 maxblocks          5800.0    1100853.5   1898.0
Pipe Throughput                               12440.0     414920.4    333.5
Pipe-based Context Switching                   4000.0      88485.3    221.2
Process Creation                                126.0       6307.9    500.6
Shell Scripts (1 concurrent)                     42.4       8814.3   2078.8
Shell Scripts (8 concurrent)                      6.0       2210.1   3683.5
System Call Overhead                          15000.0     302151.7    201.4
                                                                   ========
System Benchmarks Index Score                                         922.7

------------------------------------------------------------------------
Benchmark Run: 木  9月 28 2023 14:49:24 - 15:17:22
4 CPUs in system; running 4 parallel copies of tests

Dhrystone 2 using register variables      142820987.7 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                    27995.6 MWIPS (9.9 s, 7 samples)
Execl Throughput                              10236.0 lps   (29.7 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks       1387766.5 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks          543428.5 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks       1328002.9 KBps  (30.0 s, 2 samples)
Pipe Throughput                             1656919.6 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                 312064.0 lps   (10.0 s, 7 samples)
Process Creation                              14014.6 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                  17045.5 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                   2217.8 lpm   (60.1 s, 2 samples)
System Call Overhead                        1208120.9 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0  142820987.7  12238.3
Double-Precision Whetstone                       55.0      27995.6   5090.1
Execl Throughput                                 43.0      10236.0   2380.5
File Copy 1024 bufsize 2000 maxblocks          3960.0    1387766.5   3504.5
File Copy 256 bufsize 500 maxblocks            1655.0     543428.5   3283.6
File Copy 4096 bufsize 8000 maxblocks          5800.0    1328002.9   2289.7
Pipe Throughput                               12440.0    1656919.6   1331.9
Pipe-based Context Switching                   4000.0     312064.0    780.2
Process Creation                                126.0      14014.6   1112.3
Shell Scripts (1 concurrent)                     42.4      17045.5   4020.2
Shell Scripts (8 concurrent)                      6.0       2217.8   3696.4
System Call Overhead                          15000.0    1208120.9    805.4
                                                                   ========
System Benchmarks Index Score                                        2479.7

以前Raspberry Pi 4で取得した際は1パラレルの結果が320、パラレルの結果が851でしたので、いずれも3倍近い性能向上が確認できました。

OpenSSLテスト

Raspberry Pi 5では、CPUでAES暗号化の機能が搭載され、OpenSSLのパフォーマンスが大幅に向上しています。

$ lscpu 
Architecture:            aarch64
  CPU op-mode(s):        32-bit, 64-bit
  Byte Order:            Little Endian
CPU(s):                  4
  On-line CPU(s) list:   0-3
Vendor ID:               ARM
  Model name:            Cortex-A76
    Model:               1
    Thread(s) per core:  1
    Core(s) per cluster: 4
    Socket(s):           -
    Cluster(s):          1
    Stepping:            r4p1
    CPU(s) scaling MHz:  42%
    CPU max MHz:         2400.0000
    CPU min MHz:         1000.0000
    BogoMIPS:            108.00
    Flags:               fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp
                          asimdhp cpuid asimdrdm lrcpc dcpop asimddp
Vulnerabilities:         
  Gather data sampling:  Not affected
  Itlb multihit:         Not affected
  L1tf:                  Not affected
  Mds:                   Not affected
  Meltdown:              Not affected
  Mmio stale data:       Not affected
  Retbleed:              Not affected
  Spec rstack overflow:  Not affected
  Spec store bypass:     Mitigation; Speculative Store Bypass disabled via prctl
  Spectre v1:            Mitigation; __user pointer sanitization
  Spectre v2:            Mitigation; CSV2, BHB
  Srbds:                 Not affected
  Tsx async abort:       Not affected

UnixBenchと同様ヒートシンクとファンで冷却しながら取得した結果は以下のとおりです。こちらはPi 4とPi 5の両方で取得しました。

Raspberry Pi 4
version: 3.0.9
built on: Tue Jun 27 11:03:08 2023 UTC
options: bn(64,64)
compiler: gcc -fPIC -pthread -Wa,--noexecstack -Wall -fzero-call-used-regs=used-gpr -DOPENSSL_TLS_SECURITY_LEVEL=2 -Wa,--noexecstack -g -O2 -ffile-prefix-map=/build/openssl-3EYFh
e/openssl-3.0.9=. -fstack-protector-strong -Wformat -Werror=format-security -DOPENSSL_USE_NODELETE -DOPENSSL_PIC -DOPENSSL_BUILDING_OPENSSL -DNDEBUG -Wdate-time -D_FORTIFY_SOURCE
=2
CPUINFO: OPENSSL_armcap=0x81
The 'numbers' are in 1000s of bytes per second processed.
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes  16384 bytes
md5              20060.20k    63573.53k   151300.61k   235601.92k   281542.66k   285196.29k
sha1             17071.09k    54337.88k   126238.55k   191955.97k   226500.61k   229244.93k
rmd160           14590.26k    44724.57k    98697.22k   142409.73k   163799.04k   165472.94k
sha256           16343.43k    47364.39k   104071.34k   147695.62k   169000.96k   170732.20k
sha512           13388.09k    53628.05k   115350.95k   191555.93k   240074.75k   243886.76k
hmac(md5)        12954.35k    44555.26k   121571.75k   215362.56k   277427.54k   283060.91k
des-ede3         13872.51k    14476.86k    14628.78k    14671.19k    14682.79k    14685.53k
aes-128-cbc      45137.76k    48874.45k    50187.86k    50521.77k    50604.71k    50621.10k
aes-192-cbc      38315.12k    40966.76k    42086.74k    42387.80k    42289.83k    42303.49k
aes-256-cbc      33279.44k    35311.38k    36007.17k    36201.13k    36255.06k    36252.33k
camellia-128-cbc    55411.08k    65619.88k    68665.69k    69651.80k    69935.10k    69905.07k
camellia-192-cbc    44774.70k    51409.24k    53273.34k    53868.54k    54031.70k    54012.59k
camellia-256-cbc    44913.11k    51417.77k    53275.73k    53867.86k    54037.16k    54018.05k
ghash            90443.33k   123293.55k   138805.08k   143634.09k   144586.07k   140683.95k
rand              2817.99k    10049.37k    30343.83k    63935.95k    95414.66k    99422.10k
Raspberry Pi 5
version: 3.0.9
built on: Tue Jun 27 11:03:08 2023 UTC
options: bn(64,64)
compiler: gcc -fPIC -pthread -Wa,--noexecstack -Wall -fzero-call-used-regs=used-gpr -DOPENSSL_TLS_SECURITY_LEVEL=2 -Wa,--noexecstack -g -O2 -ffile-prefix-map=/build/openssl-3EYFhe/openssl-3.0.9=. -fstack-protector-strong -Wformat -Werror=format-security -DOPENSSL_USE_NODELETE -DOPENSSL_PIC -DOPENSSL_BUILDING_OPENSSL -DNDEBUG -Wdate-time -D_FORTIFY_SOURCE=2
CPUINFO: OPENSSL_armcap=0xbd
The 'numbers' are in 1000s of bytes per second processed.
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes  16384 bytes
md5              38876.14k   112459.26k   244872.99k   343889.92k   388713.13k   392407.72k
sha1             54259.39k   195820.84k   560858.54k  1046074.03k  1403792.04k  1439159.64k
rmd160           32580.90k    87789.51k   182199.38k   255504.10k   286324.05k   288484.01k
sha256           52860.18k   192068.07k   534115.67k  1035979.43k  1447362.56k  1489928.19k
sha512           25557.98k   107456.55k   206635.78k   323940.35k   388903.56k   393560.06k
hmac(md5)        22670.27k    75366.53k   197372.84k   316821.16k   383109.80k   389403.99k
des-ede3         23404.53k    23946.99k    24163.75k    24196.10k    24207.36k    24210.09k
aes-128-cbc     673310.63k  1340616.36k  1732335.62k  1856858.45k  1909036.37k  1913978.88k
aes-192-cbc     628817.58k  1197309.53k  1475447.38k  1547643.22k  1592404.65k  1595796.14k
aes-256-cbc     622174.58k  1062045.76k  1278014.63k  1339694.42k  1365753.86k  1368260.61k
camellia-128-cbc   101635.74k   109795.29k   112098.65k   113008.98k   113186.13k   113339.05k
camellia-192-cbc    80806.49k    85497.51k    86893.48k    87367.68k    87542.44k    87577.94k
camellia-256-cbc    79942.40k    85506.88k    86894.85k    87393.28k    87536.98k    87556.10k
ghash           444674.42k  1505138.90k  3199533.65k  4460456.96k  5020199.59k  5068035.41k
rand             11319.77k    42223.40k   161315.61k   547445.78k  1698195.69k

たとえばaes-256-cbcを抜き出して比較してみると、最大37倍も処理できるようになっていることがわかります。

type                    16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes  16384 bytes
(Pi4) aes-256-cbc      33279.44k    35311.38k    36007.17k    36201.13k    36255.06k    36252.33k
(Pi5) aes-256-cbc     622174.58k  1062045.76k  1278014.63k  1339694.42k  1365753.86k  1368260.61k
Pi5/Pi4                    18.70        30.08        35.49        37.01        37.67        37.74

AESとは関係しない項目、たとえばsha512でも、1.6〜2倍の性能向上が確認できます。

type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes  16384 bytes
(Pi4) sha512    13388.09k    53628.05k   115350.95k   191555.93k   240074.75k   243886.76k
(Pi5) sha512    25557.98k   107456.55k   206635.78k   323940.35k   388903.56k   393560.06k
Pi5/Pi4             1.91         2.00         1.79         1.69         1.62         1.61

高速化したMicroSDスロットのベンチマーク

MicroSDカードスロットはSDR104モードに対応したため、理論値では104MB/sの転送に対応します。このため、最近の一般的なMicroSDカードであれば高速に起動できるようになりました。

MicroSDカードを使用してPi4・Pi5それぞれでOSを起動し、hdparmコマンドで読み込み性能を確認した結果、Pi4は43.9MB/s、Pi5は89.4MB/sとなりました。理論値にはやや届きませんでしたが、Pi4に比べて約2倍の性能が出ていることがわかります。

ddコマンドによるシーケンシャルの書き込み性能は、Pi4が27.5MB/s、Pi5が35.1MB/sとなりました。それほど差が出ていないように見えますが、MicroSDカードは一般的に読み込みは早く、書き込みはそれほど早くないため、MicroSDカードの書き込み性能が先に限界にきている可能性が考えられます。WindowsマシンでCrystalDiskMarkを用いた書き込みテストでも38MB/sだったため、概ねこのあたりが上限のようです。

USB3.0ポートも高速化。ただし電源周りに注意(USBを使わないときも)

USB3.0ポートは、Raspberry Pi 4ではVL805 USBハブチップによって帯域を共有したものでしたが、Raspbery Pi 5では、RP1チップによって2つのUSB3.0+USB2.0ポートが提供されるようになったため、どちらのUSB3.0ポートを使用しても性能を引き出すことが可能になりました。

同時使用のテストではなく1つのSSDのみ接続してのテストですが、こちらもddとhdparmで測定した結果、ddによるシーケンシャルの書き込み性能は、Pi 4では約135MB/s、Pi 5では約328MB/sとなりました。また、hdparmによるシーケンシャルの読み込みテストは、Pi4では約200MB/s、Pi 5では約333MB/sとなりました。いずれも性能の向上が確認できました。

なお、USBの電源を十分に供給するには、オフィシャルの電源アダプターを用いて5V/5Aの電力供給をすることが推奨されています。USBストレージから起動しようとすると、以下のメッセージが表示されます。

***
USB boot requires high current (5 volt 5 amp) power supply.
To disable this check set usb_max_current_enable=1 in config.txt
or press the power button to temporarily enable usb_max_current_enable
and continue booting.
See https://rptl.io/rpi5-power-supply-info for more information
***

市販のUSB-PD電源では5V5Aを出力できるものが少ないため、オフィシャルの電源アダプターのPSE取得を待ってそれを用いるか、メッセージを無視して電源ボタンを押すことで一時的に無視して起動するか、usb_max_current_enable=1を/boot/config.txtに投入して恒久的に無視するかの選択が必要になります。

性能を活かすための電源と冷却選び

一般的なUSB PD電源は5Vの場合3Aまでの出力のため、これをRaspberry Pi 5で使用すると、USBデバイスへの供給が600mAに制限されたり、電力が不足する可能性があります。よって、オフィシャルの電源も必要な機能性があります。ただ、PSEの取得問題が起こるので、これは悩ましい問題かもしれません。幸い(?)日本はRaspberry Pi 5のいわゆる技適取得で他国より発売が遅れるため、待っている間に先に利用できる国のユーザーがどう対処するかの知見を得ることができるでしょう……。

また、発熱も高性能化に伴って増加し、オフィシャルのケースにはファンが標準添付され、オフィシャルのヒートシンク+ファンも発売されます。常に負荷をかけるような使い方をする場合はファンの利用も考慮すると良いでしょう。

日本での発売について

日本での発売は、いわゆる技適の取得後、認定リセーラーとの調整を経てからとなります。詳しくはスイッチサイエンスさん、KSYさんの情報を確認ください。

https://prtimes.jp/main/html/rd/p/000000137.000064534.html

https://raspberry-pi.ksyic.com/news/page/nwp.id/130