NanoPi neo3 を最新イメージで動かしたいね

# NanoPi Neo3 とは

 NanoPi Neo3 は、ミニサイズの　CPU　ボードです。

以前紹介した

FreeBSD で NanoPi Neo2

https://qiita.com/s_mitu/items/e271f0addc202c323fec

NanoPi Neo でFreeBSD （動作編)

https://qiita.com/s_mitu/items/cd78c0b7c4240cdd3ba6

といったCPUボードの後継になります。

 これらのボードの共通の特徴は

* サイズは極小
* 無線 LAN/Bluetooth　無し
* HDMIのような画面出力も無し
* 有線　LAN １　Port
* USB　１ Port

 宅内の極小サーバの構築などの用途が考えられます。
 画面出力がないのでキーボードとディスプレイを繋いで、といったPCやRaspberryPi のような使い方はできません。シリアルコンソールかネットワークからの　ssh 接続で操作します。

 NEO3の詳細や以前紹介した　NEO２との違いは公式サイトを参照してください。

https://www.friendlyarm.com/index.php?route=product/product&product_id=279

 SoCが変わってますが、CPUは同じARM Architecture で、クロック数やコア数も同じです。オンボードのUSB端子がUSB3になっているのが大きな違いでしょうか。またボードのサイズは一回り大きくなっています。給電は micro USB から USB TypeC になっています。

左が NEO2 右が　NEO3
![neo2_neo3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103137/b0dd45f5-3bc0-c0a7-68c1-168e7f8f3e16.jpeg)


# FreeBSD の公式最新配布イメージで動かすには　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　

 FreeBSD での動作自体は去年　＠mina_im さんが

https://qiita.com/mina_im/items/5d5d06b5a2606be0b61c

で確認しています。しかし、動作確認したイメージはかつて作られた拾い物ということでアップデートされていません。できれば　download.FreeBSD.org で公開している最新イメージを動かす方法があるといいですね。

で、検索すると The FreeBSD forums(forums.freebsd.org) にやり方が書いてありましたので試してみます。
説明は Linux 環境での説明になってるので FreeBSD 環境用に合わせています。

https://forums.freebsd.org/threads/nanopi-neo-3-rockchip-rk3328.76449/#post-493043

## aarch64 公式最新イメージをダウンロード

https://download.freebsd.org/ftp/snapshots/arm64/aarch64/ISO-IMAGES/14.0/

上記ページにおいてある ROCK64 のイメージをダウンロードします。

```
wget https://download.freebsd.org/ftp/snapshots/arm64/aarch64/ISO-IMAGES/14.0/FreeBSD-14.0-CURRENT-arm64-aarch64-ROCK64-20211209-b7c55487ff2-251490.img.xz
```

これを展開しておきます。

```
xz -d FreeBSD-14.0-CURRENT-arm64-aarch64-ROCK64-20211209-b7c55487ff2-251490.img.xz
```

 これで　FreeBSD-14.0-CURRENT-arm64-aarch64-ROCK64-20211209-b7c55487ff2-251490.imgが展開されます。

## ブート用のファイルをダウンロード

ブート用のファイルの入ったDebianパッケージをダウンロードして展開

```
wget https://mirrors.dotsrc.org/armbian-apt/pool/main/l/linux-u-boot-nanopineo3-current/linux-u-boot-current-nanopineo3_21.02.1_arm64.deb
ar x linux-u-boot-current-nanopineo3_21.02.1_arm64.deb
tar xzvf data.tar.gz
```

欲しいファイルはこの三つです。
```
./usr/lib/linux-u-boot-current-nanopineo3_21.02.1_arm64/idbloader.bin
./usr/lib/linux-u-boot-current-nanopineo3_21.02.1_arm64/trust.bin
./usr/lib/linux-u-boot-current-nanopineo3_21.02.1_arm64/uboot.img
```

## dd でブート用ファイルを公式イメージの特定アドレスに書き込む

Forum の書き込みではこんなコマンドを実行しろとなっています（linux 用なので of= の外部ストレージのデバイスノード指定が/dev/sdbになっています)

```
dd if=idbloader.bin of=/dev/sdb seek=64 conv=notrunc
dd if=uboot.img of=/dev/sdb seek=16384 conv=notrunc
dd if=trust.bin of=/dev/sdb seek=24576 conv=notrunc
```

このseekで指定されている64 や16384 というアドレスはなんじゃらほい？と思ったら RockChip の都合のようです。
下記の　RockChipの wiki に詳細が書かれていました。

http://opensource.rock-chips.com/wiki_Boot_option

こちらの表によると、

* pre-loader の idbloader.bin が 0x40(64)
* その後に実行されるuboot.img が 0x4000(16384)
* idbloader.bin から使われる trust.bin が 0x6000(24576)

にそれぞれ配置しなくてはいけないようです。

Linux環境ではROCK６４のイメージをSDに書き込んだ後に書き込んでますが、FreeBSD の私の環境では書き込みエラーとなりました。デバイスに書き込んでからだと制限でうまくいかないようなので、イメージファイルに先に書き込んでからそのイメージを　SD に書き込みます。/dev/da0 が　SDだとすると（うっかり他の外部ストレージに出力しないように確認してから）。

```
(イメージファイルにブート用ファイルを位置指定で書き込み）
# dd if=./usr/lib/linux-u-boot-current-nanopineo3_21.02.1_arm64/idbloader.bin of=FreeBSD-14.0-CURRENT-arm64-aarch64-ROCK64-20211209-b7c55487ff2-251490.img　seek=0x40 conv=notrunc
# dd if=./usr/lib/linux-u-boot-current-nanopineo3_21.02.1_arm64/uboot.img of=FreeBSD-14.0-CURRENT-arm64-aarch64-ROCK64-20211209-b7c55487ff2-251490.img　seek=0x4000 conv=notrunc
# dd if=./usr/lib/linux-u-boot-current-nanopineo3_21.02.1_arm64/trust.bin of=FreeBSD-14.0-CURRENT-arm64-aarch64-ROCK64-20211209-b7c55487ff2-251490.img　seek=0x6000 conv=notrunc
（SDに書き込み）
# dd if=FreeBSD-14.0-CURRENT-arm64-aarch64-ROCK64-20211209-b7c55487ff2-251490.img of=/dev/da0 bs=2m
```

 これで NanoPi NEO3 で起動する　SD　が出来ました。確認しましょう。
 給電前にシリアルコンソール確認用　USB-シリアル変換ケーブルを挿して、PCと接続しておきます。

シリアルのピン。左のシルクにピンの説明が書かれている。
![debug_serialport.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103137/1a7c2d3a-a02b-896d-e6f0-fb17e77407ba.jpeg)


 PC側でシリアルのbpsを150000に設定したターミナルソフトを起動しておきます。FreeBSD ならば以下のコマンドです。

```
# cu -l /dev/cuaU0 -s 150000
```

 そして SD　を　NanoPi NEO３に挿入してUSB TypeCの給電ケーブルを挿します。

FreeBSD の起動ログがでて、ログインプロンプトが出れば成功です。

## loader.conf で dtb を読み込ませる

 起動までは出来ましたが、このままだと USB が動きません。
 そこで USB ポートを使えるようにしましょう、と言いたいところですが、以下の手順でも USB　オンボードの USB３ ポートは結局使えないのです……。
 ですがヘッダーピンに接続して使う USB2 外付け端子が使えるようになります。全く使えないよりはマシです。

 /boot/loader.conf に以下の記述を追記して、nanopi-r2s の dtb ファイルを起動時に読み込ませるようにします。

```loader.conf
rk3328_nanopi_r2s_load="YES"
rk3328_nanopi_r2s_type="dtb"
rk3328_nanopi_r2s_name="rk3328-nanopi-r2s.dtb"

```

# 動くデバイス

## 有線ネットワークは動く
問題なく動きます(dwc0)。DHCP環境ならばLANケーブルに繋いで起動すればすぐにネットワーク接続できます。

## USB はオンボードのポート(USB3)は動かない　
すでに述べた通りオンボードのUSB3のポートが動きません。

## 外付けのポート(USB2)は動く
USBポート（USB2）に繋ぐためのヘッダーピンが2ポート分あるので、現状USBを使いたい場合はヘッダーピンから線を伸ばして、外付けのポートを使うしかないです。無線LANドングル(ロジテック LAN-W300N/U25)などの動作を確認しました。

USBのヘッダーピン
![usb_pin.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103137/f4cb739b-0556-7bce-2eb3-cd51077cd5da.jpeg)

ヘッダーピンから線を伸ばしてUSBポートに接続し、WiFiドングルを挿した状態。
![usb_connect.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103137/c4f5065e-c3ee-ba0e-f588-d322fdd532d0.jpeg)


## GPIOは動く
ヘッダーピンの GPIO ポートは、コントローラー/dev/gpioc0 〜 /dev/gpioc3 のどれか(ポートによって違うっぽい）で制御し、入力や出力ができました。全部のポートの対応はまだ取れていません。

## オンボード LED は /dev/gpioc0 の PA2への出力で点灯制御
オンボードのLEDのうち、緑色のLEDはGPIOで制御出来ます。/dev/gpioc0 の PA2 を０　にすると消灯、1 にすると点灯します。

```
 # gpioctl -f /dev/gpioc0 PA2 1 (点灯）
 # gpioctl -f /dev/gpioc0 PA2 0 (消灯)
```

![onboard_led.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103137/87d17b17-5709-a955-a3ea-4b847319909a.jpeg)

## オンボードスイッチは /dev/gpioc0 の PA0 の入力
　NanoPi NEO3 にはユーザーが自由に使えるスイッチがオンボードのヘリについています。

![onbard_switch.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103137/3504dcd1-1760-3e51-6334-549434ce8d96.jpeg)

押されているかどうかは /dev/gpioc0 の PA0 の入力値を監視し、0 ならば押されています(論理が反転してます)。

```
# gpioctl -f /dev/gpioc0 PA0
１ (押されてない）
# gpioctl -f /dev/gpioc0 PA0
0 （押されている）
```

## I2C はまだ未確認
まだ試していません。RaspberryPiとかで確認したコードが動くか確認してみるつもりです。


# 実演

## 起動まで
USB 接続の WiFi ドングルでネットワークも設定されています（鼻息が…）。

<iframe width="560" height="315" src="https://www.youtube.com/embed/8d36lDFB-rs" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>


## センサーチェック

障害物センサーの値を GPI　で監視し、検知したら GPO　でのLED点灯/消灯のトグルと、PCにネットワークで文字列「障害」を　nc で投げます（PC 側は nc で待ち受け）。

<iframe width="560" height="315" src="https://www.youtube.com/embed/JjPLegLGB2c" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>


## オンボードスイッチチェック

オンボードのスイッチONで、　オンボードのLEDの点灯/消灯トグルと、PCにネットワークで文字列「switch on」を　nc で投げます（PC 側は nc で待ち受け）。

<iframe width="560" height="315" src="https://www.youtube.com/embed/rWUl2SHYx_o" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

監視用スクリプトはこんな感じ

```check.sh
#!/bin/sh
while true; do 
        if [ `gpioctl -f /dev/gpioc0 PA0` -eq 0 ] ; then
                echo switch on | nc -N 192.168.11.12 9029;
                gpioctl -f /dev/gpioc0 -t PA2
        fi
        if [ `gpioctl -f /dev/gpioc2 PA2` -eq 0 ] ; then
                echo 障害 | nc -N 192.168.11.12 9029;
                gpioctl -f /dev/gpioc2 -t PB7
        fi
        sleep 1
done

```

# 動かしてはみましたが

USB3　ポートが使えないとちょっとまだ厳しいですなぁ。