NuttX ESP32 アプリケーションのDockerビルド

概要

上記にてNuttXのビルトインアプリケーションを作成してESP32で自動起動するやり方を理解しました。

WSLのUbuntuでビルド用のDockerコンテナを作成してビルドします。 Dockerfileとスクリプトを組み合わせたビルド方法、ファイル構成について検討し、プロジェクトとして作成しましたのでこの説明をしたいと思います。

前提

  • MCU及び基板 ESP32-DevKitC-32 (ESP32-DevKitC-32E)
  • OS NuttX
  • ビルド環境 Ubuntu22.04 (WSL) Docker
  • アプリケーションは Hello World 相当
  • nsh (NuttX Shell) 使用

方針

  • Dockerfileとシェルスクリプトにてビルドする
  • コンテナイメージは1度ビルドしたものを使いまわすことができる
    • docker build するスクリプトをプロジェクトに含める
  • OSを含むソースコードはDocker外のファイルシステムに置いたままビルドする
    • ソースコードを編集しやすくする
  • OSのソースコードとアプリケーションのソースコードのディレクトリを分ける
    • アプリケーションのソースコードを識別しやすくする
    • 類似のプロジェクトを作成する際に流用しやすくする

作成したプロジェクト

nuttx_hello

これが今回作成したプロジェクトです。

GitHub - wurly200a/nuttx_hello
Contribute to wurly200a/nuttx_hello development by creating an account on GitHub.
  • LICENSE
  • README.md
  • build-nuttx-esp32
    • 01_build-builder.sh
    • 02_enter-builder.sh
    • 03_build.sh
    • Dockerfile
  • execution.png
  • hello
    • Kconfig
    • Make.defs
    • Makefile
    • hello_main.c

ビルド方法

スクリプトの実行方法

READMEの通り、プロジェクトをクローンしたら最上位のディレクトリから、スクリプトがあるディレクトリのパスを含んだ形でスクリプトを実行します。

step1

ビルド用のDockerコンテナのイメージを docker build します。(最初の1回のみ)

(なおデフォルトのイメージ名は”nuttx_esp32_builder”としており、第一引数で任意の名前を指定可能です。)

$ build-nuttx-esp32/01_build-builder.sh

step2

ビルド用のDockerコンテナに入ります。(第一引数でイメージ名を指定可能です。)

コンテナに入ったら “get_idf” を実行します。

$ build-nuttx-esp32/02_enter-builder.sh
$ get_idf

step3

ソースコードをビルドします。 スクリプトの中で https://github.com/apache/incubator-nuttxhttps://github.com/apache/incubator-nuttx-apps をクローンしています。

$ build-nuttx-esp32/03_build.sh

解説

hello

下記のような構成で作成します。

  • hello
    • Kconfig
    • Make.defs
    • Makefile
    • hello_main.c

今回は external/ ディレクトリ以下に配置する為、Make.defs は下記のような記述になります。

ifeq ($(CONFIG_APP_HELLO),y)
CONFIGURED_APPS += external/hello
endif

Dockerfile

引数指定することでdocker build を実行した環境のユーザ、グループを作成します。

# add user and group
RUN groupadd -g $GROUP_ID $GROUP_NAME
RUN useradd -u $USER_ID -g $GROUP_ID -m $USER_NAME
RUN echo "$USER_NAME:$PASSWORD" | chpasswd
Installing — NuttX latest documentation

NuttXについては上記ページの Prerequisites, KConfig frontend, Toolchain に基づくパッケージをインストールします。

# NuttX Prerequisites
RUN apt install -y \
    bison flex gettext texinfo libncurses5-dev libncursesw5-dev xxd \
    gperf automake libtool pkg-config build-essential gperf genromfs \
    libgmp-dev libmpc-dev libmpfr-dev libisl-dev binutils-dev libelf-dev \
    libexpat-dev gcc-multilib g++-multilib picocom u-boot-tools util-linux

# NuttX Kconfig frontend
RUN apt install -y kconfig-frontends

# NuttX Toolchain
RUN apt install -y gcc-arm-none-eabi binutils-arm-none-eabi
Standard Toolchain Setup for Linux and macOS - ESP32 - — ESP-IDF Programming Guide latest documentation

ESP32向けのビルドを行う為 ESP-IDF が必要です。 上記ページの Install Prerequisites, Get ESP-IDF に基づくパッケージのインストールと esp-idf のクローン、”get_idf”エイリアスの設定を行います。

# ESP-IDF Prerequisites
RUN apt install -y git wget flex bison gperf python3 python3-venv cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0

# Get ESP-IDF
USER ${USER_ID}
RUN mkdir -p ~/esp
RUN git clone --recursive https://github.com/espressif/esp-idf.git ~/esp/esp-idf

# ESP-IDF Set up the tools
RUN ~/esp/esp-idf/install.sh esp32
RUN echo "alias get_idf='. $HOME/esp/esp-idf/export.sh'" > ~/.bash_aliases

01_build-builder.sh

docker buildします。上記の Dockerfile に合わせて引数を指定します。

CMD="docker build . -f $(cd $(dirname $0); pwd)/Dockerfile -t ${IMAGE_NAME} \
            --build-arg USER_NAME=$(id -u -n) \
            --build-arg USER_ID=$(id -u) \
            --build-arg GROUP_NAME=$(id -g -n) \
            --build-arg GROUP_ID=$(id -g) \
            --build-arg PASSWORD=password"

イメージ名を指定可能にしています。

if [ "$#" != 1 ]; then
IMAGE_NAME="nuttx_esp32_builder"
else
IMAGE_NAME=$1
fi

02_enter-builder.sh

Dockerコンテナに入った後、 “get_idf” の実行が必要ですのでそのメッセージを表示します。

03_build.sh

Installing — NuttX latest documentation

上記に記載があるように https://github.com/apache/incubator-nuttxhttps://github.com/apache/incubator-nuttx-apps をそれぞれ、nuttx と apps というディレクトリ名にしてクローンします。

アプリケーションについては、apps/external 以下にシンボリックリンクを作成します。

NuttX ビルトインアプリケーションを作成する - みつきんのメモ
はじめに NuttXにビルトインアプリケーションを追加する方法を調査した。 ここが日本語でよくまとまっていた。 プログラムを作成する場所 プログラムをどこに追加するかと言うのが一つ考えどころだが、apps/README.txtによると、 Use of the name ''apps/external'' is sugg...
Building NuttX with Applications Outside of the Source Tree - NUTTX - Apache Software Foundation

上記にも記載されている通りです。

ただし、/external ディレクトリにも Make.defs, Makefile が必要です。

例えば既存の apps/games などを参考にすればよく、最低限下記の記述が必要です。

Make.defs

include $(wildcard $(APPDIR)/games/*/Make.defs)

Makefile

MENUDESC = "External"

include $(APPDIR)/Directory.mk

ここではスクリプトで処理します。

NUTTX_APPS_EXTERNAL_DIR=${NUTTX_APPS_DIR}/external

if [ ! -d ${NUTTX_APPS_EXTERNAL_DIR} ]; then
    mkdir -p ${NUTTX_APPS_EXTERNAL_DIR}
    cat << 'EOS' > ${NUTTX_APPS_EXTERNAL_DIR}/Makefile
MENUDESC = "Extenal"

include $(APPDIR)/Directory.mk
EOS
    cat << 'EOS' > ${NUTTX_APPS_EXTERNAL_DIR}/Make.defs
include $(wildcard $(APPDIR)/external/*/Make.defs)
EOS
fi

if [ ! -d ${NUTTX_APPS_EXTERNAL_DIR}/${MY_APP_NAME} ]; then
    ln -s $(pwd)/${MY_APP_NAME} ${NUTTX_APPS_EXTERNAL_DIR}/${MY_APP_NAME}

configure を行います。 ESP32-DevKitC-32、nsh を使用するため、下記のように指定します。

./tools/configure.sh -l esp32-devkitc:nsh

make menuconfig を行う代わりに、kconfig-tweak で設定します。

kconfig-tweak --file .config --enable CONFIG_BOARDCTL_ROMDISK
kconfig-tweak --file .config --set-str CONFIG_NSH_SCRIPT_REDIRECT_PATH ""
kconfig-tweak --file .config --set-val CONFIG_FS_ROMFS_CACHE_FILE_NSECTORS 1

kconfig-tweak --file .config --disable CONFIG_NSH_CONSOLE_LOGIN

kconfig-tweak --file .config --enable CONFIG_FS_ROMFS
kconfig-tweak --file .config --enable CONFIG_NSH_ROMFSETC
kconfig-tweak --file .config --enable CONFIG_NSH_ARCHROMFS

kconfig-tweak --file .config --enable CONFIG_FS_FAT

kconfig-tweak --file .config --enable CONFIG_APP_HELLO
kconfig-tweak --file .config --set-val CONFIG_APP_HELLO_PRIORITY 100
kconfig-tweak --file .config --set-val CONFIG_APP_HELLO_STACKSIZE 2048

自動起動設定用のヘッダ生成を行います。

cd boards/xtensa/esp32/esp32-devkitc/include
rm rc.sysinit.template
touch rc.sysinit.template
rm rcS.template
touch rcS.template
echo "#! /bin/nsh" > rcS.template
echo "hello" >> rcS.template
../../../../../tools/mkromfsimg.sh ../../../../../
cd ../../../../..

make します。

make -j$(nproc)
Copied title and URL