あっきぃ日誌

鉄道ブログのような技術系ブログのようななにか

Compute Module 4のIOボードについてるRTCをさわる

Raspberry Pi Advent Calendar 2020の17日目です。19日目にまめもさん、21日目にgyaboが入ってくれたので、明日書いたら次回は22日目までゆっくり次のネタを考えられそうです。

adventar.org

いつまで引っ張るんだCompute Module 4ネタと言う感じですが、機能的にはまだ色々あるのでネタもたくさんあります。カメラとかまだつないでないしね。で、今日はRTCモジュールを触ります。

RTC

RTCはReal Time Clockの略で、要するに時計機能です。普通のPCにはRTCがついています(ボタン電池がPCのシステムボードにあるのはこれの時刻を維持するためです)が、Raspberry PiにはRTCが搭載されていないので、インターネット接続なしに起動するとfake-hwclockというサービスが前回のシャットダウンした時間に復元します。

Raspberry Piの初期の頃からI2C接続RTCモジュールなどが販売されていて、それを使えばRaspberry Piでも時刻の維持はできていました。

CM4のIOボードにRTCがついた

何の気まぐれかは不明ですが、Compute Module 4のIOボードにはRTCが実装されています。今までCompute ModuleのIOボードにはなかったので、今回が初です。電池はそこらで普通に買えるCR2032が使えるように電池スロットが用意されています。

f:id:Akkiesoft:20201216193736j:plain

電池の横にあるRTCチップの数字を読み取って検索するとPCF85063Aというものが使われていました。検索ワードに更にRaspberry Pi Compute Module 4を足すと、10日前のフォーラムの記事が出てきました。

www.raspberrypi.org

曰く、中の人がこのチップが採用されたことに気づいておらず、チップのドライバーが現在のカーネルに組み込まれていないので、組み込まれるまでは自分でソースをコンパイルするか、rpi-updateをするか、aptでカーネルが降ってくるまで待ってほしいとのこと。ワロタ。誰も使ってなかったのかよ。

数日前にPCIeデバイスのために実行したrpi-updateで降ってきたカーネルではすでに使えるようになっていたため、この環境で設定をやってみます。

設定する

設定の前に、現在はRTCがないことをtimedatectlコマンドで確認します。RTC timeがn/aになっているのでなさそうですね。

pi@m2ssd:~ $ timedatectl
               Local time: 水 2020-12-16 19:58:01 JST
           Universal time: 水 2020-12-16 10:58:01 UTC
                 RTC time: n/a
                Time zone: Japan (JST, +0900)
System clock synchronized: no
              NTP service: active
          RTC in local TZ: no

それでは設定していきます。PCF85063AはI2C接続なので、I2Cを有効にしておきます。

pi@m2ssd:~ $ sudo raspi-config nonint do_i2c 0

/boot/configに設定を追加します。最新のEEPROM(beta版2020-12-11 == stable版2020-12-14)を適用済みなら[cm4]セクションを作ってその中に書くと良いですが、そうでなければ最後の[all]のあとに書いても良いでしょう。おすすめは前者ですかね。

pi@m2ssd:~ $ sudo vi /boot/config.txt 
(ファイルの最後の方に移動して)

[pi4]
# Enable DRM VC4 V3D driver on top of the dispmanx display stack
dtoverlay=vc4-fkms-v3d
max_framebuffers=2

# ここから
[cm4]
dtparam=i2c_vc=on
dtoverlay=i2c-rtc,pcf85063a,i2c_csi_dsi
# ここまで

[all]
#dtoverlay=vc4-fkms-v3d
#EEPROM適用前ならここにdtparamとdtoverlayの2行をここに書く

設定を書けたら再起動して、再度timedatectlコマンドを実行します。おーRTC timeに時刻が入ってますね。

pi@m2ssd:~ $ timedatectl 
               Local time: 水 2020-12-16 19:56:22 JST
           Universal time: 水 2020-12-16 10:56:22 UTC
                 RTC time: 水 2020-12-16 10:56:23
                Time zone: Japan (JST, +0900)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

フォーラムの記事曰く、dmesgでこのあたりを確認するのも良さそうです。

pi@m2ssd:~ $ dmesg | grep rtc
[    8.659511] rtc-pcf85063 10-0051: registered as rtc0

まとめ

Compute Module 4のIOボードについてるRTCを使う方法を紹介しました。

LANに接続されていて、インターネットにアクセスできるか、出られなくてもLAN内にNTPサーバーがあるような環境であれば、RTCがなくてもRaspberry Piが起動する時に自動的に時刻が同期されて問題なく利用できますが、そうでない環境であればRTCは有効な時刻保持手段となります。

とはいえ私も基本的にネットワークに接続して使うので、とりあえず電池を突っ込んではみたもののあまり意味はない感じです。まあ、ついてたのでやってみたかったんです。

まああとは、そんな感じの需要だから、発売後ややしばらく経ってから、実はドライバーがカーネルに含まれてねえという話が出るのかもしれませんが。apt upgradeで降ってくるカーネルにドライバーが含まれるようになるのは数週間後とのことなので、年明けにはカーネル周りの云々をせずとも、すっと設定できるようになっているかと思います。

Raspberry Pi Compute Module 4でPCI Expressデバイスを動かす(10GbE NIC編)

Raspberry Pi Advent Calendar 2020の16日目です。

adventar.org

15日目はtakiponeさんのRaspberry Pi Zero 2台とB+をUSBで繋いでLinuxルーター検証環境でした。私が7日にL2スイッチを作っていたので、これでL3もカバーされましたね!

さて今日はついに!CM4で10GbE NICです。

試すNIC

今回試すのは、自前の10GbEカード「SolarFlare SFN5122F」と会社から借りてきた「Intel X520DA-2」の2枚。結果から言うとSolarFlareのNICが使えて、メジャーなはずのX520は一瞬しかリンクアップせず使えない結果となりました。

(追記)X520は自宅の10GbEスイッチとの相性でリンクしないだけで、動作しました。

カーネルコンパイル

コンパイル作業は例によってCM4ではなくPi4 8GBRAMモデルを使用し、ストレージもUSB SSDUSB3.0接続して爆速でコンパイルしていきます。クロスコンパイル……知らない子ですね。あと、カーネルコンパイル環境の用意の方法はGbE編で紹介済みです。

Raspberry Pi Compute Module 4でPCI Expressデバイスを動かす(GbE NIC編) - あっきぃ日誌

今回は、Raspberry Piカーネルコンパイルのドキュメントに従って、CONFIG_LOCALVERSIONを付け足すようにしました。これとkernel7l.imgのバックアップをやっておけば、なんかミスっても切り戻し可能です。

Kernel building - Raspberry Pi Documentation

pi@usbpi:~/linux $ vi .config

# -pcitestを足した
CONFIG_LOCALVERSION="-v7l-pcitest"

SolarFlareのカーネルオプション

make menuconfigで入ったら、「Device Drivers」→「Network device support」→「Ethernet driver support」 の順に辿り、IntelとSolarFlareのオプションを有効にします。

<M>     Intel(R) 10GbE PCI Express adapters support              
[*]       Intel(R) 10GbE PCI Express adapters HWMON support (NEW)

[*]   Solarflare devices  
<M>     Solarflare SFC9000/SFC9100/EF100-family support               
[*]       Solarflare SFC9000/SFC9100-family MTD support (NEW)         
[*]       Solarflare SFC9000/SFC9100-family hwmon support (NEW)       
[*]       Solarflare SFC9000/SFC9100-family MCDI logging support (NEW)
<M>     Solarflare SFC4000 support                                    
[*]       Solarflare SFC4000 MTD support (NEW)  

あとは保存してコンパイルします。所要時間は1時間くらいでした。

pi@usbpi:~/linux $ make modules_prepare
(必要に応じてscreenなどを張って)
pi@usbpi:~/linux $ make -j 4

コンパイルできたら、成果物をインストールしていきます。モジュールはmakeコマンドで、カーネルイメージとDeviceTree周りはバックアップしつつコピーします。

# モジュール
pi@usbpi:~/linux $ sudo make modules_install

# カーネルイメージ。バックアップは2回目以降は適宜工夫を
pi@usbpi:~/linux $ sudo cp /boot/kernel7l.img /boot/kernel7l.img.bak
pi@usbpi:~/linux $ sudo cp arch/arm/boot/zImage /boot/kernel7l.img

# DeviceTree
pi@usbpi:~/linux $ sudo mv -a /boot/overlays /boot/overlays.bak
pi@usbpi:~/linux $ sudo mkdir /boot/overlays
pi@usbpi:~/linux $ sudo cp arch/arm/boot/dts/overlays/*.dtb* /boot/overlays/
pi@usbpi:~/linux $ sudo cp arch/arm/boot/dts/overlays/README /boot/overlays/

ここまでできたら一旦再起動します。

Solar Flareの10GbE NICを動かす!

ではいよいよ10GbE NICを動かします。一式をつなぎ込んで電源ON!!

f:id:Akkiesoft:20201216123612j:plain

lspci、lsmod、ethtoolの情報は異常なしです。

pi@usbpi:~ $ lspci
00:00.0 PCI bridge: Broadcom Limited Device 2711 (rev 20)
01:00.0 Ethernet controller: Solarflare Communications SFC9020 [Solarstorm]
01:00.1 Ethernet controller: Solarflare Communications SFC9020 [Solarstorm]

pi@usbpi:~ $ lsmod | grep sfc
sfc                   286720  0
mdio                   16384  1 sfc
mtd                    69632  8 ofpart,sfc

pi@usbpi:~ $ ethtool -i eth1
driver: sfc
version: 5.10.0-rc7-v7l-sfc1+
firmware-version: 3.3.2.1000
expansion-rom-version: 
bus-info: 0000:01:00.0
supports-statistics: yes
supports-test: yes
supports-eeprom-access: no
supports-register-dump: yes
supports-priv-flags: no

IPアドレスが取得できているか確認します。以前はカーネルコンパイル周りの経験値が足りず、DHCPのアドレス取得に失敗したり、取得できていてもうまく疎通できなかったりしましたが、今回は成功しています。きたー!

3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0f:53:**:**:** brd ff:ff:ff:ff:ff:ff
    inet 192.168.29.141/24 brd 192.168.29.255 scope global dynamic noprefixroute eth1
       valid_lft 14390sec preferred_lft 12590sec
    inet6 (略) scope global dynamic mngtmpaddr noprefixroute 
       valid_lft 14390sec preferred_lft 12590sec
    inet6 (略) scope link 
       valid_lft forever preferred_lft forever
4: eth2: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000
    link/ether 00:0f:53:**:**:** brd ff:ff:ff:ff:ff:ff

X520

先に動かないと書いてしまいましたが、X520の方も動作検証をします。認識の具合は普通でした。

pi@usbpi:~ $ lspci
00:00.0 PCI bridge: Broadcom Limited Device 2711 (rev 20)
01:00.0 Ethernet controller: Intel Corporation 82599ES 10-Gigabit SFI/SFP+ Network Connection (rev 01)
01:00.1 Ethernet controller: Intel Corporation 82599ES 10-Gigabit SFI/SFP+ Network Connection (rev 01)

pi@usbpi:~ $ lsmod | grep ixgbe
ixgbe                 266240  0

pi@usbpi:~ $ ethtool -i eth1
driver: ixgbe
version: 5.10.0-rc7-v7l-pcitest+
firmware-version: 0x000161ae
expansion-rom-version: 
bus-info: 0000:01:00.0
supports-statistics: yes
supports-test: yes
supports-eeprom-access: yes
supports-register-dump: yes
supports-priv-flags: yes

ケーブルは繋いでいますが、リンクダウンしています。

pi@usbpi:~ $ ip a
3: eth1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000
    link/ether 90:e2:ba:**:**:** brd ff:ff:ff:ff:ff:ff
4: eth2: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000
    link/ether 90:e2:ba:**:**:** brd ff:ff:ff:ff:ff:ff

dmesgでケーブルをさしこんだときのログを見ると、すぐにリンクダウンしている様子が確認できました。カードを見ると、LINKとACTのランプが高速で点滅していて、動作が怪しいです。まあ、動作NGと見るのが妥当でしょう。

[  176.263616] ixgbe 0000:01:00.0 eth1: detected SFP+: 3
[  176.421193] ixgbe 0000:01:00.0 eth1: NIC Link is Up 10 Gbps, Flow Control: RX/TX
[  176.421490] IPv6: ADDRCONF(NETDEV_CHANGE): eth1: link becomes ready
[  177.422576] ixgbe 0000:01:00.0 eth1: NIC Link is Down

ちなみに、DellのSFP+モジュールを差し込んだらunsupportedと怒られました。

[  564.014629] ixgbe 0000:01:00.0: failed to initialize because an unsupported SFP+ module type was detected.
[  564.014650] ixgbe 0000:01:00.0: Reload the driver after installing a supported module.

このX520カードもDell OEMっぽいシールがはられているんですが……。そう、一点気になるとすれば、そのあたりのOEMによるファームウェアの違いとかがあります。とにかくCM4でこのX520カードはダメでした。いちおう会社に純正のもあるんですが使用中なので、空いたらリトライしたいところです。

追記

Twitterでコメントを もらいました。うちのQNAPのハブQSW-308-1CにはX520と相性問題があるそう。マジか

というわけでつなぎ先をスイッチからラックサーバー×SolarFlareに変えてテストしようとしたら、このタイミングでラックサーバーが死亡こっちはこっちで相性問題が発生して起動せず……。自宅サーバーで稼働中のSolarFlareに差し込んで無事リンクまで確認できました。

iperf3でベンチマーク

X520は動かなかったのでラックサーバーに入ってもらって、これとCM4のSolarFlareとでiperf3で測定します。どちらの10GbENICも直結してIPアドレスを固定した上で測定しました。長ったらしいですが、全部の出力を貼ります。ところでラックサーバーではX520は動きましたね。また、ラックサーバー側はUbuntu Server 20.04です。

f:id:Akkiesoft:20201216202758j:plain
(追記)ベンチマークの様子の写真を貼り忘れてたので貼りました

まずはCM4をサーバーにした方の結果。

pi@usbpi:~ $ iperf3 -s
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------
Accepted connection from 192.168.0.1, port 57926
[  5] local 192.168.0.2 port 5201 connected to 192.168.0.1 port 57928
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-1.00   sec   300 MBytes  2.52 Gbits/sec                  
[  5]   1.00-2.00   sec   313 MBytes  2.62 Gbits/sec                  
[  5]   2.00-3.00   sec   313 MBytes  2.62 Gbits/sec                  
[  5]   3.00-4.00   sec   313 MBytes  2.62 Gbits/sec                  
[  5]   4.00-5.00   sec   313 MBytes  2.63 Gbits/sec                  
[  5]   5.00-6.00   sec   313 MBytes  2.63 Gbits/sec                  
[  5]   6.00-7.00   sec   313 MBytes  2.62 Gbits/sec                  
[  5]   7.00-8.00   sec   313 MBytes  2.62 Gbits/sec                  
[  5]   8.00-9.00   sec   313 MBytes  2.63 Gbits/sec                  
[  5]   9.00-10.00  sec   313 MBytes  2.63 Gbits/sec                  
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-10.00  sec  3.04 GBytes  2.61 Gbits/sec                  receiver

---

akkie@rackme:~$ iperf3 -c 192.168.0.2
Connecting to host 192.168.0.2, port 5201
[  5] local 192.168.0.1 port 57928 connected to 192.168.0.2 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec   306 MBytes  2.57 Gbits/sec    0    724 KBytes       
[  5]   1.00-2.00   sec   312 MBytes  2.62 Gbits/sec    0    724 KBytes       
[  5]   2.00-3.00   sec   312 MBytes  2.62 Gbits/sec    0    724 KBytes       
[  5]   3.00-4.00   sec   314 MBytes  2.63 Gbits/sec    0    724 KBytes       
[  5]   4.00-5.00   sec   312 MBytes  2.62 Gbits/sec    0    724 KBytes       
[  5]   5.00-6.00   sec   314 MBytes  2.63 Gbits/sec    0    724 KBytes       
[  5]   6.00-7.00   sec   312 MBytes  2.62 Gbits/sec    0    724 KBytes       
[  5]   7.00-8.00   sec   312 MBytes  2.62 Gbits/sec    0    724 KBytes       
[  5]   8.00-9.00   sec   314 MBytes  2.63 Gbits/sec    0    724 KBytes       
[  5]   9.00-10.00  sec   312 MBytes  2.62 Gbits/sec    0    724 KBytes       
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  3.05 GBytes  2.62 Gbits/sec    0             sender
[  5]   0.00-10.00  sec  3.04 GBytes  2.61 Gbits/sec                  receiver

iperf Done.

次にラックサーバーをサーバーにした方の結果。

akkie@rackme:~$ iperf3 -s
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------
Accepted connection from 192.168.0.2, port 34584
[  5] local 192.168.0.1 port 5201 connected to 192.168.0.2 port 34586
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-1.00   sec   304 MBytes  2.55 Gbits/sec                  
[  5]   1.00-2.00   sec   322 MBytes  2.70 Gbits/sec                  
[  5]   2.00-3.00   sec   320 MBytes  2.69 Gbits/sec                  
[  5]   3.00-4.00   sec   322 MBytes  2.70 Gbits/sec                  
[  5]   4.00-5.00   sec   321 MBytes  2.70 Gbits/sec                  
[  5]   5.00-6.00   sec   323 MBytes  2.71 Gbits/sec                  
[  5]   6.00-7.00   sec   317 MBytes  2.66 Gbits/sec                  
[  5]   7.00-8.00   sec   321 MBytes  2.69 Gbits/sec                  
[  5]   8.00-9.00   sec   320 MBytes  2.68 Gbits/sec                  
[  5]   9.00-10.00  sec   320 MBytes  2.69 Gbits/sec                  
[  5]  10.00-10.02  sec  5.97 MBytes  2.76 Gbits/sec                  
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-10.02  sec  3.12 GBytes  2.68 Gbits/sec                  receiver

---

pi@usbpi:~ $ iperf3 -c 192.168.0.1
Connecting to host 192.168.0.1, port 5201
[  5] local 192.168.0.2 port 34586 connected to 192.168.0.1 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec   312 MBytes  2.62 Gbits/sec    0   1.27 MBytes       
[  5]   1.00-2.00   sec   322 MBytes  2.71 Gbits/sec    0   1.27 MBytes       
[  5]   2.00-3.00   sec   320 MBytes  2.68 Gbits/sec    0   1.27 MBytes       
[  5]   3.00-4.00   sec   322 MBytes  2.71 Gbits/sec    0   1.27 MBytes       
[  5]   4.00-5.00   sec   321 MBytes  2.69 Gbits/sec    0   1.27 MBytes       
[  5]   5.00-6.00   sec   322 MBytes  2.71 Gbits/sec    0   1.27 MBytes       
[  5]   6.00-7.00   sec   318 MBytes  2.66 Gbits/sec    0   1.27 MBytes       
[  5]   7.00-8.00   sec   321 MBytes  2.69 Gbits/sec    0   1.27 MBytes       
[  5]   8.00-9.00   sec   320 MBytes  2.69 Gbits/sec    9   1.27 MBytes       
[  5]   9.00-10.00  sec   320 MBytes  2.68 Gbits/sec    0   1.27 MBytes       
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  3.12 GBytes  2.68 Gbits/sec    9             sender
[  5]   0.00-10.02  sec  3.12 GBytes  2.68 Gbits/sec                  receiver

iperf Done.

上記から、大体2.6Gbps、MB単位ではで300MB/sくらい出ることが確認できました。Raspberry Pi4のPCI Expressは2.0 x1規格で理論値は500MB/sくらいのようなので、3/5くらいの性能が出る、ということになります。

また、先日のNVMe SSDの測定結果も270MB/s前後だったことから、なんとなく実測性能は300MB/s前後、と見ることができそうです。

まとめ

Raspberry Pi Compute Module 4で10GbE NICがついに動作させられました。ブログなので動くように手順が整理していますが、手探りしながら動いた瞬間「うおお!!」って叫びました。

測定の結果から、Pi4のUSB3.0ポートに2.5GbE NICでもさしておけば性能的にはOKという見方もできます。ただ、ここにUSB SSDもつないでローカルストレージにすると300MB/sの帯域を奪い合うことになるので、やるならどっちかになりそうな感じです。まあ、SSDですね。

ヤフオクで粘っていればたまに安価にカードが拾えるので、速度よりも男のロマン的に動かしてみるのも良いですね。

さて、このあとはGPUも……と生きたいところですが、こちらはドライバー以前に起動中にカーネルパニックでコケるレベルなので、おそらくブログネタにはできなさそうです。もしかするとCM4のRAMが足りないとか、そっち方面の問題が出てるかなあと想像しているところです。わからないですけどね。ちなみに、x1スロット形状でHDMIが4つ出るGT710カードは使えているという話が財団の中の人から出てるっぽいです。が、そこまでして動かしたいわけでもなく……🤔。

あとは、SolarFlareを動かしている様子の写真に写り込んでいたUSB3.0SATAのコンボカードもあるのですが、これもどうもコンボにするためのスイッチチップが怪しいのかどちらも動作が不安定です。VL805チップなUSB3.0カードはAliExpressでポチポチしたので、届いたらテストしていくつもりですが、これは多分Advent Calendarが終わったあとになりそうです。

Raspberry Pi Compute Module 4でPCI Expressデバイスを動かす(NVMe SSD編)

Raspberry Pi Advent Calendar 2020の14日目です。

adventar.org

今回はCM4でNVMe SSDを動かす話。どうもNVMe SSDはドライバーコンパイルをしなくても動きそうなので、先日のrpi-updateした環境でテストをしてみます。

NVMe SSDの検証には、LenovoのM75q-2についているSSDを使おうと着弾前から企んでいたのですが、いざ到着して開けてみたらまさかの聞いたこともない謎SSDが実装されており、一抹の不安を感じます。写真はM75q-2の記事からの再掲。M75q-1のときは(128GBだからかもですけど)KIOXIAだったのに。Union Memory完全に知らん子ですわ……。

f:id:Akkiesoft:20201212224733j:plain

気を取り直してCM4に接続していきます。変換アダプターはこないだ自宅サーバーのSSD移行をするときに使ったものを使いました。上の空きスロットはM.2 SATA SSDSATAネクターに出すときに使うやつです。

f:id:Akkiesoft:20201213173458j:plain

起動したらlspciを実行し……応答がないと思ったらやべー感じのメッセージが出ました。もうダメそうです。

pi@raspberrypi:~ $ lspci

Message from syslogd@raspberrypi at Dec 13 16:54:19 ...
 kernel:[   50.923847] Internal error: : 1211 [#2] SMP ARM

Message from syslogd@raspberrypi at Dec 13 16:54:19 ...
 kernel:[   50.924746] Process lspci (pid: 551, stack limit = 0x85eeec38)

Message from syslogd@raspberrypi at Dec 13 16:54:19 ...
 kernel:[   50.924769] Stack: (0xc3149dd0 to 0xc314a000)

dmesgでもダメっぽそうな感じのtraceとかが出ていたので、ダメそうです。

[    1.134519] brcm-pcie fd500000.pcie: host bridge /scb/pcie@7d500000 ranges:
[    1.134569] brcm-pcie fd500000.pcie:   No bus range found for /scb/pcie@7d500000, using [bus 00-ff]
[    1.134672] brcm-pcie fd500000.pcie:      MEM 0x0600000000..0x063fffffff -> 0x00c0000000
[    1.134781] brcm-pcie fd500000.pcie:   IB MEM 0x0000000000..0x003fffffff -> 0x0400000000
[    1.195599] brcm-pcie fd500000.pcie: link up, 5.0 GT/s PCIe x1 (SSC)
[    1.195998] brcm-pcie fd500000.pcie: PCI host bridge to bus 0000:00
[    1.196035] pci_bus 0000:00: root bus resource [bus 00-ff]
[    1.196071] pci_bus 0000:00: root bus resource [mem 0x600000000-0x63fffffff] (bus address [0xc0000000-0xffffffff])
[    1.196179] pci 0000:00:00.0: [14e4:2711] type 01 class 0x060400
[    1.196438] pci 0000:00:00.0: PME# supported from D0 D3hot
[    1.199662] PCI: bus0: Fast back to back transfers disabled
[    1.199704] pci 0000:00:00.0: bridge configuration invalid ([bus ff-ff]), reconfiguring
[    1.200000] pci 0000:01:00.0: [1cc4:17ab] type 00 class 0x010802
[    1.200097] pci 0000:01:00.0: reg 0x10: [mem 0x00000000-0x00003fff 64bit]
[    1.200495] pci 0000:01:00.0: PME# supported from D0 D3hot
[    1.200609] pci 0000:01:00.0: 4.000 Gb/s available PCIe bandwidth, limited by 5.0 GT/s PCIe x1 link at 0000:00:00.0 (capable of 31.504 Gb/s with 8.0 GT/s PCIe x4 link)
[    1.203721] PCI: bus1: Fast back to back transfers disabled
[    1.203758] pci_bus 0000:01: busn_res: [bus 01-ff] end is updated to 01
[    1.203851] pci 0000:00:00.0: BAR 8: assigned [mem 0x600000000-0x6000fffff]
[    1.203892] pci 0000:01:00.0: BAR 0: assigned [mem 0x600000000-0x600003fff 64bit]
[    1.203959] pci 0000:00:00.0: PCI bridge to [bus 01]
[    1.203999] pci 0000:00:00.0:   bridge window [mem 0x600000000-0x6000fffff]
[    1.204423] pcieport 0000:00:00.0: enabling device (0140 -> 0142)
[    1.204652] pcieport 0000:00:00.0: PME: Signaling with IRQ 62

(中略)

[    4.279373] nvme nvme0: pci function 0000:01:00.0
[    4.279465] nvme 0000:01:00.0: enabling device (0000 -> 0002)
[    5.467617] 8<--- cut here ---
[    5.467651] Unhandled fault: asynchronous external abort (0x1211) at 0x00000000
[    5.467681] pgd = (ptrval)
[    5.467701] [00000000] *pgd=80000000004003, *pmd=00000000
[    5.467746] Internal error: : 1211 [#1] SMP ARM

10GbEといいUSB3.0カードといい、変換アダプターをつかうカードがことごとくダメなので、疑心暗鬼に陥りかけましたが、先人JeffがNVMe SSDについてもレポートしていました。

The Raspberry Pi Compute Module 4 Review | Jeff Geerling

曰く、「XPG SX6000(ADATA)だと動かなくて、複数アダプターを買って確かめても変なメッセージがでてダメだった。Samsung 970 EVO Plusに変えたら認識した。早いぜヒャッホー!!」とのこと。UnionMemoryのSSDもおそらくこのパターンでは……。

Samsung 970 EVO Plusは自宅サーバーで使用中ですがサーバーは止められないので、メインPCからSamsung 950 PROを取り外すことにしました。MiniITXの自作機だからマザーボードの裏にあって外すのが面倒なんだぞ……!しかも開けたらホコリまみれでついでに大掃除が発生しました。極力配線を外さないように無理やりNVMe SSDを取り外しました。

f:id:Akkiesoft:20201213174614j:plain

というわけでUnionMemoryにはご退場いただいて、Samsung 950 PROでやっていきます。

f:id:Akkiesoft:20201213174725j:plain

CM4に接続。

f:id:Akkiesoft:20201213174917j:plain

起動したらlspciで確認。おっ!ちゃんと結果が出る!

pi@raspberrypi:~ $ lspci
00:00.0 PCI bridge: Broadcom Limited Device 2711 (rev 20)
01:00.0 Non-Volatile memory controller: Samsung Electronics Co Ltd NVMe SSD Controller (rev 01)

Jeffのレポート曰く、NVMe のドライバーを読み込み直す必要があるみたいなことが書かれていましたが、パーティションが見えているので、読み込みの必要はなさそうでした。rpi-updateでバージョンが変わっているからかもしれません。

pi@raspberrypi:~ $ cat /proc/partitions 
major minor  #blocks  name
(中略)
 179        0   60751872 mmcblk0
 179        1     262144 mmcblk0p1
 179        2   60485632 mmcblk0p2
 259        0  250059096 nvme0n1
 259        1    5242880 nvme0n1p1
 259        2  169869312 nvme0n1p2
 259        3   66463744 nvme0n1p3
 259        4    8479744 nvme0n1p4

fdiskもちゃんと見えてますね。

pi@raspberrypi:~ $ sudo fdisk -l /dev/nvme0n1
Disk /dev/nvme0n1: 238.5 GiB, 256060514304 bytes, 500118192 sectors
Disk model: Samsung SSD 950 PRO 256GB               
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: (略)

Device             Start       End   Sectors  Size Type
/dev/nvme0n1p1      2048  10487807  10485760    5G EFI System
/dev/nvme0n1p2  10487808 350226431 339738624  162G Linux filesystem
/dev/nvme0n1p3 367185920 500113407 132927488 63.4G Microsoft basic data
/dev/nvme0n1p4 350226432 367185919  16959488  8.1G Linux swap

Partition table entries are not in disk order.

このSSDにはUbuntuが入っていてLinuxパーティションがあるのでマウントもしてみました。問題なさそうです!

pi@raspberrypi:~ $ sudo mount /dev/nvme0n1p2 /mnt
pi@raspberrypi:~ $ ls /mnt
bin   cdrom  etc   lib    lib64   media  opt   root  sbin  srv       sys  usr
boot  dev    home  lib32  libx32  mnt    proc  run   snap  swap.img  tmp  var

そしてhdparm。ちょっと不穏なメッセージが出ていますが、計測はできています。CM4のPCIe性能がボトルネックになるので、NVMeとはいえ270MB/s程度しか出せませんが、Raspberry Piで270MB/s出るので、これは早いですね!

pi@raspberrypi:~ $ sudo hdparm -t /dev/nvme0n1

/dev/nvme0n1:
 HDIO_DRIVE_CMD(identify) failed: Inappropriate ioctl for device
 Timing buffered disk reads: 812 MB in  3.00 seconds = 270.36 MB/sec

まとめ

Jeffの言う通り、SamsungのNVMe SSDならCM4で認識させて使うことができました。これでどのSSDも使えなかったら(ブログのネタ的に)どうしようかと思いました。検証用にNVMe SSDがあったほうがいいなと思ったので、メルカリで適当に中古をポチポチしちゃいました。昨日仕事ついでにアキバに寄っていてNVMe SSDを物色しながら買うのをやめていたので、買っておけばよかった……!

ただし、こちらもJeffが言う通り、NVMe SSDをPCIeから直接ブートできないので、ブートに使いたいときは(たぶんVL805の)USB3.0ポートを経由する必要があります。で、USB3.0を経由するなら帯域的にSATA SSDで事足りると思われるので、NVMeほど気合をいれなくてもOKという感じになりそうです。

さて、次は今度こそ10GbE NICの話を書きたいところですが、まだ動かせていないと言うか、コンパイルがうまくできていなくて、ぐぬぬとなっています……。明日のカレンダーはtakiponeさんという方にご参加いただけそうなので、その間にがんばります!

Raspberry Pi Compute Module 4でUSBマスストレージブートを有効化する

Raspberry Pi Advent Calendar 2020の13日目です。つぼさんご結婚おめでとうございます!式が終わって一息みたいなことを言っていたので、今なら書く余裕出ましたか?!とつついたところ参加登録してもらえました。新婚のひとに対してやることじゃない感がありちょっと反省しています。

adventar.org

今日はPCIeデバイスの続き……をするためにCM4でUSBマスストレージブート(以下USB MSDブート)を有効化しようとしたら、これだけで1記事書ける感じになったのでそのはなしです。

CM4のUSB MSDブートサポート

CM4の出荷時のBoot EEPROMバージョンは2020-10-02リリースのものになっています。が、これはcriticalにもstableにも置かれておらず、なんやねんという感じがしました。さておき、この2020-10-02リリースのものでは実はUSB MSDブートができません。

Pi4のUSB MSDブートはVL805がある前提で作られているらしく、それがないCM4ではUSBからのブートができないようです。ちなみにIOボードのUSB2.0ポートはSoCから出たUSB2.0ポートをUSB2514ハブチップで増やしていて、USB-Ax2と、ピンヘッダ(ピンアサインはわからんけど多分データシートにあるはず)で提供されています。

そんなわけで、CM4のUSB MSDブートサポートは2020-11-24リリースのbetaのイメージで提供され始めたので、USBを使いたければアップデートせよ、ということのようです。

rpi-eeprom/release-notes.md at master · raspberrypi/rpi-eeprom · GitHub

rpi-eeprom-updateは使えない

いつものようにCM4でRaspberry Pi OSを起動してrpi-eeprom-updateコマンドでアップデートを……とおもったらなんか怒られました。

pi@raspberrypi:~ $ sudo rpi-eeprom-update 
BCM2711 detected
rpi-eeprom-update is not enabled by default on CM4

CM4ではrpi-eeprom-updateが使えないらしく、母艦を用意して母艦上に用意したrpibootコマンドを使ってイメージを流し込む必要があるとのこと。

やり方は以下のドキュメントに記載されていました。というわけで手順を読みながら進めていくことにします。

www.raspberrypi.org

アップデートのためのファイルを準備する

母艦には手元に転がっていたPi4を使うことにして、MicroSDカードをCM4からPi4に移して起動し、作業開始します。

まずはイメージの用意。最新は2020-11-24の次にリリースされた2020-12-11(これもbeta)になるので、これを使います。このバージョンではconfig.txtで[pi400]と[cm4]セクションが使えるようになったので、config.txtの設定をPi400とCM4とその他とで使い分けたいことがあれば有用な変更です。最新のパッケージに2020-12-11版イメージが含まれているのでaptでインストールします。

pi@raspberrypi:~ $ sudo apt update;sudo apt install rpi-eeprom

次にrpibootの用意。これもaptで入るっぽかったのですが、パッケージ版のコマンドで書き込んだら変な出力が出て怖かったので、手順に従ってソースからコンパイルします。

pi@raspberrypi:~ $ git clone --depth=1 https://github.com/raspberrypi/usbboot
pi@raspberrypi:~ $ cd usbboot
pi@raspberrypi:~/usbboot $ sudo apt install -y libusb-1.0-0-dev
pi@raspberrypi:~/usbboot $ make -j 4

次はイメージの準備をします。clone下リポジトリの中にrecoveryディレクトリがあり、古いイメージが鎮座しているので、適当にどかします。

pi@raspberrypi:~/usbboot $ cd recovery
pi@raspberrypi:~/usbboot/recovery $ mkdir original
pi@raspberrypi:~/usbboot/recovery $ mv pieeprom.* original/

かわりに2020-12-11版イメージをコピーしたいのですが、ブート順を変更する必要があるため、rpi-eeprom-configコマンドで設定を書き換えたイメージを生成する必要があります。だるいね。やり方は以前Pi4のPXEブートをやったときと同様です。

(pieeprom-2020-12-11.binの設定をhoge.confに書き出し)
pi@raspberrypi:~/usbboot/recovery $ rpi-eeprom-config /lib/firmware/raspberrypi/bootloader/beta/pieeprom-2020-12-11.bin -o hoge.conf
(hoge.confの設定を編集)
pi@raspberrypi:~/usbboot/recovery $ vi hoge.conf

[all]
BOOT_UART=0
WAKE_ON_GPIO=1
POWER_OFF_ON_HALT=0
BOOT_ORDER=0xf51   ←この行を追記

(pieeprom-2020-12-11.binにhoge.confの設定を投入したものをpieeprom.binに書き出し)
pi@raspberrypi:~/usbboot/recovery $ rpi-eeprom-config -c hoge.conf -o pieeprom.bin /lib/firmware/raspberrypi/bootloader/beta/pieeprom-2020-12-11.bin

BOOT_ORDERの値については、リリースノートにもあるとおり"5"がUSB2.0ポート版USB USDブートとなります。この5の値はPi4とPi400のUSB-Cポートでも有効のようです。使いみちは……🤔?

続けて、pieeprom.binのsha256チェックサムを記述したpieeprom.sigファイルを作成します。別のドキュメント(どれか忘れた)にはpieeprom.sigの内容は将来的に変更される可能性があるとか書かれていたので、この記事を遠い未来に読んでいる方は、先述のドキュメントを参照してください。ただ、記事公開からそれほど経っていない時点で読んでいる方は以下を見てください。公式ドキュメントのawkのパラメーターが間違っていて$2になっていました。$2にしたらファイル名が書かれるやろがい。

pi@raspberrypi:~/usbboot/recovery $ sha256sum pieeprom.bin | awk '{print $1}' > pieeprom.sig

ここまででファイルの準備は完了です。

物理的な準備

イメージを書き込むための準備をします。

イメージを書き込むには、IOボードのJ2ジャンパの「Fit jumper to disable eMMC Boot」と書かれた部分をショートさせる必要があります。ジャンパピンを使うか、メス-メスのヘッダーピン用ケーブルでつなぐかすると良いでしょう。

f:id:Akkiesoft:20201212221406j:plain

データ転送には、IOボードのUSB Slave(MicroUSBポート)と母艦をつなぎます。つまりMicroUSBケーブルが必要です。こんなかんじ。IOボードの電源はまだ入れません。

f:id:Akkiesoft:20201212221848j:plain

書き込み!

準備完了。母艦側でrpibootコマンドを実行して、待機状態にします。

pi@raspberrypi:~/usbboot/recovery $ sudo ../rpiboot -d .
Waiting for BCM2835/6/7/2711...

待機状態になったらIOボードの電源ケーブルを差し込みます。

f:id:Akkiesoft:20201212222137j:plain

すると、こんな感じでメッセージが流れます。「Second stage boot server done」と出てコマンドが終われば成功です。またIOボード側は緑ランプが高速で点滅していれば書き込み完了の状態です。

Waiting for BCM2835/6/7/2711...
Loading: /home/pi/recovery/bootcode4.bin
Sending bootcode.bin
Successful read 4 bytes 
Waiting for BCM2835/6/7/2711...
Loading: /home/pi/recovery/bootcode4.bin
Second stage boot server
Loading: /home/pi/recovery/config.txt
File read: config.txt
Loading: /home/pi/recovery/pieeprom.bin
Loading: /home/pi/recovery/pieeprom.bin
Loading: /home/pi/recovery/pieeprom.sig
File read: pieeprom.sig
Loading: /home/pi/recovery/pieeprom.bin
File read: pieeprom.bin
Second stage boot server done

IOボードの電源ケーブルを抜いて、ジャンパを取り外します。この辞典でCM4のSDカードブートができるか確認しておくと良いでしょう。

USB MSDブートする

あとはUSBデバイスをIOボードに挿して起動します、うまく起動したら成功です。

f:id:Akkiesoft:20201212222339j:plain

まとめ

CM4でUSB MSDブートをするための手順を紹介しました。

USB2.0なのになぜCM4でUSB MSDブートする必要があるのかと思われるかもしれませんが、Pi 4のUSB3.0ポートでSSDを使って高速にUSB MSDブート&読み書きできる環境で生成した結果をCM4上で利用したかったので、CM4でせっせとUSB MSDブートを有効化していたのでした。

具体的には、USB SSDを使ってLinuxカーネルコンパイルをやっていました。10GbEを利用するにはドライバー以外にカーネルのオプション周りもいじらないといけないのかと思い、カーネル全体をコンパイルしたりしていた次第です。ちなみに、正確な時間は測っておらず放置した時間からの推測ですが、Pi4とSSDだと1時間半くらいでコンパイルできていたんじゃないかと思います。つよいね。

Lenovo ThinkCentre M75q-2 Tinyを買った

夏にM75q-1を買いましたが、すぐに実家の甥にあげてしまったので何故買った状態になりましたが、やっぱ小さいパワフルなマシンほしいなあとか、AMD DASHもうちょっと触りたいとか、色々思っていたらM75q-2が出たので、また買ってしまいました。

これは夏の記事。

akkiesoft.hatenablog.jp

今回は53,900円。ちょっとお値段が前よりも高く見えますが、CPUをRyzen 7 PRO 4750GEにしています。あと、背部USB-Cポートをつけたり無線をつけたりしたので最小構成ではありません。それでもバグみたいな値段なんだよなあ。

f:id:Akkiesoft:20201212223818p:plain

こんな価格なので、メモリはカスタムで一番安くなるようにしつつ、じゃんぱらで奮発して32GBx2を3万弱で買ってしまったので、8万くらいでつよつよマシンになりました。これならApple M1とも勝負できるやろ(??)

んで、当初は納期が来年2月とかいう状態でグエーとなってたんですが、12月上旬に変わって今週着弾しました。何があった。どうも、USB-Cポートのスペックに表記ミスが有り、キャンセルしたという人がいたりしたそうなので、そのへんで順番が早く回ってきたのだとしたらラッキーですね。

というわけでドン。いいっすね。相変わらずiの赤ポッチが光ります。

f:id:Akkiesoft:20201212224428j:plain

背部のUSB-Cポート。シリアルポートのところにそうつけるんかーい!と突っ込んでしまいました。

f:id:Akkiesoft:20201212224507j:plain

到着したてはヒエヒエなので、フタをあけて中を観察しながら室温に慣らします。まあ、M75q-1と大きくは変わらなさそうな印象です。

f:id:Akkiesoft:20201212224536j:plain

ひっくり返してRAMとSSD。今回はKIOXIAじゃないんですね。Union Memory……完全に知らん子だ……。

f:id:Akkiesoft:20201212224733j:plain

室温になれたところで一旦フタを閉じて動作を確認。その後メモリを換装しました。32GBを1枚買うか2枚買うかで迷ったんですが、迷うくらいなら今2枚買ってしまえと血迷って64GBになった次第。

f:id:Akkiesoft:20201212224950j:plain

SATA SSDも突っ込んでUbuntu 20.04をインストールしつつ、ffmpegで録画データをH.265エンコードしてみたら、47fps前後で安定したので、Ryzenつえーと言った感じです。パワー系の作業はこいつにやらせていくぞい。

Raspberry Pi AdventCalendarというか、CM4のPCIe周りの挑戦に夢中になっていて、M75q-2がさっそく放り投げられてしまっていますが、落ち着いたらAMD DASHとかも改めて見ていきたいところ。ただ、BIOSの隠しメニューが閉じられているという話もあって、どこまでM75q-1と同じくらい遊べるのかは未知っぽそうでもあります。