NanoPi NEO3 Plus で フレームバッファを使う

Armbianのようにはいかない

Armbianでは…

 ・/boot/armbianEnv.txt を書き換える
 ・dts ファイルを作って armbian-add-overlay を実行する

という2ステップで SPI が有効になり、モニタが使える。(フレームバッファ経由で)

あ、もちろん、Linux 側がモニタのドライバを持っていること前提ね。
(最近のLinuxなら、そして、流通している多くのモニタなら、ドライバ持ってることが多いかと)

ところが、同じ NanoPi シリーズでも NEO3 Plus ではまだ上記ステップではできない(2026/07/15時点)
Armbian もまだなければ、Friendly Elec 公式のOSイメージでもできない。

なので、Armbian に比べたらかなり面倒な手順を踏んで設定してあげないとならない。

てことで、その手順を以下に。

ならどうすればいいか

NEO3 Plus だと eMMC 運用もあるかと思うけど、SD カード運用が前提ということにしたい。
(eMMCでもパーティション確認さえすればやることは同じ)

で、その SD カードの特定パーティションに、Armbian でやるような dts ファイルをまとめたものが入ってる。
(正確には dts ファイルを元に作成された dtb ファイルの塊)

なので、「dts ファイルを用意して、dtb に変換して」というところまでは Armbian と似た感じの作法になる。
(手順が面倒だけど)

そして、変換したものを、SD カードの特定パーティションに書き込むことで目的がかなえられる。

必要なファイル、ツール類の入手

ツール類が Ubuntu 20.04、22.04、24.04 までしか対応してないのでご注意を。
26.04 では使えない。

そして、Friendly Elec は 20.04 で動作確認を撮っているようなので、20.04 が好ましい。
が、うちでは 22.04 でも問題なかった。
以下の作業を行うだけならば。

また、参照したのは公式の Wiki の「7 How to Compile」あたりから

NanoPi NEO3 Plus – FriendlyELEC WiKi

実作業は以下の通り。

$ sudo apt update
$ sudo apt install curl ccache

$ sudo bash -c "$(curl -fsSL https://raw.githubusercontent.com/friendlyarm/build-env-on-ubuntu-bionic/master/install.sh)"

(それなりに時間がかかるのでコーヒーでも飲みながら待つ…)

$ export PATH=/opt/FriendlyARM/toolchain/11.3-aarch64/bin:$PATH
$ export GCC_COLORS=auto
$ . ~/.bashrc

$ aarch64-linux-gcc -v
Using built-in specs.
COLLECT_GCC=aarch64-linux-gcc
COLLECT_LTO_WRAPPER=/opt/FriendlyARM/toolchain/11.3-aarch64/libexec/gcc/aarch64-cortexa53-linux-gnu/11.3.0/lto-wrapper
Target: aarch64-cortexa53-linux-gnu
Configured with:(長いので省略)
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 11.3.0 (ctng-1.25.0-119g-FA)

(クロスコンパイルになるので、aarch64-linux-gcc は上記になってるか確認しておいた方がいい)

$ git clone https://github.com/friendlyarm/kernel-rockchip --single-branch --depth 1 -b nanopi6-v6.1.y kernel-rockchip
$ cd kernel-rockchip
$ export PATH=/opt/FriendlyARM/toolchain/11.3-aarch64/bin/:$PATH
$ touch .scmversion
$ make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 nanopi5_linux_defconfig

$ wget https://raw.githubusercontent.com/friendlyarm/sd-fuse_rk3528/kernel-6.1.y/tools/mkkrnlimg
$ chmod 755 mkkrnlimg
$ wget https://raw.githubusercontent.com/friendlyarm/sd-fuse_rk3528/kernel-6.1.y/tools/resource_tool
$ chmod 755 resource_tool
$ wget https://raw.githubusercontent.com/friendlyarm/sd-fuse_rk3528/kernel-6.1.y/prebuilt/boot/logo.bmp
$ wget https://raw.githubusercontent.com/friendlyarm/sd-fuse_rk3528/kernel-6.1.y/prebuilt/boot/logo_kernel.bmp

最後の方、2行になってしまっているコマンドもあるけど、1行で書ききること。
(\使って複数行にしてもかまわないけど)

dts ファイルの編集とコンパイルとその他

dts ファイルは設定があれこれ書かれたファイルで、これを編集することで ILI3941 を起動時に有効にして、フレームバッファを使えるようになる。

編集対象のファイルは下記ディレクトリにある。

arch/arm64/boot/dts/rockchip/

この中にある2つのファイルがターゲット。

rk3528-nanopi-common.dtsi
rk3528-nanopi-rev02.dts

まずは rk3528-nanopi-common.dtsi から。
(Rockchip RK3528 を搭載した NanoPi 共通の設定ファイル)

        chosen: chosen {
                bootargs = "earlycon=uart8250,mmio32,0xff9f0000 console=ttyFIQ0 coherent_pool=1m fbcon=map:1 console=tty1";
                bootargs_ext = "root=/dev/mmcblk2p8 rw rootfstype=ext4 rootflags=discard";
        };

赤文字部分が変更、というか追記した部分。
ここも複数行に分かれちゃってるけど、1行で書ききってね。

続いて rk3528-nanopi-rev02.dts を編集。
(機種ごとに固有の設定が書かれたファイル)

まずは赤文字の部分を探す。探して削除!
(削除じゃなくてコメントアウトでももちろん良い)

&spi1 {
        status = "okay";
        num-cs = <2>;
        pinctrl-0 = <&spi1_csn0 &spi1_csn1 &spi1_pins>;

        spidev0: spidev@0 {
                status = "okay";
                compatible = "rockchip,spidev";
                reg = <0>;
                spi-max-frequency = <10000000>;
        };
};

削除した後に下記赤文字部分を書く。

&spi1 {
        status = "okay";
        num-cs = <2>;
        pinctrl-0 = <&spi1_csn0 &spi1_csn1 &spi1_pins>;

        spidev0: ili9341@0 {
                status = "okay";
                compatible = "ilitek,ili9341";
                reg = <0>;
                spi-max-frequency = <32000000>;
                reset-gpios = <&gpio1 13 GPIO_ACTIVE_LOW>;
                dc-gpios = <&gpio1 12 GPIO_ACTIVE_HIGH>;
                rotate = <90>;
                bgr;
                fps = <30>;
                buswidth = <8>;
           };
};

reset-gpios = <&gpio1 13 GPIO_ACTIVE_LOW>;
dc-gpios = <&gpio1 12 GPIO_ACTIVE_HIGH>;

ここの 13 や 12 という番号は GPIO の番号になるけど、公式 Wiki のPin#で言うと、それぞれ 18、16 になる。
GPIO1_B5 や GPIO1_B4 ということだね。

この番号の計算がちょっと面倒と言えば面倒なので、省略w

で、編集が終わったら、コンパイル。

もし、arch/arm64/boot/dts/rockchip/ に移動していたら、kernel-rockchip まで戻り、以下を実行。

$ make CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 dtbs

コンパイルが終わったら、dts → dtb が出来上がっているので、それを含めた resource.img を作る。

$ ./resource_tool --dtbname arch/arm64/boot/dts/rockchip/rk3528-nanopi-rev02.dtb \
  logo.bmp logo_kernel.bmp

公式 Wiki だと、「rk3528-nanopi*-rev*.dtb」みたいに、ワイルドカードが使われていたけど、NEO3 Plus だけで使うイメージなら、上記のように nanopi-rev02 固定で良い。

これで resource.img が出来上がった。

出来上がった resource.img をSDカードに書き込む

既に NEO3 Plus 上で FE公式Ubuntu が動いている、という前提で、その SD カードにさっきコンパイルした resource.img を書き込むことになる。

なるんだけど、書き込み先を間違えると当然起動しないので要注意。

ということでまずはパーティションがどうなっているか一応見ておこう。

$ sudo parted /dev/mmcblk0 print
Model: SD SE064 (sd/mmc)
Disk /dev/mmcblk0: 61.9GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags:

Number  Start   End     Size    File system  Name      Flags
 1      8389kB  12.6MB  4194kB               uboot
 2      12.6MB  16.8MB  4194kB               misc
 3      16.8MB  21.0MB  4194kB               dtbo
 4      21.0MB  37.7MB  16.8MB               resource
 5      37.7MB  79.7MB  41.9MB               kernel
 6      79.7MB  113MB   33.6MB               boot
 7      113MB   147MB   33.6MB               recovery
 8      147MB   2496MB  2349MB  ext4         rootfs
 9      2496MB  61.9GB  59.4GB  ext4         userdata

4番目のパーティションが resource となっているので、ここに resource.img を書き込んでやればいい。

書込みには dd を使って以下のようにする。

$ sudo dd if=resource.img of=/dev/mmcblk0p4 bs=1M

書込みはほぼ一瞬で完了するほど小さなファイルサイズなので、終わったら、起動してくることを祈りつつ…

$ sudo reboot

と再起動。

モニタを SPI に繋げていれば、最終的にログインプロンプトが表示されるはず! されたよね!?

動画を流し込む例

ログインプロンプトが表示されていると、カーソル位置がブリンクするけど、まぁ、とりあえず確認なのでそのまま実行してみた。

ffmpeg もフレームバッファを扱うので、ffmpeg を使うけど、その前に ffmpeg が入ってないのでインストール。

$ sudo apt install ffmpeg

そして、映像表示。

$ sudo ffmpeg -i rtsp://[id]:[pw]@[ip adress]/ -vf scale=320:240 -f rawvideo -pix_fmt rgb565le -f fbdev /dev/fb1

rtsp://[id]:[pw]@[ip adress]/ この部分は動画でもOK
そして、これを実行すれば SPI に繋がった ILI9341 なモニタに映像が流れる。

一応確認

フレームバッファが現れたか確認。
尚、NEO3 Plus だと最初から fb0 は存在している。どうやら HDMI ようだが…(物理端子は出てないけど)

$ ls -al /dev/fb(
-bash: syntax error near unexpected token `('
root@NanoPi-NEO3-Plus:~# ls -al /dev/fb*
crw-rw---- 1 root video 29, 0 Jul 15 14:34 /dev/fb0
crw-rw---- 1 root video 29, 1 Jul 15 14:34 /dev/fb1

もう少し詳しく見るのなら…

$ apt install fbset

と、fbset をインストールして、下記のように実行。
fb0 は 解像度からしてなんとなく HDMI みたい。

$ sudo fbset -i -fb /dev/fb0

mode "1920x1080"
    geometry 1920 1080 1920 2560 32
    timings 0 0 0 0 0 0 0
    accel true
    rgba 8/16,8/8,8/0,0/0
endmode

Frame buffer device information:
    Name        : rockchipdrmfb
    Address     : 0
    Size        : 19660800
    Type        : PACKED PIXELS
    Visual      : TRUECOLOR
    XPanStep    : 1
    YPanStep    : 1
    YWrapStep   : 0
    LineLength  : 7680
    Accelerator : No

続いて fb1

$ sudo fbset -i -fb /dev/fb1

mode "320x240"
    geometry 320 240 320 240 16
    timings 0 0 0 0 0 0 0
    nonstd 1
    rgba 5/11,6/5,5/0,0/0
endmode

Frame buffer device information:
    Name        : fb_ili9341
    Address     : 0
    Size        : 153600
    Type        : PACKED PIXELS
    Visual      : TRUECOLOR
    XPanStep    : 0
    YPanStep    : 0
    YWrapStep   : 0
    LineLength  : 640
    Accelerator : No

こんな感じで fb_ili9341 とともに使用可能になっていた。

この記事にコメントしてみる