最近、Raspberry Pi 3を自作HaskellライブラリーのAArch64での動作確認用に使っていた。だが何かとスペックが物足りないので、Raspberry Pi 4の最近新たに出たメモリ8GBモデルに環境を移行することにした。
色々あった結果、ラズパイ本体だけではなくストレージやOS(ディストリ)も変わった:
旧環境
- Raspberry Pi 3 Model B (メモリ1GB)
- /: microSD 16GB
- OS: Ubuntu Server 18.04 LTS 64bit
新環境
- Raspberry Pi 4 Model B (メモリ8GB)
- /: USB接続SSD 250GB
- OS: Ubuntu Server 20.04 LTS 64bit
購入物
秋葉原に行ったついでに以下の物品を購入した。
- Raspberry Pi 4 Model B メモリ8GBモデル(本体)
- ラズパイ用ACアダプター
- ラズパイ4用ケース。ファンを使わなくても十分放熱してくれそうなやつ。(ラズパイ3の時点で発熱がすごかったので、ラズパイ4はさらに発熱することが予想された)
家に帰ってから気づいたのだが、ラズパイ4のHDMI端子はフルサイズではなくmicroHDMIだった。
ラズパイ4の端子類は、EthernetがGbE対応になってUSB 3.0に対応して電源がUSB Type-Cになったことは把握していたが、HDMI端子のサイズが変わったことは把握していなかった。HDMI端子が小型なのはラズパイZeroだと思って油断していたこともあるかもしれない(ラズパイ売り場にHDMIアダプターが並んでいてもZero用だと思って気に留めなかった)。
(HDMI出力が2本になっているのは、デジタルサイネージでの利用やマルチディスプレイ環境を想定しているのだろうか?)
とは言っても、普段はMacからSSH接続して使用しているので、ラズパイ自身のHDMI出力はそれほど重要ではない。なので、後述の方法でHDMI出力に頼らずに環境構築ができればmicroHDMIアダプターを買わなくてもどうにかできる…と思ったのだがうまくいかなかったので、トラブルシューティングのために結局microHDMI変換アダプターをポチった。
後日買ったもの:
- microHDMIアダプター
「小型の」HDMI端子はデジカメに使われている印象がある。実際、自分が持っている一眼レフには小型のHDMI端子がついていたので、以前、それ用の変換アダプターを購入していた。それを利用できないかと家を探してみたが、出土したのはminiHDMIのアダプターだった(写真の真ん中)。「小型のHDMI」端子にはminiとmicroがあるのである。クソッタレ
- USB接続SSD
当初は128GBくらいのmicroSDカードを買おうと思って思ったが、冷静に考えるとUSB接続SSDの方が容量単価が低いし読み書きが高速なのでSSDを買った(詳しくは後述)。パッケージに記載された読み書き速度が430MB/sの安いやつ。USB 3.0でしか接続できないラズパイごときに高速なNVMe SSDは必要ない。
ラズパイ3のmicroSDカードをラズパイ4にそのまま挿して動くのか
ラズパイ3に乗っているCPUのアーキテクチャはArmv8.0-A, ラズパイ4に乗っているCPUのアーキテクチャもArmv8.0-Aである。ということは、ソフトウェア的な面ではラズパイ3とラズパイ4は互換性がある。なので、ラズパイ3のmicroSDカードをそのままラズパイ4に挿しても動作する可能性がある。
だが、現実はそう甘くなかった。
microSDのブート用パーティション(?)に入っているファームウェア(?)がこのモデル(ラズパイ4)に対応していないというようなエラーが出る。ラズパイ3側で起動してapt full-upgradeを実行しても同じく、である。
「ラズパイ3とラズパイ4にはソフトウェア(OS含む)的に互換性がある」というのは事実のはずで、公式のダウンロードリンクはラズパイ3とラズパイ4のリンク先が同一である。
よく見るとUbuntu Serverのダウンロードリンクには19.10と20.04は載っているが、18.04は載っていない。ラズパイ4ではUbuntu Server 18.04は動かない(?)が、Ubuntu Server 19.10や20.04なら動くかもしれない、という結論に至った。
果たして、 sudo do-release-upgrade -d
によってUbuntu Serverのディストリを20.04へアップグレードしたら同じSDカードでもラズパイ4で動作した。
この節の結論としては、「基本的にはラズパイ3のSDカードをラズパイ4にそのまま挿しても動作するが、ディストリのバージョンが古いと動かない可能性がある」となるだろうか。
Haskell環境
筆者のラズパイの用途は主に「自作Haskellライブラリーの動作確認」であった。アーキテクチャに依存するライブラリーを書く場合、この時代にx86系でしか動作しない(あるいは、x86向けにしか最適化されていない)というのでは不味かろう、という動機である。
これまではUbunut Server 18.04上でStack 2.1.3を使ってGHC 8.8.3を動かしていた。しかし、Ubuntu Server 20.04上で同じことをすると
Unable to find installation URLs for OS key: linux-aarch64-tinfo6
というメッセージが表示されてGHCが動かない。また、Stack自身も、2.3.1ではAArch64向けのバイナリが配布されていないようだ。
(ちなみに、「Ubuntu Server 18.04でビルドしたバイナリをUbuntu Server 20.04で動かす」ことには問題ないようで、ビルド済みのベンチマークプログラムを走らせることはできた。その結果を見ると、ラズパイ4はラズパイ3の倍くらい速くなっているようだ。強い。)
こうなると、最悪自前でGHCをビルドする必要が出てくる。しかし、使っているストレージは16GBのmicroSDカードである。以前「複数のGHCを導入(8.6.5と8.8.3)」しようとしたところストレージの不足で失敗したので、本格的にHaskell環境を整えるにはもっと大容量のストレージを用意する必要がある。
外付けSSDの利用
16GBのmicroSDカードで不足なのであればもっと大容量のmicroSDカードを買えば良い。128GBとか。
そう思って電器屋に行って「どうせ挿す先がラズパイだからそこまで読み書きが高速じゃなくても良いな(読み書きが高速なカードはクソ高い)」「この5000円強くらいのやつが良さそう」などと考えていたが、気づいてしまった。
同じお金があれば、microSDの倍くらいの容量の外付けSSDが買えるのである。
軽くググった感じではラズパイのmicroSDカードの読み書き速度は50MB/sも出れば良い方で、そんなに高速な部類ではない。一方、USB 3.0でSSDを接続すればUSB 3.0の速度に見合った速度(500MB/sくらいのオーダー)で読み書きできることが期待できる。
用途がソフトウェアのビルドなので、ファイルシステムの読み書き速度は速ければ速いほど良い。そういうわけでUSB接続のSSDを買うことにした。ラズパイ4のインターフェースはUSB 3.0(最大5Gbps)なので、高速・高発熱な読み書きを謳うNVMe SSDの性能は必要ない。安いSATA SSDで十分である。
そういうわけで、店のレジ前で安売りされていたUSB接続SSDを買った。
SSDへの移行
ラズパイを外付けUSBデバイスから起動!と言ったときに、
- microSDカードを完全に廃して、USB接続ストレージから起動する
- ブート用のパーティションはmicroSDに残したまま、OSの入ったパーティション(Linuxの
/
)をUSB接続ストレージに移す
の2通りが考えられる。ラズパイ4は前者はできなくはないようだが、ラズパイのEEPROMの書き換えやら何やらが必要らしい。筆者は面倒くさがりなので後者を実践することにした。
まずは、SDカードの内容をSSDへコピーする。この手の作業には筆者は昔からGPartedを使っていたが、筆者の家にはGUIのLinuxが起動するマシンがなかったのでその辺のCD-RにGParted Liveを焼いてデスクトップ機で起動した。その上で、SSDをGPTでアレした上でLinuxの入ったext4のパーティションをコピーした。
データのコピー後、コピー先のラベル&UUIDはコピー元のラベルと別のものにしておく。ラベルは「writable」だったのを「writable-ssd」に変更し、UUIDはGPartedの「New UUID」で新しいものを設定した。
あとは、ブート時にSDカードではなくSSDからOSを起動するように設定を変えれば良い。そのためにはmicroSDにあるブート用のパーティション(FAT32でフォーマットされている)の中にある btcmd.txt
および nobtcmd.txt
を編集すれば良さそうだ。具体的には、 LABEL=writable
となっている部分を、SSDに設定したラベルを使う LABEL=writable-ssd
に変更する。
編集前:
$ cat /boot/firmware/btcmd.txt net.ifnames=0 dwc_otg.lpm_enable=0 console=tty1 root=LABEL=writable rootfstype=ext4 elevator=deadline rootwait fixrtc $ cat /boot/firmware/nobtcmd.txt net.ifnames=0 dwc_otg.lpm_enable=0 console=ttyAMA0,115200 console=tty1 root=LABEL=writable rootfstype=ext4 elevator=deadline rootwait fixrtc
編集後:
$ cat /boot/firmware/btcmd.txt net.ifnames=0 dwc_otg.lpm_enable=0 console=tty1 root=LABEL=writable-ssd rootfstype=ext4 elevator=deadline rootwait fixrtc $ cat /boot/firmware/nobtcmd.txt net.ifnames=0 dwc_otg.lpm_enable=0 console=ttyAMA0,115200 console=tty1 root=LABEL=writable-ssd rootfstype=ext4 elevator=deadline rootwait fixrtc
これでmicroSDとSSDをラズパイ4に接続すると、Linuxが立ち上がった。このLinuxがSSDから立ち上がっていることを確認するために mount
や df -h
を実行すると、 /
が /dev/sda2
になっており、空き容量が210GBに増えていた。めでたしめでたし。
SSD からの起動ですが、PI3の場合は、本体のEE-PROMの書き換えが必要ですが、Pi4の場合は、そのまま、SD Card copy で丸ごとSSD にCopy して SD-card を抜いて起動すればOKです。
私には、UUIDの知識がなく(できればお教え願いたい)、GPARTEDもめったに使わないので、一部だけSSDに移すというよな高度な技はもっていませんので、SDcard copier で丸ごとCOPYしました。
蛇足ですが、pi-3 のEEPROM を 書き換えると元には戻す方法はないとの事。でも、SD-card を差せばそこから起動しますので、実害はないと思います。P14 のEEPROM は一切さわっておりません。
更に蛇足2ですが、ハード的にPi4 は3.3V電源の質が悪く、Pi3 で動いてたI2Cセンサーが誤動作します。センサーの3.3Vライン(直近)に強力なパスコン(3.3μF)を付け、解決はしました。 2023 FEB 26