NanoPi Neo でFreeBSD （動作編)


## 次は実際に動かしてみる
前回[NanoPi Neo でFreeBSD (ビルド編)](https://qiita.com/s_mitu/items/b54d796a33c35409315e)の続きとなります。
とりあえずmicroSDに FreeBSD が書き込んで、さて実際にボードに入れて動かそうかということになるわけですが、その前にハード的な準備です。
そんなものはとっくにわかっとるという人は起動まで飛ばしてください。

## ボードの準備
ボードには GPIO のヘッダピンがはんだ付けされていません。付属（RaspberryPi 準拠の二列とUSBなどの接続用の一列）はしているので「自分ではんだ付けしてね」という形になります。
GPIO など使わないという場合はつける必要はありません。GPIO で遊びたい自分ははんだ付けしました。
![nanopineo-nopin.jpg](https://qiita-image-store.s3.amazonaws.com/0/103137/d8d7cba5-4486-dec5-900f-a53a4f9a5434.jpeg)

↓

![nanopineo-pin.jpg](https://qiita-image-store.s3.amazonaws.com/0/103137/46588daa-9162-2e82-409d-321b88cc4b85.jpeg)


あと安定動作させるにはヒートシンクがあったほうがいいということで (https://wave.hatenablog.com/entry/2018/07/24/080900) 、ヒートシンクも取り付け。

![nanopineo-heatsink.jpg](https://qiita-image-store.s3.amazonaws.com/0/103137/466904e5-c4bb-6b9b-8fca-fa98d740fe5d.jpeg)

## シリアルピン
HDMIなどの映像出力がないので、シリアルコンソールが命綱となります。すでに Linux で NanoPi Neoを動かしている人は、有線ネットワークケーブル経由で ssh 接続出来ないかと思うかもしれませんが、後述しますがそれが現時点では出来ません。
USB TTLシリアル変換ケーブル(例えば[こんなの](https://www.sengoku.co.jp/mod/sgk_cart/detail.php?code=EEHD-4WXL) )をシリアル用のピンに接続して操作をします。

シリアル接続するためのピンだけは最初からはんだ付けされてます。下の写真の 4ピンのヘッダピンです。
![nanopineo-debugpin.jpg](https://qiita-image-store.s3.amazonaws.com/0/103137/88be96ed-19b8-2127-043d-22d0801c2f97.jpeg)

ピン配列は上の写真の右から pin#1 で

| 4 | 3| 2 |  1|
|:-:|:-:|:-:|:-:|
| RX  | TX  | 5V  | GND  |

となっています。USB TTLシリアル変換ケーブルと接続する場合は、5V を接続すると USB からの電源供給で中途半端に動き出して途中で panic を起こしたりするので、RX, TX, GNDのみを接続します。

電源はRaspberryPiと同じく Micro USBからの給電です。

## 起動
やっとこさ FreeBSD の起動です。
PCで USBシリアルをつなぎ、FreeBSD などならcu コマンド、WindowsならばTeraTermなどのなどでシリアル接続します。設定は 115200 bps / 8bit / ストップビット 1/ パリティなしです。

```shell:cuコマンド
$ cu -l /dev/cuaU0 -s 115200 
```

Micro USBからの給電を開始すれば起動開始します。シリアルコンソールに

![nanopineo-freebsd-tama.png](https://qiita-image-store.s3.amazonaws.com/0/103137/52c9534b-6599-38bd-9cbe-7a815748a128.png)

と出たら Enter を押すと FreeBSD の起動が始まります。

初回起動時は少し起動に時間がかかります。4GB 以上の micro SDで起動した場合、ddで書き込んだ段階では範囲外の容量(16GB なら 12GB分)をすべて使うために領域拡張が自動で行われます(growfs)。microSD の領域全てをちゃんと使ってくれます。

login: が出るまで行けば起動成功です。デフォルトのユーザーとパスワードは

|| ユーザー | パスワード |
|:-:|:-:|:-:|
|スーパーユーザー|root| 無し |
|一般| freebsd | freebsd |

です。ログインしたらさっさとpasswd コマンドで変更しましょう。

## SMP は動いている

FreeBSD/arm は SMP に対応していて、NanoPi Neo のクアッドコアも問題なく動いています。
下はport のビルド時のtopの様子です。

![nanopineo-top-vim-build.png](https://qiita-image-store.s3.amazonaws.com/0/103137/535c9167-3a86-9d2e-490a-7a447dc1cde1.png)

## 有線LANが使えない

結構重要な要素なのですが有線LANが現状使えません。dmesgを見ると Allwinnerの Ethernet である awg0の検出は成功してますが、attachで失敗しています。

```shell-session:dmesg
awg0: <Allwinner Gigabit Ethernet> mem 0x1c30000-0x1c3ffff irq 22 on simplebus0
awg0: soft reset timed out
device_attach: awg0 attach returned 60
```

## USBで WiFi 接続
NanoPi NeoにはUSBポートが出荷状態で一つ付いています。このポートは動くので、USBのWiFiドングルを使って、無線 LAN 接続が可能となります。
試したのは [ELECOM WDC-150SU2M](https://www2.elecom.co.jp/products/WDC-150SU2MBK.html)です(if_rtwnドライバ)。Buffalo の WLI-UC-GNM2 (if_runドライバ)も動作します。
NanoPi Neo には一列のヘッダピンに USB の D+/D-が２つ出ているので、そこにのUSBポートを接続することも出来ますが、FreeBSDからは認識しませんでした。

WiFi 設定は i386/amd64 の FreeBSD と同様です。sshd がデフォルトで起動しているので、WiFi 設定でネットワーク接続ができれば ssh での接続が可能となります。

##ボード上のLEDを光らせる
NanoPi Neoにはボード上にコントロール可能な青と緑のLEDが付いていて、FreeBSDから光らせる事が可能です。緑は電源投入時に光ってパワーランプとして通常使われていますが、消灯させる事が可能です。

![nanopi-neo-led.jpg](https://qiita-image-store.s3.amazonaws.com/0/103137/cd6f70e7-df74-1e6f-711d-640aa10562a6.jpeg)

FreeBSDからは /dev/led 以下に生えるデバイスノード

```shell-session
/dev/led/nanopi:blue:status
/dev/led/nanopi:green:pwr
```
が生えています。

```shell-session:ボード上LED操作
# echo 1 > /dev/led/nanopi:blue:status
```

で青が点灯。

![nanopi-neo-led-blueon.jpg](https://qiita-image-store.s3.amazonaws.com/0/103137/3b5610a2-ba13-58b8-21a1-049565e66cdf.jpeg)

```shell-session:ボード上LED操作
# echo 0 > /dev/led/nanopi:blue:status
```

で消灯です。

緑色 LED も同様です。

## GPIO 操作(一覧表示)
Lチカの要のGPIOも動きます。GPIO ピンにデバイスを接続して、出力でLEDを光らせたり入力でセンサーのON/OFF を検知したりできます。

FreeBSD ではGPIOコントローラーとして /dev/gpioc0 と /dev/gpioc1 が認識されています。 /dev/gpioc0 が二列のヘッダピン、/dev/gpioc1 が一列のヘッダピンのGPIOを操作します。
FreeBSDでは gpioctl でGPIOを操作します。 
操作できる PIN の一覧は

```shell-session:GPIOの一覧取得
gpioctl -l -f /dev/gpioc0 
```

で取れます。-f でどの GPIO コントローラーを使うか指定します。

```shell-session:GPIOの一覧
pin 00:	0	PA0<>
pin 01:	0	PA1<>
pin 02:	0	PA2<OUT>
pin 03:	0	PA3<>
pin 04:	0	PA4<>
pin 05:	0	PA5<PU>
pin 06:	0	PA6<>
pin 07:	0	PA7<>
pin 08:	0	PA8<>
pin 09:	0	PA9<>
〜（略）〜
```

上の一覧で出てくる PA0 とかの名前とピン配置の関係はメーカーサイトにある https://www.friendlyarm.com/image/catalog/description/NanoPi-NEO_en_02.jpg の図で確認します。
上記の GPIO 一覧全てがピンヘッダに割り振られているわけではなく、例えば PA10 は実は上述したボード上の青色 LED (/dev/led/nanopi:blue:status)用のピンなので、このピンを操作することでも LED の操作ができます。
ちなみに緑色のLED は(/dev/led/nanopi:green:pwr)はgpioc1 側の PL10です。

## GPIO 操作(ピンのIN/OUT設定)
使いたいピンに対して、入力 or 出力どちらで使うか設定します。gpioctl の -c オプションを付けて、ピン名と IN/OUTを指定します。PA0 を入力設定する場合は。

```shell-session:GPIO入力設定
# gpioctl -c PA0 IN
```

設定後はピンにかかった電圧が印加(3.3V)されていれば

```shell-session:GPIO入力結果
# gpioctl PA0
1
```
と 1 が帰ってきます。0V ならば 0 です。

PA2を出力設定する場合は

```shell-session:GPIO出力
# gpioctl -c PA2 OUT
```
と指定します。
設定後は

```shell-session:GPIO出力
# gpioctl PA2 1
```
で電圧ON、1を0にすれば OFF となります。

##GPIOを実際に使ってみる
単純な GPIO 実例です。

![nanopineo-gpio-device-front.jpg](https://qiita-image-store.s3.amazonaws.com/0/103137/21983f60-ea49-a859-121c-28c7e7d50dea.jpeg)
人感センサー( https://www.seeedstudio.com/PIR-Motion-Sensor-Large-Lens-version-p-1976.html )を入力に、LED を出力をつなぎ、人感センサーが感知したら LED ONする単純なシェルスクリプトを実行しました。

![nanopineo-gpio-headerpin.jpg](https://qiita-image-store.s3.amazonaws.com/0/103137/5465e98f-7307-1bd6-a814-0b2d4100ff4d.jpeg)

![nanopineo-gpio-device.jpg](https://qiita-image-store.s3.amazonaws.com/0/103137/94c6a611-c7a1-4430-e931-9b29da7bdacc.jpeg)

人感センサーの入力は PA0ピン(白線) に、LEDのプラスはPA2ピン(青線)につないでいます。人感センサーには電源の 3.3Vピン(赤線)もつないでいます。人感センサーの GND とLED のマイナスはGNDピン(黒線)につないでいます。

```shell:gpio-pir.sh
#!/bin/sh
# GPIOピンの設定
gpioctl -f /dev/gpioc0 -c PA0 IN    # 人感センサ入力
gpioctl -f /dev/gpioc0 -c PA2 OUT   # LED出力

while true; do
    # 人感センサをチェック
    pinstate=`gpioctl -f /dev/gpioc0 PA0`
    if [ "$pinstate" -eq 1 ]; then
        # 人感センサ ON ならば LED ON
        gpioctl -f /dev/gpioc0 PA2 1
    else
        # 人感センサ OFF ならば LED OFF
        gpioctl -f /dev/gpioc0 PA2 0
    fi
    sleep 1
done
```

実行中の動画です。体が動くと一定時間 LED が光ります。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">NanoPi  Neo の GPIO で 人感センサー検知と LED点灯<br>動くとLEDが光る <a href="https://twitter.com/hashtag/FreeBSD?src=hash&amp;ref_src=twsrc%5Etfw">#FreeBSD</a> <a href="https://twitter.com/hashtag/NanoPiNeo?src=hash&amp;ref_src=twsrc%5Etfw">#NanoPiNeo</a> <a href="https://t.co/VXe005Z4po">pic.twitter.com/VXe005Z4po</a></p>&mdash; 鈴木光宏@FreeBSD Advent Calendar 2018 参加者募集 (@s_mitu) <a href="https://twitter.com/s_mitu/status/1071613819430985729?ref_src=twsrc%5Etfw">2018年12月9日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## I<sup>2</sup>Cは動かない

２列の GPIO ピンヘッダに I<sup>2</sup>C ピンがあります。RaspberryPiだと/dev/iic? デバイスノードが生えていて、ユーザーランドから操作できますが、NanoPi Neo ではまだ対応していません。

# まとめない
とりあえず有線LANがなんとかならんものか。
エラーを出しているのは[sys/arm/allwinner/if_awg.c のここらあたり](https://svnweb.freebsd.org/base/head/sys/arm/allwinner/if_awg.c?view=markup#l1673)

```c:if_awg.c
         /* Wait for soft reset bit to self-clear */ 

         for (retry = SOFT_RST_RETRY; retry > 0; retry--) { 
                 if ((RD4(sc, EMAC_BASIC_CTL_1) & BASIC_CTL_SOFT_RST) == 0) 
                         break; 
                 DELAY(10); 
         } 
         if (retry == 0) { 
                 device_printf(dev, "soft reset timed out\n"); 
 #ifdef AWG_DEBUG 
                 awg_dump_regs(dev); 
 #endif 
                 return (ETIMEDOUT); 
         } 

```
ですが、単純にリトライ回数増やせば行けたりしないのだろうか。まだ試してませんが。