Ubuntu 22.04 LTS で Microsoft PPA 版の dotnet-sdk-7.0 を導入するメモ

Ubuntu 上で .NET Core を使いたい場合は、Microsoft PPA から dotnet-sdk-7.0 パッケージを導入すると便利です。

Ubuntu に .NET SDK または .NET ランタイムをインストールする

この記事では、Ubuntu に .NET をインストールする方法について説明します。 Microsoft パッケージ リポジトリには、Ubuntu で現在または以前にサポートされていたすべてのバージョンの .NET が含まれています。 Ubuntu 22.04 以降では、Ubuntu パッケージ フィードで一部のバージョンの .NET を使用できます。 使用可能なバージョンの詳細については、「 サポートされているディストリビューション 」セクションを参照してください。

Ubuntu PPA 上にもパッケージが用意されていますが、Microsoft PPA を使う場合は次のようにします。

# Get Ubuntu version
declare repo_version=$(if command -v lsb_release &> /dev/null; then lsb_release -r -s; else grep -oP '(?<=^VERSION_ID=).+' /etc/os-release | tr -d '"'; fi)

# Download Microsoft signing key and repository
wget https://packages.microsoft.com/config/ubuntu/$repo_version/packages-microsoft-prod.deb -O packages-microsoft-prod.deb

# Install Microsoft signing key and repository
sudo dpkg -i packages-microsoft-prod.deb

# Clean up
rm packages-microsoft-prod.deb

# Update packages
sudo apt update

ここまでドキュメントの通りですが、同名で Ubuntu PPA のパッケージがあるため、Microsoft PPA を優先させるために次のようにします。

これをしないと Ubuntu PPA 版のアップデートが起きた場合に上書きされて、dotnet コマンドは効けど SDK が見えなくなったりします。

(不具合が発生している場合は一度 dotnet* package を削除:)

sudo apt purge dotnet*
sudo apt autoremove

Microsoft PPA を優先設定:

sudo sh -c "cat > /etc/apt/preferences.d/dotnet <<'EOF'
Package: dotnet*
Pin: origin packages.microsoft.com
Pin-Priority: 1001
EOF"
sudo sh -c "cat > /etc/apt/preferences.d/aspnet <<'EOF'
Package: aspnet*
Pin: origin packages.microsoft.com
Pin-Priority: 1001
EOF"

dot-net-sdk-7.0 を導入:

sudo apt update
sudo apt install dotnet-sdk-7.0

これで dotnet --info が次のようになれば OK です。

$ dotnet --info
.NET SDK:
 Version:   7.0.302
 Commit:    990cf98a27

ランタイム環境:
 OS Name:     ubuntu
 OS Version:  22.04
 OS Platform: Linux
 RID:         ubuntu.22.04-x64
 Base Path:   /usr/share/dotnet/sdk/7.0.302/

Host:
  Version:      7.0.5
  Architecture: x64
  Commit:       8042d61b17

.NET SDKs installed:
  7.0.302 [/usr/share/dotnet/sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 7.0.5 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 7.0.5 [/usr/share/dotnet/shared/Microsoft.NETCore.App]

Other architectures found:
  None

Environment variables:
  DOTNET_ROOT       [/usr/lib/dotnet]

global.json file:
  Not found

Learn more:
  https://aka.ms/dotnet/info

Download .NET:
  https://aka.ms/dotnet/download

ハローワールド:

$ mkdir hello && cd hello
$ dotnet new console
テンプレート "コンソール アプリ" が正常に作成されました。

作成後の操作を処理しています...
/home/hiromasa/devel/dotnet/hello/hello.csproj を復元しています:
  復元対象のプロジェクトを決定しています...
  /home/hiromasa/devel/dotnet/hello/hello.csproj を復元しました (108 ms)。
正常に復元されました。
$ ls -laF
合計 20
drwxrwxr-x 3 hiromasa hiromasa 4096  5月 28 19:00 ./
drwxrwxr-x 5 hiromasa hiromasa 4096  5月 28 18:59 ../
-rw-rw-r-- 1 hiromasa hiromasa  105  5月 28 19:00 Program.cs
-rw-rw-r-- 1 hiromasa hiromasa  249  5月 28 19:00 hello.csproj
drwxrwxr-x 2 hiromasa hiromasa 4096  5月 28 19:00 obj/
$ dotnet run
Hello, World!
$ file obj/Debug/net7.0/hello.dll
obj/Debug/net7.0/hello.dll: PE32 executable (console) Intel 80386 Mono/.Net assembly, for MS Windows

VS Code の C# Extention でコーディングしてデバッグブレイクしている様子:

Sipeed Lichee Pi 4A 導入記

Sipeed Lichee Pi 4A を購入しました…! プレオーダーして発売を楽しみにしていたハイスペック RISC-V シングルボードコンピュータです。

https://sipeed.com/licheepi4a

Lichee Pi 4A
Powerful RISC-V SBC ever!

TH1520, 12nm, RISC-V 2.0G C910 x4
4 / 8 / 16 GB 64bit LPDDR4X-3733
TF Card, or 16 / 32 / 64 / 128 GB eMMC

今回購入したのは最初期バージョン(販売サイトではβの文字がついています)の 8GB memory + 8GB storage (日本円で 1.7万円ほど)のもとのなり、しばらくすると各バリエーションが増えていくと思います。(そういえばこちらのスペック表に eMMC 8GB 版の記載がされてないですね… Wiki によると16GB 版はなくて 8GB 版になったようです)

https://wiki.sipeed.com/hardware/en/lichee/th1520/lpi4a/1_intro.html

· eMMC: 可选 空贴、 8G、 32G、 128G

メインボード(?) と、LM4A と呼ばれる RISC-V SoC と eMMC・メモリーとが 260P SODIMM で接続されているのが特徴で、おそらく今後 LM4A の各バリエーションの単体売りや、LM4A を使った機器の販売が予定されているのだと思います。楽しみです…!


ドキュメント Wiki(英語翻訳中とのこと) :

https://wiki.sipeed.com/hardware/en/lichee/th1520/lpi4a/1_intro.html

LicheePi 4A 是基于 Lichee Module 4A 核心板的 高性能 RISC-V Linux 开发板,以 TH1520 为主控核心(4xC910@1.85G, RV64GCV,4TOPS@int8 NPU, 50GFLOP GPU),板载最大 16GB 64bit LPDDR4X,128GB eMMC,支持 HDMI+MIPI 双4K 显示输出,支持 4K 摄像头接入,双千兆网口(其中一个支持POE供电)和 4 个 USB3.0 接口,多种音频输入输出(由专用 C906 核心处理)。

Github リポジトリー(まだ 2023-05 時点では空です)

https://github.com/sipeed/LicheePi4A

LicheePi4A info&sdk

Linux カーネルと u-boot

https://github.com/revyos/thead-kernel

https://github.com/revyos/thead-u-boot

本記事(2023-05)は発売直後のものです。OS アップデート等で今後変わる可能性が高い情報ですが、動かしてみた部分をいくつか書いておきたいと思います。

  • HDMI とオーディオコネクタはしっかり奥まで差し込みましょう。特に HDMI は割と硬いので奥まで刺さないと写りません。
  • 空冷用のファンとサーマルグリースシートが付属します。プログラムのビルドなどで RISC-V 4コアを 1.85GHz で連続的に回し続けるとファン付きで 60度くらいまで上がりますので付けましょう。
  • 温度を観測していると SoC sensors が 40度以降でファンが回転始めるようです。部屋が寒いと OS 起動直後は動かない時がありますのでご安心を。そのうち回ります。
  • 電源は USB-C の 2A で SoC と HDMI、USB-SSD、Ethernet の動作は問題ありませんでした。Anker のスマホ充電用 USB Type C アダプタと(オーバースペックですが) 60W 通せる USB Type C to C ケーブルを使いました。
  • 12V DC Power は MISI LCDパネル(基板背面にコネクタあり)などを利用するときに使うとよいとのこと。

以下は OS に初期提供されている Debian イメージを使ったときの話題です。

執筆時点(2023-05) – LPi4A_20230511_gnome.zip

  • 消費電力にも関係しますがメインボード側(LM4A の外側)に付いている WiFi/BT モジュールは(技適の関係もありますので)disable に設定していて未検証です。
  • GPU については現在ドライバーがフルサポートではないようです。自分もいくつかの GPU アクセラレーションを使うソフトが真っ黒になるなどを確認しました。
  • HDMI からの音声出力は現在未サポートです。付属のラインアウトは I2S に接続されており、こちらから音が出ます。(パッチが入っているのを見ましたので、次のリリースで対応されそうです)

eMMC への OS イメージの焼き方

ドキュメント記載の通りですが、執筆時点(2023-05)で最新だった Debian – GNOME(LPi4A_20230511_gnome.zip)イメージを使っています。

ダウンロード:

https://wiki.sipeed.com/hardware/en/lichee/th1520/lpi4a/3_images.html

Mega 云盘:点我 (←ここにあります)

焼き方:

https://wiki.sipeed.com/hardware/en/lichee/th1520/lpi4a/4_burn_image.html

電源の USB-C の上にある BOOT ボタンを押しながら、USB-C を PC の USB-C に接続すれば T-HEAD USB download gadget として認識されるはずです。

自分は PC に Ubuntu/ThinkPad を使っているので dmesg lsusb は次のようになります。

$ sudo dmesg | tail -5
[ 2827.718195] usb 6-1: new high-speed USB device number 4 using xhci_hcd
[ 2827.882776] usb 6-1: New USB device found, idVendor=2345, idProduct=7654, bcdDevice= 2.23
[ 2827.882787] usb 6-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 2827.882791] usb 6-1: Product: USB download gadget
[ 2827.882794] usb 6-1: Manufacturer: T-HEAD
$ lsusb | grep 2345
Bus 006 Device 004: ID 2345:7654 T-HEAD USB download gadget

Windows の方は先程のダウンロード先にドライバーと fastboot バイナリーがあります。

認識できたらアーカイブ内の burn_gnome_gpu.sh を実行すれば OK です。イメージ同梱の fastboot コマンドは Linux バイナリで、burn_gnome_gpu.sh もシェルスクリプトなので、Windows の方も WSL2 の Ubuntu でやったほうが簡単かもしれません。ドライバーも入れる必要がありません(認識のさせ方を記事の最後の「関連」に記載しておきます)

$ pwd
/home/hiromasa/devel/riscv/LPi4A/images/0511_gnome
$ ls -laF
合計 4259020
drwxrwxr-x 2 hiromasa hiromasa       4096  5月 12 12:04 ./
drwxrwxr-x 3 hiromasa hiromasa       4096  5月 17 16:05 ../
-rw-rw-r-- 1 hiromasa hiromasa   62914560  5月 12 11:35 boot-20230510-230240.ext4
-rwxrwxr-x 1 hiromasa hiromasa        368  5月 12 11:29 burn_gnome_gpu.sh*
-rwxrwxr-x 1 hiromasa hiromasa    2230360  5月  5 23:47 fastboot*
-rw-rw-r-- 1 hiromasa hiromasa       2022  5月 12 11:38 image_intro.txt
-rw-r--r-- 1 hiromasa hiromasa      68443  5月 12 11:36 light-lpi4a_1.85GHz.dtb
-rw-r--r-- 1 hiromasa hiromasa      68464  5月 12 11:36 light-lpi4a_2Ghz.dtb
-rw-rw-r-- 1 hiromasa hiromasa        259  5月 12 11:21 md5sum.txt
-rw-rw-r-- 1 hiromasa hiromasa 4294967296  5月 12 11:32 rootfs-20230511-183752-gnome.ext4
-rw-rw-r-- 1 hiromasa hiromasa     957728  5月 12 11:21 u-boot-with-spl-lpi4a-20230510.bin
$ cat burn_gnome_gpu.sh
#! /bin/sh
# Script to flash images via fastboot, edit image path first
#


sudo ./fastboot flash ram ./u-boot-with-spl-lpi4a-20230510.bin
sudo ./fastboot reboot
sleep 10
sudo ./fastboot flash uboot ./u-boot-with-spl-lpi4a-20230510.bin
sudo ./fastboot flash boot ./boot-20230510-230240.ext4
sudo ./fastboot flash root ./rootfs-20230511-183752-gnome.ext4

ちなみに、最初は慎重にやるために burn_gnome_gpu.sh を使わずに 1行づつ手で実行していたのですが flash uboot が waiting device になってしまいうまくいきませんでした。シェルスクリプトでやるとうまくいったので、reboot 後の sleep 10 後のタイミングが重要なのかもしれません。

$ ./fastboot --version
fastboot version 31.0.3-7562133
Installed as /home/hiromasa/devel/riscv/LPi4A/images/0511_gnome/fastboot
$ file fastboot
fastboot: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.24, not stripped
$ ./burn_gnome_gpu.sh
[sudo] hiromasa のパスワード:
Sending 'ram' (935 KB)                             OKAY [  0.248s]
Writing 'ram'                                      OKAY [  0.002s]
Finished. Total time: 0.262s
Rebooting                                          OKAY [  0.001s]
Finished. Total time: 0.202s
Sending 'uboot' (935 KB)                           OKAY [  0.057s]
Writing 'uboot'                                    OKAY [  0.030s]
Finished. Total time: 0.110s
Sending 'boot' (61440 KB)                          OKAY [  1.860s]
Writing 'boot'                                     OKAY [  1.439s]
Finished. Total time: 3.417s
Invalid sparse file format at header magic
Sending sparse 'root' 1/33 (113316 KB)             OKAY [  3.530s]
Writing 'root'                                     OKAY [  3.099s]
Sending sparse 'root' 2/33 (110992 KB)             OKAY [  3.236s]
Writing 'root'                                     OKAY [  2.869s]
...(snip)...
Sending sparse 'root' 32/33 (114684 KB)            OKAY [  3.522s]
Writing 'root'                                     OKAY [  2.620s]
Sending sparse 'root' 33/33 (9492 KB)              OKAY [  0.342s]
Writing 'root'                                     OKAY [  0.225s]
Finished. Total time: 213.113s
$ sudo dmesg | tail -20
[23502.628598] usb 6-1: new high-speed USB device number 4 using xhci_hcd
[23502.793534] usb 6-1: New USB device found, idVendor=2345, idProduct=7654, bcdDevice= 2.23
[23502.793545] usb 6-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[23502.793549] usb 6-1: Product: USB download gadget
[23502.793552] usb 6-1: Manufacturer: T-HEAD
[23546.038600] usb 6-1: USB disconnect, device number 4
# ここで書き込み終了
[23547.584600] usb 6-1: new high-speed USB device number 5 using xhci_hcd
[23547.749402] usb 6-1: New USB device found, idVendor=1234, idProduct=8888, bcdDevice= 2.23
[23547.749415] usb 6-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[23547.749419] usb 6-1: Product: USB download gadget
[23547.749422] usb 6-1: Manufacturer: U-Boot-THEAD
$ lsusb | grep 1234
Bus 006 Device 005: ID 1234:8888 Brain Actuated Technologies USB download gadget

起動

イメージが焼けたら HDMI をしっかり接続して USB-C 電源に接続すれば、ファンが始動し始め GUI が表示されると思います。ちなみにうちの 2560 x 1440 HDMI モニターだとログイン GDM から 2560 x 480 みたいな解像度で起動しました。w

$ cat /etc/debian_version
12.0
$ uname -a
Linux lpi4a 5.10.113-gbb4691fe5572 #1 SMP PREEMPT Wed May 10 14:16:50 UTC 2023 riscv64 GNU/Linux
$ arch
riscv64
$ cat /proc/cpuinfo | grep -e 'isa' -e 'freq'
isa             : rv64imafdcvsu
cpu-freq        : 1.848Ghz
isa             : rv64imafdcvsu
cpu-freq        : 1.848Ghz
isa             : rv64imafdcvsu
cpu-freq        : 1.848Ghz
isa             : rv64imafdcvsu
cpu-freq        : 1.848Ghz
$ lsmod
Module                  Size  Used by
pvrsrvkm             8585216  0
dwc3                 2584576  0
galcore              3170304  0
roles                  40960  1 dwc3
dwc3_thead             28672  0
$ sudo modinfo dwc3
filename:       /lib/modules/5.10.113-gbb4691fe5572/kernel/drivers/usb/dwc3/dwc3.ko
description:    DesignWare USB3 DRD Controller Driver
license:        GPL v2
author:         Felipe Balbi <balbi@ti.com>
alias:          platform:dwc3
alias:          of:N*T*Csynopsys,dwc3C*
alias:          of:N*T*Csynopsys,dwc3
alias:          of:N*T*Csnps,dwc3C*
alias:          of:N*T*Csnps,dwc3
depends:        roles
intree:         Y
name:           dwc3
vermagic:       5.10.113-gbb4691fe5572 SMP preempt mod_unload riscv
parm:           usb_mode:USB mode (int)
parm:           usb_speed:USB speed (int)

ログインユーザは debian と sipeed ユーザの 2つがデフォルトで用意されています。最初は sipeed/licheepi でログインすると良いでしょう。sudo することができます。

もし正しい解像度で Wayland セッションが起動しなかった場合は、GNOME 右上から Settings にたどり着いて Displays 項目から正しい解像度を選択してください。GDM ログイン画面の解像度については、本設定後、以下のコマンドで同じ解像度にできます。

sudo cp ~/.config/monitors.xml /var/lib/gdm3/.config/

eMMC の rootfs は 8GB 弱です。自分は開発ツールチェインを入れる関係で /mnt/ssd に ext4 フォーマットをした外付けの USB 3.1 SSD を接続してマウントしています。

開発専用にして fstab で /home ごとオートマウントしてもいいかもしれません。

$ sudo mkdir /mnt/ssd
$ sudo mount /dev/sda2 /mnt/ssd/
$ mount | grep ssd
/dev/sda2 on /mnt/ssd type ext4 (rw,relatime)
$ pwd
/home/sipeed
$ ls -laF | grep /mnt
lrwxrwxrwx  1 sipeed sipeed   28 May 18 15:51 .cargo -> /mnt/ssd/home/sipeed/.cargo//
lrwxrwxrwx  1 sipeed sipeed   29 May 18 16:10 .rustup -> /mnt/ssd/home/sipeed/.rustup//
lrwxrwxrwx  1 sipeed sipeed   28 May 18 15:51 .wasmer -> /mnt/ssd/home/sipeed/.wasmer/
lrwxrwxrwx  1 sipeed sipeed   30 May 18 15:51 .wasmtime -> /mnt/ssd/home/sipeed/.wasmtime/
lrwxrwxrwx  1 sipeed sipeed   27 May 18 15:51 devel -> /mnt/ssd/home/sipeed/devel//
lrwxrwxrwx  1 sipeed sipeed   25 May 19 03:02 vgm -> /mnt/ssd/home/sipeed/vgm//

gcc/clang や Rust 等を導入しています。また、リソース監視系のコマンドと openssh-server も入れました。

$ sudo apt install curl wget
$ sudo apt install build-essential cmake git
$ sudo apt install libssl-dev pkg-config
$ sudo apt install clang llvm-dev
$ sudo apt install lm-sensors nmon htop
$ sudo apt install ssh openssh-server # ssh リモート接続したい場合
$ sudo apt install ffmpeg

openssh-server で導入した SSH でのリモート接続はデフォルトでパスワード認証になっています。接続先は ip address コマンドで IP アドレスを取得すると良いでしょう。

また、執筆時点では DHCP では起動のたびにアドレスが変わってしまうようなので(MAC アドレスが変わってしまう)、GNOME のネットワーク設定から固定にしたほうがいいかもしれません。(既にパッチが入っているのを確認しましたので次のリリースで修正されるはずです)

Every boot, a random MAC address. #7

導入後のファイルシステム:

$ df -k | grep /
/dev/root        6923792  4687340   1893296  72% /
devtmpfs         3822156        0   3822156   0% /dev
tmpfs            3986160        0   3986160   0% /dev/shm
tmpfs            1594464     2272   1592192   1% /run
tmpfs               5120        8      5112   1% /run/lock
/dev/mmcblk0p2     52197    24842     23055  52% /boot
tmpfs             797232       28    797204   1% /run/user/1001
/dev/sda2      115012332 38564448  71671768  35% /mnt/ssd

なお、Rust toolchaine は Debian の rust-all ではなく rustup で導入しています。上記の通り Rust 系の導入場所はシンボリックリンクで USB-SSD 側に飛ばしていますので rootfs の容量には含まれていません。

$ # rustup
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
$ # wasmer
$ curl https://get.wasmer.io -sSfL | sh
$ # wasmtime
curl https://wasmtime.dev/install.sh -sSf | bash
$ pwd
/home/sipeed/.cargo
$ cat config.toml
[env]
TMPDIR = { value = "/mnt/ssd/home/sipeed/tmp2", force = true }
$ # cargo install する場合は rootfs /tmp を使われないように --target-dir を指定
$ cargo install --target-dir /mnt/ssd/home/sipeed/tmp alacritty

以下、LicheePi 4A 上で Rust アプリケーションのビルドをしている様子。RISC-V 4コア全てが正しく使われ 100% となり、SoC の温度は 60度未満くらいに。ファンコントロールもうまく動作しています。

$ watch df -k
$ watch sensors
$ sudo cat /sys/devices/system/cpu/cpu*/cpufreq/cpuinfo_cur_freq

以下、観測できた CPU クロック周波数です。コメントは自分が書いたものです。

# /sys/devices/system/cpu/cpu*/cpufreq/cpuinfo_cur_freq の結果例
800000  # Silence
1500000 # Normal
1848000 # Peek
300000  # Sleep?

一日中 rustc などでビルドを回していたら、一度だけサーマルスロットリング機能が働いて速度が低下するのを確認しました。断続的に休んだり働いたりする動きとなります。

セルフホスト開発などでヘビーに使う場合は、ターミナルマルチプレクサなどで画面分割して、次のように CPU クロック等を watch して使うと良いでしょう。なお、Debian イメージは最大 1.85GHz で動作するように設定されています。(Wiki にありますが、個体によっては設定を変更して 2GHz でも動作するかもとのことです)

sudo watch -n1 cat /sys/devices/system/cpu/cpu*/cpufreq/cpuinfo_cur_fre

これらのリソース情報をターミナルマルチプレクサ Zellij を使い、リモート ssh 接続時に一気に表示するレイアウトファイル(.config/zellij/layouts/licheepi.kdl)をつくってみました。

後述していますが現在 LPi 上では Zellij が動作しないので、ssh 接続元ホスト側用です。Windows の方は WSL2/Ubuntu を使うと便利だと思います。

zellij -l licheepi

上記のコマンドひとつで以下のような画面となります。

Ubuntu/Alactirry での接続の様子(これでいつでも開発できる…!):

Windows Terminal/WSL2 Ubuntu での様子。

サイズやユーザ・パスワード、IP アドレス、ターミナルサイズに応じて適宜変更してください。

layout {
    tab name="LPi4A" focus=true {
        pane split_direction="vertical" {
            pane size="60%" close_on_exit=true {
                command "sshpass"
                args "-p" "licheepi" "ssh" "sipeed@172.16.15.201"
            }
            pane size="40%" {
                pane size="25%" close_on_exit=true {
                    command "sshpass"
                    args "-p" "licheepi" "ssh" "sipeed@172.16.15.201" "-t" "watch" "-n5" "df" "-k"
                }
                pane size="16%" close_on_exit=true {
                    command "sshpass"
                    args "-p" "licheepi" "ssh" "sipeed@172.16.15.201" "-t" "watch" "sudo" "cat" "/sys/devices/system/cpu/cpu*/cpufreq/cpuinfo_cur_freq"
                }
                pane size="16%" close_on_exit=true {
                    command "sshpass"
                    args "-p" "licheepi" "ssh" "sipeed@172.16.15.201" "-t" "watch" "sensors"
                }
                pane size="43%" close_on_exit=true {
                    command "sshpass"
                    args "-p" "licheepi" "ssh" "sipeed@172.16.15.201" "-t" "htop"
                }
            }
        }
    }
    tab name="Host"
    default_tab_template {
        pane size=1 borderless=true {
            plugin location="zellij:tab-bar"
        }
        children
        pane size=2 borderless=true {
            plugin location="zellij:status-bar"
        }
    }
}

ssh 接続にはパスワード認証を使っています。また LPi Debian ユーザには sudo に NOPASSWORD していますので、ご理解の上、必要ならアレンジしてください。

ホスト側 Linux

sudo apt install sshpass

LPi 側 Debian

echo "sipeed ALL=(ALL:ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/users

あとこれは趣味ですが、デフォルトエディタを vim にしています。

$ sudo update-alternatives --config editor
There are 3 choices for the alternative editor (providing /usr/bin/editor).

  Selection    Path                Priority   Status
------------------------------------------------------------
  0            /bin/nano            40        auto mode
  1            /bin/nano            40        manual mode
* 2            /usr/bin/vim.basic   30        manual mode
  3            /usr/bin/vim.tiny    15        manual mode

Press <enter> to keep the current choice[*], or type selection number:

Alacritty

試しに、GPU アクセラレーションを使う Rust 製のターミナルエミュレータである Alacritty のビルドを LPi 上でしてみました。

$ sudo apt install pkg-config libfontconfig-dev
$ time cargo install --target-dir /mnt/ssd/home/sipeed/tmp alacritty
...(snip)..
   Installed package `alacritty v0.12.0` (executable `alacritty`)
real    16m22.428s
user    60m41.044s
sys     1m26.451s

起動ですが(予想はしていましたが)恐らく GPU ドライバーが未完成のため真っ黒画面でした。コマンドを打つとカーソルは動いているのが見えるので動作はしていそうです。(スクリーンショット右下で CPU が MAX になっているのは偶然です)

Zellij

ターミナルマルチプレクサ・ワークスペースである Zellij のビルド。こちらも Rust 製。

$ time cargo install --target-dir /mnt/ssd/home/sipeed/tmp zellij
real    51m20.308s
user    127m50.878s
sys     2m56.126s
$ zellij
Error occurred in server:

  × Thread 'async-std/runtime' panicked.
  ├─▶ At /home/sipeed/.cargo/registry/src/github.com-1ecc6299db9ec823/wasmer-compiler-cranelift-2.3.0/src/config.rs:73:45
  ╰─▶ construct Cranelift ISA for triple: Unsupported

実はこれも予想通りの結果なのですが、Zellij がプラグインシステムのために内蔵する WebAssembly ランタイム(Wasmer 2.3)が riscv64gc-unknown-linux-gnu に対応していないため Unsuppoted でダウンしました。OK です。

上述の通り、本記事のスクリーンショットで使われている Zellij は、ssh 接続元のホスト側で動作しているものです。 LPi 4A 側でターミナルマルチプレクサを使いたい場合は tmux を使うと良いでしょう。

sudo apt install tmux

Wasmer

WebAssembly ランタイムである Wasmer(3.2 以降で RISC-V を initial support)を導入して、自分がつくっている VGM parser を動作させてみました。FM 音源ライブラリである ymfm を使って波形合成を行っています。

Wasmer の速度が思ったとおりにでなくてリアルタイム演算できていないのですが、メインボード側の I2S デバイスで発音しています。(詳しくは動画概要欄をご覧ください)

Rust LLVM ビルドしたプログラムの実行速度については現在いろいろ検証中です。どうも生成するバイナリーが機械の性能に対して想定より遅いような気がしていますが、はっきりとまだ特定できていません。

target=riscv64gc-unknown-linux-gnu だけでなく、LLVM に RISC-V C910 に合わせた optimize option を指定する必要があるかもしれません。

https://github.com/h1romas4/libymfm.wasm

This repository is an experimental WebAssembly build of the [ymfm](https://github.com/aaronsgiles/ymfm) Yamaha FM sound cores library.

自分がビルドをミスしており最適化オプションがうまくコンパイラに渡っていないだけでした…。修正後はシングルスレッド性能になりますが、非常にパワフルな速度で動作しています。

実行メモ:

$ # 54.vzg: Music Duration: 00:01:41.94
$ time wasmer run --cranelift ~/.local/share/libymfm/libymfm-cli.wasm --mapdir /:"$(pwd)" -- -r 44100 54.vgz > /dev/null

real    0m44.462s
user    0m42.783s
sys     0m1.856s
$ wasmer run --cranelift ~/.local/share/libymfm/libymfm-cli.wasm --mapdir /:"$(pwd)" \
-- -r 44100 54.vgz | ffplay -infbuf -nodisp -autoexit -f f32le -ar 44100 -ac 2 -i -

顛末をツイッターでいくつかつぶやいていますのでご参考程度で…

https://twitter.com/h1romas4/status/1660172653704146944

サウンド系メモ

Debian sid なので PipeWire と WirePlumber でオーディオデバイスが制御されています。Wayland セッション「未ログイン時」は auto_null というフォールバックデバイスになって I2S から発音しないようです。

LPi 関係ありませんが、、

pw-top

$ pw-top # Wayland session login 時
alsa_output.platform-lightsound_1.stereo-fallback
$ pw-top # Wayland session no login 時
auto_null
$ # wireplumber.service がこのあたりで動的に制御しているようだ
$ ls -alF /usr/share/wireplumber/scripts
$ ls -alF /usr/share/wireplumber/main.lua.d

ssh 経由で GUI を使わずに I2S を発音させたい場合は、(この方法が最良か分かりませんが)とりあえず、ユーザーを audio グループに入れておくと /dev/snd 配下の ALSA sound device が見えて認識され、Wayland セッションに入らなくても cli コマンドから PipeWire 経由で音声が再生できるようになります。

$ sudo usermod -aG audio sipeed
$ sudo reboot
$ sudo apt install alsa-utils
$ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: LightSoundCard [Light-Sound-Card], device 0: light-i2s-dai-ES8156 HiFi es8156.5-0008-0 [light-i2s-dai-ES8156 HiFi es8156.5-0008-0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

ALSA 系メモ:

$ sudo dmesg | grep -A1 ALSA
[    5.765048] ALSA device list:
[    5.772741]   #0: Light-Sound-Card
$ cat /proc/devices | grep alsa
116 alsa
$ cat /proc/asound/devices
  0: [ 0]   : control
 16: [ 0- 0]: digital audio playback
 25: [ 0- 1]: digital audio capture
 33:        : timer
$ cat /proc/asound/cards
 0 [LightSoundCard ]: Light-Sound-Car - Light-Sound-Card
                      Light-Sound-Card
$ cat /proc/asound/pcm
00-00: light-i2s-dai-ES8156 HiFi es8156.5-0008-0 : light-i2s-dai-ES8156 HiFi es8156.5-0008-0 : playback 1
00-01: light-i2s-dai-ES7210 ADC 0 es7210.5-0040-1 : light-i2s-dai-ES7210 ADC 0 es7210.5-0040-1 : capture 1
$ ls -laF /dev/snd/
total 0
drwxr-xr-x   3 root root      140 Feb 28 11:15 ./
drwxr-xr-x  17 root root    14000 May 22 21:36 ../
drwxr-xr-x   2 root root       60 Feb 28 11:15 by-path/
crw-rw----+  1 root audio 116,  0 Feb 28 11:15 controlC0
crw-rw----+  1 root audio 116, 16 Feb 28 11:15 pcmC0D0p
crw-rw----+  1 root audio 116, 25 Feb 28 11:15 pcmC0D1c
crw-rw----+  1 root audio 116, 33 Feb 28 11:15 timer
$ # もし ALSA 直で音を鳴らす場合
$ aplay -D hw:0,0 test.wav

pipewire 経由で音がノイズだけになったり、サンプリングレートがおかしくなった時(何かのタイミングで発生):

$ systemctl --user restart pipewire.service pipewire-pulse.service

PipeWire 経由の cli からのボリューム制御はこちらの pw-volume が便利でした。Rust 製なのでビルドして使うと良いでしょう。(標準の wpctrl コマンドでも良いかもしれません)

https://github.com/smasher164/pw-volume

Basic interface to PipeWire volume controls

$ git colne https://github.com/smasher164/pw-volume.git
$ cd pw-volume
$ cargo build --release
$ target/release/pw-volume --help
pw-volume
Basic interface to PipeWire volume controls

USAGE:
    pw-volume <SUBCOMMAND>

OPTIONS:
    -h, --help    Prints help information

SUBCOMMANDS:
    change    adjusts volume by decimal percentage, e.g. '+1%', '-0.5%'
    mute      mutes audio [possible values: on, off, toggle]
    status    get volume and mute information
$ cp -p target/release/pw-volume ~/.local/bin/
$ pw-volume status
{"percentage":6, "tooltip":"6.3997%"}

なお、メインボード側に配置されているラインアウト I2S の音質ですが、オーディオブロックのハイパスフィルター値が高く設定されており低音が若干出にくくなっています。次の rev では修正されるとのこと。

MAME

Debian sid に MAME 0.251 が入っています。

$ sudo apt install mame

残念ながら SDL2 が opengl を見つけられないというメッセージで起動せず。

$ ./mame -window -video soft -window -videodriver wayland -audiodriver pipewire
OpenGL not supported on this driver: Couldn't find matching EGL config (call to eglChooseConfig failed, reporting an error of EGL_SUCCESS)
video_init: Initialization failed!

gles なら?vulkan なら?等

$ ./mame -window -video bgfx -bgfx_backend gles -window
../../../../../3rdparty/bgfx/src/glcontext_glx.cpp (198): BGFX FATAL 0x00000002: Failed to create GL 2.1 context.
Aborted
$ ./mame -window -video bgfx -bgfx_backend vulkan -window
../../../../../3rdparty/bgfx/src/glcontext_glx.cpp (198): BGFX FATAL 0x00000002: Failed to create GL 2.1 context.
Aborted
$ sudo apt install vulkan-tools
$ vulkaninfo
ERROR: [Loader Message] Code 0 : vkCreateInstance: Found no drivers!
Cannot create Vulkan instance.
This problem is often caused by a faulty installation of the Vulkan driver or attempting to use a GPU that does not support Vulkan.
ERROR at ./vulkaninfo/vulkaninfo.h:674:vkCreateInstance failed with ERROR_INCOMPATIBLE_DRIVER
$ sudo systemctl status pvrsrvkm.service
× pvrsrvkm.service - Imagination GPU BXM-4-64 driver init Service.
     Loaded: loaded (/etc/systemd/system/pvrsrvkm.service; enabled; preset: enabled)
     Active: failed (Result: exit-code) since Fri 2023-05-26 14:50:32 UTC; 1 day 23h ago
   Duration: 192ms
    Process: 385 ExecStart=sh usr/share/gpu/insmod.sh (code=exited, status=1/FAILURE)
   Main PID: 385 (code=exited, status=1/FAILURE)
        CPU: 171ms

May 26 14:50:32 lpi4a systemd[1]: Started pvrsrvkm.service - Imagination GPU BXM-4-64 driver init Service..
May 26 14:50:32 lpi4a sh[387]: insmod: ERROR: could not insert module /lib/modules/5.10.113-gbb4691fe5572/extra/pvrsrvkm.ko: File exists
May 26 14:50:32 lpi4a systemd[1]: pvrsrvkm.service: Main process exited, code=exited, status=1/FAILURE
May 26 14:50:32 lpi4a systemd[1]: pvrsrvkm.service: Failed with result 'exit-code'.
$ ls -alF /lib/firmware/rgx*
-rwxr-xr-x 1 debian debian 122880 May 26 14:14 /lib/firmware/rgx.fw.36.52.104.182*
-rwxr-xr-x 1 debian debian 306660 May 26 14:14 /lib/firmware/rgx.sh.36.52.104.182*
$ sudo modinfo pvrsrvkm
filename:       /lib/modules/5.10.113-gbb4691fe5572/extra/pvrsrvkm.ko
license:        Dual MIT/GPL
author:         Imagination Technologies Ltd. <gpl-support@imgtec.com>
alias:          platform:rgxthead
alias:          of:N*T*Cimg,gpuC*
alias:          of:N*T*Cimg,gpu
depends:
name:           pvrsrvkm
vermagic:       5.10.113-gbb4691fe5572 SMP preempt mod_unload riscv
parm:           gPVRDebugLevel:Sets the level of debug output (default 0x7) (uint)

自分がなにか勘違いしている可能性もありますが、いったん GPU ドライバーのアップデートを楽しみに待ちたいと思います。

なお MAME のビルドについてですが、Debian sid 版の 0.251 より先の執筆時最新の MAME 0.254 との間で、ビルドスクリプトから RISC-V へ渡るデフォルトコンパイルオプションが変わっていて、コンパイルとリンクがエラーで落ちてしまうようなので、最新 MAME ソースからビルドする場合は以下の patch を当ててみてください。

riscv64 build patch

diff --git a/scripts/genie.lua b/scripts/genie.lua
index 9a1f3140..310ec2f2 100644
--- a/scripts/genie.lua
+++ b/scripts/genie.lua
@@ -1134,6 +1134,10 @@ if (_OPTIONS["PLATFORM"]=="arm64") then
 end

 if (_OPTIONS["PLATFORM"]=="riscv64") then
+       buildoptions {
+               "-Wno-cast-align",
+               "-fpic",
+       }
        defines {
                "PTR64=1",
        }

LPi 4A GPU ドライバーがリリースされれば、MAME 0.253 から入った新 m68000 エミュコアを RISC-V で試すことができるはずです。

ちなみにコンパイル時間ですが、MAME のビルドをしている方だとおなじみだと思いますが make -j4 などで並行コンパイルすると、src/emu 配下の emumem* あたりでメモリーを 8GB 近くまでとってしまい I/O wait スローダウンしてしまうパターンがありますので、make -j3 くらいがいいかと思います。

$ sudo apt-get install libsdl2-dev libsdl2-ttf-dev libasound2-dev libxinerama-dev libxi-dev # qtbase5-dev qtbase5-dev-tools
$ git clone https://github.com/mamedev/mame.git
$ cd mame
$ # apply riscv64 build patch - scripts/genie.lua
$ time make -j3 SOURCES=src/mame/neogeo/neogeo.cpp USE_QTDEBUG=0

neogeo ドライバーだけ指定して 120分といったところでした。今回はベンチマーク的にセルフコンパイル(USB3 -SSD を使用 )していますが、さすがにこの規模になるとクロスコンパイル環境をつくったほうがいいかもしれません。

その他

Node.js は unofficial build で RISC-V 版があります。動くのかな?(未検証)

https://unofficial-builds.nodejs.org/download/release/v18.16.0/

node-v18.16.0-linux-riscv64.tar.gz

Chromium はメインラインに RISC-V ビルドがないようで対応版を以下で作業されているようです。まだ動作しないとドキュメントにはありました(未検証)

https://github.com/revyos/chromium-109.0.5414.119

Android が RISC-V 対応するとどこかで見たのでそのうちメインラインにも入るかもしれません。

ちなみにまだ詳しく見ていないですが、Firefox の WebAssembly モジュールは RISC-V では disable になっているような気がします(軽く動かしたら WebAssembly Object がないとエラーになりました)

おわりに

というわけで、非常に高性能な実機の RISC-V Linux を堪能できて楽しいボードだと感じています。各アプリケーションの RISC-V 対応も進化が見られてホットですね。

LM4A モジュールが単体発売されたら、自作でシンセサイザーになるボードをつくってみたいと夢見ていろいろ検証中です。モジュールを使ったプロダクトの発売もいろいろ予定されているようなので、そちらも楽しみにしています…!


関連

Powerline 説明用メモ

Linux のプロンプトを彩る Powerline ですが、説明用メモ画像です。

以下、キャラクターコードごとそのままコピペ。

~  devel  rust  hello  $  echo 'hego' | grep 'hoge' > /dev/null
~  devel  rust  hello  $  # ← コマンドの $? が 0 以外だと赤くなる
~  devel  rust  hello  $  echo 'hego' | grep 'hego' > /dev/null
~  devel  rust  hello  $  # ← コマンドが $? が 0 なので赤くならない
~  devel  rust  hello  $ 
~  devel  rust  hello  $  cd ../../amd64/mame/
~  devel  amd64  mame  master  $  # git 配下の場合はカレントブランチ名がでる
~  devel  amd64  mame  master  $  echo "test/" >> .gitignore
~  devel  amd64  mame  master  ✎  $  # 未コミットだと赤鉛筆マーク
~  devel  amd64  mame  master  ✎  $  git add .gitignore
~  devel  amd64  mame  master  ✔  $  # ステージングで緑
~  devel  amd64  mame  master  ✔  $  git commit -m 'test'
[master 2058a2e6c50] test
 1 file changed, 1 insertion(+)
~  devel  amd64  mame  master  ⬆  $  # コミット済み & 未push で上矢印
~  devel  amd64  mame  master  ⬆  $  git reset --hard HEAD^1
HEAD is now at fb2b5745d1d namco/namcos10.cpp: Add MP3 decoder support to the MEM(P3) board. (#11210)
~  devel  amd64  mame  master  $  # 元通り

自分は Rust cargo でお手軽に導入できて高速な powerline-rs を使っています。

powerline-shell rewritten in Rust. Inspired by powerline-go.

$ cargo install powerline-rs
$ vi ~/.bashrc # 以下を追加
prompt() {
    PS1="$(powerline-rs --shell bash $?)"
}
PROMPT_COMMAND=prompt

Powerline フォントは HackGen Console NFが良いと思います…!(なお、最初のスクショは Ubuntu/Alacritty 上の Ricty Diminished for Powerline です)

https://github.com/yuru7/HackGen

白源 (はくげん/HackGen) は、プログラミング向け英文フォント Hack と、源ノ角ゴシックの派生フォント源柔ゴシックを合成したプログラミングフォントです。

ダウンロード(執筆時点で v2.9.0 です)

https://github.com/yuru7/HackGen/releases/tag/v2.9.0

HackGen_NF_v2.9.0.zip

以下、Windows Terminal と HackGen Console NF の表示です。


関連