Raspberry Pi Compute Module 5を買ったのでレビュー

Raspberry Pi Advent Calendar 2024の14日目です。今日はこちらのブログに投稿です。

先月末に発売されたRaspberry Pi Compute Module 5を買ってみたのでレビューしていきます。

最初に言うと、CM5は技適がまだなので、今回は電波暗箱で検証しています。技適未取得機器を用いた実験等の特例制度を申請して検証するのもアリだと思いますが、180日ごとに検証内容を変えてまで、技適マークがつくのをまたずに買うものかどうかは各自で判断が必要そうです。わたしの場合は、暗箱である程度検証が済んだら、無線チップはヒートガンで炙って剥がしてしまおうかと考えています。

Seeedさんでポチポチ

今回は、先に販売ページができてたSeeedさんで購入しました。ついでにSeeed XIAO RP2350が欲しかったのもあります。さらについででUSBハブもポチり。

CM5は、4GB RAM・32GB eMMC・無線ありモデルです。Dev Kitに含まれているのと同モデルのため、これがCM5の標準的なモデルに当たりのではないかと思っています。Pimoroniでは8GB RAMモデルなど別のモデルも展開されていますが、今のところ”無線なし”が売られているところは確認していません。よって、日本では現状は技適がないなりの対応が求められます。

IOボードは、購入時点では売られていなかったので、一旦はCM4のIOボードを流用する方向にしました。

しかし、もう少し待てば、PimoroniからIOボードとかも含めて一式が発売されていたので、焦らないで待てばよかったなあと後悔しました。あと、Seeedからの配送は2週間ほどかかり、Pimoroniで購入した勢の方が先に受け取っていたようなので、それもまた悔しみ。

外観とか

表面は冒頭の画像の通り。右上には、Pi5で登場した容量の表記があります。CM5はeMMCの概念もあるので、列は2つです。16GBはCM5のリリースでも触れられていましたが、シルク印刷は今のところ略されている模様。Pi 5で増えたRP1がどうなるか気になっていましたが、ちゃんと搭載されましたね。このおかげで、CM5でもUSB3.0が標準で使えるようになったのはいい話です。

裏面。CM4と比べると、チップ部品が増えた印象です。そして、部品の斜め配置も少し増えたなと言う感じです。eMMCはこちらに移動しました。CM5ではRP1チップが増えたので、追いやられた感がありますね。認証は、FCCIDとIC、KC IDの3つが見えます。PIPで確認するとFCC、CE、イスラエルとシンガポールしか確認できませんでしたが、KC IDって韓国だったような。

実際にCM4と並べて比較。下がCM5です。上のCM4がLite版なせいもあるとは思いますが、密度が違いますね。

表面もついでに比較。

側面。Pi 5では側面の加工が改善されてバリがなくなりましたが、CM5でも同じく側面がきれいな処理になりました。以前のモデルでは、届いてたらまず紙やすりで側面を削ったりしていましたが、そんな作業とはお別れです。

GbEのトランシーバーチップは、CM4から変わらず、BCM54210PEが採用されています。

無線チップも、RPi-RM0 Cモジュールが搭載されています。じゃあ技適とか問題ないんじゃないのって思うかもしれませんが、アンテナがCM5側にあるため、アンテナと込みで技適の取り直しが必要になると推測されます。これがRM2みたいに、アンテナも込みのモジュールだったら関係なくなるんじゃないかと思うのですが、そうはなってないし、推測の話をしてもしょうがないので忘れます。

ブートローダーEEPROMも、さりげなく裏面に移動していたので、いちおう。

さわるぞ!!

というわけでやっと本編(?)。実際に触っていきます。いつもJAMの開催スペースを提供くださっているミドクラさんから借用中の電波暗箱を活用させていただきました。

箱内の構成は、スイッチサイエンスさんの5A対応電源と、D-Sub9端子経由で有線LANで接続をします。今回使用したのはIOボードはWaveShareのCM4-IO-BASE-Bと、CM4-NANO-Bの2種類。前者はNVMe SSDの接続も含めた検証用で、校舎はeMMCの書き込み管理およびeMMCからブートして試験する用にしました。

CM4-NANO-Bを使用してeMMCに書き込む準備をした状態。箱の右側にあるUSB端子を経由してMacに接続します。有線LANはいらないですが、その後起動することも考えて一応。IOボードのBOOTスイッチをオンにしたら箱を閉じます。

eMMCへのRaspberry Pi OSの書き込み

eMMCにRaspberry Pi OSを書き込むには、usbbootリポジトリのrpibootコマンドを使用します。コンパイルの手順はREADMEに従ってください。

https://github.com/raspberrypi/usbboot

rpibootコマンドのコンパイルができたら、次のコマンドを実行して、USBケーブルを接続します。箱の外から伸ばしたUSBケーブルをMacに接続します。しばらくすると、eMMCストレージが見えるようになるので、後はRaspberry Pi Imagerで書き込みを行います。

$ sudo ./rpiboot -d mass-storage-gadget64

起動!

一度MacからUSBケーブルを抜いて箱を開き、BOOTスイッチを戻したら、電源ケーブルにつなぎ替えて箱を閉じます。箱の外のコンセントを接続して、Raspberry Piを起動します。

起動後は普通にSSHして、いつも通りに使えます。

IOボードの互換性?

今回使用しているIOボードは、いずれもCM4向けのボードです。USB3.0ポートはないため、USB3.0の性能を得ることはできませんが、USB2.0ポート、HDMIポート、LANポートは使えるようでした。LANはSSHで、HDMIはUSBキャプチャボードで、USB2.0ポートは適当なCircuitPythonなPicoボードで確認できました。カメラポートとかも確認すべきですが、今日は一旦割愛ということで。まあ、一通り使えていそうです。

USBキャプチャから得られたデスクトップ多少日本語化とかの調整をした後だけどなにもない

HSMIキャプチャの接続の様子。

NVMeのことを忘れていますが、これはIOボードをチェンジする必要があるので後述します。

eMMCの読み書き速度をみてみる

CM4では、eMMCの速度はややいまいちな印象でした。実際、ベンチマークを取ってみると、100MB/s以下と、もっさりめです。ちなみにベンチマークは https://pibenchmarks.com/ のテストを使用しました。

$ sudo curl https://raw.githubusercontent.com/TheRemote/PiBenchmarks/master/Storage.sh | sudo bash
(略)
MMC Type: eMMC v4 (Embedded) - Manufacturer: Samsung/SanDisk/LG - Model: AJTD4R - Size: 14.3G
(略)
     Category                  Test                      Result     
HDParm                    Disk Read                 75.54 MB/sec             
HDParm                    Cached Disk Read          76.34 MB/sec             
DD                        Disk Write                32.1 MB/s                
FIO                       4k random read            7922 IOPS (31690 KB/s)   
FIO                       4k random write           7449 IOPS (29799 KB/s)   
IOZone                    4k read                   18428 KB/s               
IOZone                    4k write                  22075 KB/s               
IOZone                    4k random read            20386 KB/s               
IOZone                    4k random write           20903 KB/s               

                          Score: 4701

では、CM5ではどうかと言うと……早い!!シーケンシャルリードは300MB/s、シーケンシャルライトは100MB/sと、普通に使うぶんにはまず困らない速度になりました。ランダム性能も100MB/s前後で悪くないですね。これは意外です。

$ sudo curl https://raw.githubusercontent.com/TheRemote/PiBenchmarks/master/Storage.sh | sudo bash
(略)
MMC Type: eMMC v4 (Embedded) - Manufacturer: Samsung/SanDisk/LG - Model: BJTD4R - Size: 28.6G
(略)
     Category                  Test                      Result     
HDParm                    Disk Read                 313.89 MB/sec            
HDParm                    Cached Disk Read          227.71 MB/sec            
DD                        Disk Write                109 MB/s                 
FIO                       4k random read            23594 IOPS (94377 KB/s)  
FIO                       4k random write           25006 IOPS (100024 KB/s) 
IOZone                    4k read                   45470 KB/s               
IOZone                    4k write                  69301 KB/s               
IOZone                    4k random read            44893 KB/s               
IOZone                    4k random write           56323 KB/s               

                          Score: 13136

NVMeはどう?

IOボードをCM4-IO-BASE-Bにチェンジして、NVMeの性能をみていきます。Jeffがすでにテスト済みらしいのですが、CM4向けのIOボードでもPCIe3.0x1接続でNVMeを使えるらしく、追試ということにして私も試してみました。

ちなみに、デフォルトのブート順はeMMCが先になっているので、EEPROMの設定を開いて、eMMCの順番を後ろにしておきました。

$ sudo rpi-eeprom-config -e

# Default BOOT_ORDER for provisioning
# NVMe -> USB -> SD -> Network
BOOT_ORDER=0xf2146

これでNVMeからブートするようになりましたので、PCIeのスピードを3.0に変更します。

$ sudo vi /boot/firmware/config.txt

[cm5]
dtparam=pciex1_gen=3

これで再起動して、ベンチマークを取ってみましょう。結果は……あれ、なんかリードが妙に遅いですね。ライトは早いんですけど。あと、ランダムリードも早いので、シーケンシャルリードだけなんかおかしいですね。SSSTC CL1-3D256-Q11 256GBを使いましたが、こいつが悪いのかしら。

     Category                  Test                      Result     
HDParm                    Disk Read                 156.65 MB/sec            
HDParm                    Cached Disk Read          125.58 MB/sec            
DD                        Disk Write                594 MB/s                 
FIO                       4k random read            155151 IOPS (620606 KB/s)
FIO                       4k random write           88658 IOPS (354632 KB/s) 
IOZone                    4k read                   243558 KB/s              
IOZone                    4k write                  198683 KB/s              
IOZone                    4k random read            62502 KB/s               
IOZone                    4k random write           232042 KB/s              

                          Score: 51281

というわけで、Samsung PM991a 256GBに変更して再テスト。結果は以下の通り、PCIe3.0x1っぽいスピード感を得られていました。ふぅ〜よかった。

     Category                  Test                      Result     
HDParm                    Disk Read                 748.64 MB/sec            
HDParm                    Cached Disk Read          664.08 MB/sec            
DD                        Disk Write                493 MB/s                 
FIO                       4k random read            208979 IOPS (835918 KB/s)
FIO                       4k random write           93090 IOPS (372363 KB/s) 
IOZone                    4k read                   208154 KB/s              
IOZone                    4k write                  173558 KB/s              
IOZone                    4k random read            57892 KB/s               
IOZone                    4k random write           193770 KB/s              

                          Score: 48226

既存環境でCM5をブートするときはそのままではUSB2.0が使えないので注意

既存環境でブートしてUSBデバイスを試そうとしたら、デバイスが認識しなくて「おや?」となりました。IOボードの互換の問題かと思ったらそうではなく、CM4ではotg_modeの設定を投入する必要があったのと同じように、CM5ではdwc2の設定が必要になるようでした。eMMCに導入した環境のconfig.txtには含まれていたので、古いバージョンからのアップデートでは自動挿入されないようです。それもそうか。

というわけで、既存環境にも設定を投入したところ、無事にUSB2.0ポートが認識するようになりました

[cm4]
otg_mode=1

# [cm4]と[all]の間あたりに差し込んでおく
[cm5]
dtoverlay=dwc2,dr_mode=host

[all]

まとめ!

届いたCM5を早速舐め回してみました。一晩でざっと触っただけなので、まだ全然見きれていないですが、CM5は逃げるわけではないので、ゆっくり触っていけたらと思っています。

そう、冬コミの執筆が終わったら、ゆっくり触りたいンゴね……(死)

Raspberry Pi 500リリース

Raspberry Pi Ltd. は12月9日に、Raspberry Pi 500をリリースしました。

https://www.raspberrypi.com/news/raspberry-pi-500-and-raspberry-pi-monitor-on-sale-now

「Raspberry Pi 500」は、Raspberry Piがキーボード一体型となった「Raspberry Pi 400」のRaspberry Pi 5版にあたるモデルです。スペックは基本的にRaspberry Pi 5相当ながら、RAMはPi 400の4GBから倍の8GBが採用されました。

単品モデルには、Raspberry Pi OSが書き込み済みの32GBのSDカードがバンドルされます。価格は90ドルです。

キットモデルは、本体、電源アダプター、マウス、MicroHDMI-HDMIケーブル、入門ガイド、SDカードとケースが付属します。価格は120ドルです。

Raspberry Pi 500は、各リセーラーを通じて販売されますが、日本では技術基準適合証明の取得が完了していないため、取得が確認されて、日本のリセーラーによる販売が開始するのを待つ必要があります。

日本のリセーラーはぞれぞれ、今後の販売予定についてアナウンスしています。日本語版も登場予定で、スイッチサイエンスでは価格を20,130 円としています。

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

スイッチサイエンス https://prtimes.jp/main/html/rd/p/000000184.000064534.html

Raspberry PI 公式モニターの発売

Pi 500との組み合わせを想定した、Raspberry Pi 公式のモニターも合わせて発売されました。15.6インチのフルHS IPSパネルとスピーカーを2つ搭載し、折りたたみ式一体型スタンドとVESAポイントも備えています。価格は100ドルです。

Raspberry Pi 400の価格変更

Raspberry Pi 400については、今後も継続して販売されることと、価格が改定されて値下げされることが、合わせて発表されました。

単品のモデルは、価格変更後の出荷分にSDカードが付属するように変更されながら、価格が70ドルから60ドルに下がりました。また、キットモデルも100ドルから80ドルに価格が変更されています。

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

おわり

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

参考資料