Raspberry Pi PicoでNuttXを動かす

Raspberry Pi Picoで[FreeRTOSを動かした](https://qiita.com/yunkya2/items/7b9b38b7c8c33a6327af)のに続いて、今度は[NuttX](http://nuttx.apache.org/)というリアルタイムOSを動かしてみました。

# NuttXとは

[NuttX](http://nuttx.apache.org/)はPOSIX準拠のAPIを持つリアルタイムOSです。FreeRTOSはスケジューラといくつかのカーネル資源を管理するのみのごく小さなOSでしたが、NuttXはカーネル本体にライブラリ群、各種ファイルシステムやネットワークスタックなども備えた、かなり本格的なOSになっています。
ドローンのフライトコントローラである[PX4](https://github.com/PX4)やソニーのボードコンピュータ[SPRESENSE](https://developer.sony.com/ja/develop/spresense/)などでの採用例があります。

# ビルド環境準備

[Getting started with Raspberry Pi Pico](https://datasheets.raspberrypi.org/pico/getting-started-with-pico.pdf)に従って、Pico SDKのインストールとHello WorldのUART版をビルドして動作できるところまでの環境を準備します[^1]。

[^1]: 現時点でPico版NuttXはUARTコンソールしかサポートしていないため、UART接続環境は必須です。

また、NuttXのビルド時にPico SDKのソースコードの一部を利用しているため、環境変数 `PICO_SDK_PATH` にPico SDKの位置を指定しておく必要があります[^2]。

[^2]: Getting Startedの記述だとなぜかpico-examplesからの相対パスを指定していますが、これはpico-sdkのある絶対パスにしておくべきです。

私は[この記事](https://qiita.com/yunkya2/items/e67996301a2d8d2a5609)で紹介したWindowsのWSL環境で開発しています。ラズパイ4のRaspberry Pi OSでのビルドも可能だと思いますが未確認です。逆に、Windowsネイティブ環境でのビルドはかなり面倒なことが予想されますので避けた方が良いと思います。

# kconfigのビルドとインストール

NuttXのビルドでは、Linuxカーネルのビルドにも使われているkconfigをコンフィグレーションのために使用します。まずこれをビルドしてインストールします。

ビルドに必要なパッケージをインストールします。

```
$ sudo apt install bison flex gettext libncurses5-dev gperf automake-1.15 libtool pkg-config
```

kconfig-frontendsのソースコードを取得してビルド、インストールします。

```
$ git clone https://bitbucket.org/nuttx/tools.git
$ cd tools/kconfig-frontends/
$ ./configure --enable-mconf --disable-nconf --disable-gconf --disable-qconf
$ make
$ sudo make install
$ sudo /sbin/ldconfig
```

# NuttXのコード取得とビルド

Raspberry Pi Pico対応コードは既に[公式リポジトリ](https://github.com/apache/incubator-nuttx)に[マージ](https://github.com/apache/incubator-nuttx/pull/2877)されています。
公式リポジトリからソースコードを取得してビルドします。

```
$ git clone https://github.com/apache/incubator-nuttx.git nuttx
$ git clone https://github.com/apache/incubator-nuttx-apps.git apps
$ cd nuttx
$ ./tools/configure.sh raspberrypi-pico:nsh
$ make
```

ビルドが完了すると、ELFバイナリである`nuttx`と、インストール用イメージの`nuttx.uf2`ができます。

Linuxカーネルのコンフィグレーションと同じように、`make menuconfig`でカーネルやアプリケーションのコンフィグレーションを行うことができます。

# 実行

`nuttx.uf2`は通常のPico SDKアプリと同様に、BOOTSELを押しながら接続したPicoのマスストレージデバイスにドラッグ&ドロップすることでインストールできます。
起動に成功すると以下のメッセージとプロンプトが表示されます。
(起動確認用にPico基板上のLEDも点灯させています)

```

NuttShell (NSH) NuttX-10.0.1
nsh>
```

NuttShell(NSH)は、NuttXのアプリケーションに標準で含まれているシェルです。
以下のように、かなりLinuxに近い感覚で使えることが分かると思います[^3]。


[^3]: 現時点では動作するデバイスがUARTしかないので使えるアプリは限られますが、`apps`に含まれているBASICインタプリタやVIエディタ(クローン)なども、コンフィグを有効にすれば動作します。

```
nsh> help
help usage:  help [-v] [<cmd>]

  .         cd        df        free      mkdir     printf    sleep     uname
  [         cp        echo      help      mkrd      ps        source    umount
  ?         cmp       env       hexdump   mh        pwd       test      unset
  basename  dirname   exec      kill      mount     rm        time      usleep
  break     date      exit      ls        mv        rmdir     true      xd
  cat       dd        false     mb        mw        set       truncate

Builtin Apps:
  sh      ostest  hello   nsh
nsh> ls
/:
 dev/
nsh> ls -l /dev
/dev:
 crw-rw-rw-       0 console
 crw-rw-rw-       0 null
 crw-rw-rw-       0 ttyS0
nsh> mkdir /proc
nsh> mount -t procfs /proc
nsh> ps
  PID PRI POLICY   TYPE    NPX STATE    EVENT     SIGMASK   STACK COMMAND
    0   0 FIFO     Kthread N-- Ready              00000000 001024 Idle Task
    1 100 RR       Task    --- Running            00000000 002036 init
nsh> uname -a
NuttX 10.0.1 6b83f6a8fe Feb 20 2021 21:13:38 arm raspberrypi-pico
nsh> free
                     total       used       free    largest
        Umem:       264400       7200     257200     257184
nsh>
```