# ESP32-S3-N16R8 に esp32-linux-build(WiFi対応)を Docker でビルド・書き込みする手順

対象ボード: **ESP32-S3-N16R8**(FLASH 16MB / PSRAM 8MB)
ホスト環境: Ubuntu 24.04 LTS + Docker
ビルドシステム: [jcmvbkbc/esp32-linux-build](https://github.com/jcmvbkbc/esp32-linux-build) を Docker でラップした [hpsaturn/esp32s3-linux](https://github.com/hpsaturn/esp32s3-linux)

> N16R8 は \\\*\\\*FLASH 16MB / PSRAM 8MB\\\*\\\* という組み合わせですが、標準で用意されている設定ファイルは
> - `devkit-c1-8m.conf` … FLASH 8MB / PSRAM 8MB
> - `box3.conf` … FLASH 16MB / PSRAM 16MB
>
> のどちらもN16R8にはドンピシャで合いません。本ガイドでは \\\*\\\*カスタム設定ファイル\\\*\\\*を作ってこの問題を回避します。

\---

## 0\. 事前準備(初回のみ)

```bash
sudo apt update
sudo apt install -y docker.io git
sudo usermod -aG docker $USER
sudo usermod -aG dialout $USER   # シリアルポートの権限問題を避けるため
```

**ここで一度ログアウト→ログインし直す**(グループ変更を反映させるため)。

反映確認:

```bash
groups
# docker と dialout の両方が含まれていればOK
```

\---

## 1\. リポジトリ取得

```bash
git clone --recursive https://github.com/hpsaturn/esp32s3-linux.git
cd esp32s3-linux
```

## 2\. Dockerイメージのビルド

```bash
docker build --build-arg DOCKER\\\_USER=$USER --build-arg DOCKER\\\_USERID=$UID -t esp32linuxbase .
```

## 3\. 設定ファイルの準備

```bash
cp settings.cfg.default settings.cfg
```

\---

## 4\. N16R8用のカスタムconfigを作成

### 4-1. `devkit-c1-16m.conf` を作成

```bash
cat > esp32-linux-build/devkit-c1-16m.conf <<'EOF'
BUILDROOT\\\_CONFIG=esp32s3\\\_devkit\\\_c1\\\_8m
ESP\\\_HOSTED\\\_CONFIG=sdkconfig.defaults.esp32s3.16m8mpsram
EOF
```

* `BUILDROOT\\\_CONFIG`(カーネル側)は`devkit-c1`のまま → PSRAMアドレス計算(8MB用)とDTB(汎用devkit用、フレームバッファコンソールなし)が実機と一致する
* `ESP\\\_HOSTED\\\_CONFIG`(WiFiブートローダ/フラッシュ側)は後で作るカスタムファイルを指定 → FLASH16MBのパーティションテーブルを使う

### 4-2. 一度ビルドを走らせて `build/esp-hosted` を生成させる

```bash
docker run --rm -it --name esp32s3linux \\\\
  --user="$(id -u):$(id -g)" \\\\
  -v ./esp32-linux-build:/app \\\\
  --env-file settings.cfg \\\\
  --device=/dev/ttyACM0 \\\\
  esp32linuxbase ./rebuild-esp32s3-linux-wifi.sh -c devkit-c1-16m.conf
```

`ESP\\\_HOSTED\\\_CONFIG`のファイルがまだ存在しないため、`Could not apply IDF config ...`というエラーで停止するのが正常です。カーネル/rootfsのビルドまでは完走します。

### 4-3. カスタムsdkconfigを作成

```bash
cd esp32-linux-build/build/esp-hosted/esp\\\_hosted\\\_ng/esp/esp\\\_driver/network\\\_adapter
cp sdkconfig.defaults.esp32s3.16n16r sdkconfig.defaults.esp32s3.16m8mpsram
sed -i \\\\
  -e 's/CONFIG\\\_LINUX\\\_PSRAM\\\_16M=y/# CONFIG\\\_LINUX\\\_PSRAM\\\_16M is not set/' \\\\
  -e 's/# CONFIG\\\_LINUX\\\_PSRAM\\\_8M is not set/CONFIG\\\_LINUX\\\_PSRAM\\\_8M=y/' \\\\
  sdkconfig.defaults.esp32s3.16m8mpsram
grep PSRAM sdkconfig.defaults.esp32s3.16m8mpsram
# → CONFIG\\\_LINUX\\\_PSRAM\\\_8M=y / # CONFIG\\\_LINUX\\\_PSRAM\\\_16M is not set になっていればOK
cd \\\~/esp32s3-linux   # 元のディレクトリに戻る(パスは環境に合わせて調整)
```

これは、box3用の「16MB flash設定」をベースに、PSRAMだけ8MB向けに戻したものです。box3のFLASH部分の設定(16MBパーティションテーブル等)はそのまま活かしつつ、実機に存在しない16MB PSRAM前提の設定だけを修正しています。

### 4-4. `keep\\\_bootloader=y` を設定(重要)

```bash
cat >> settings.cfg <<'EOF'
keep\\\_toolchain=y
keep\\\_rootfs=y
keep\\\_buildroot=y
keep\\\_bootloader=y
EOF
```

これを入れておかないと、次回ビルド時に`build/esp-hosted`ごと削除・再クローンされ、せっかく作ったカスタムファイルが消えてしまいます。

\---

## 5\. 本番ビルド・書き込み

```bash
ls -la /dev/ttyACM\\\* /dev/ttyUSB\\\*   # 今のポート名を確認しておく

docker run --rm -it --name esp32s3linux \\\\
  --user="$(id -u):$(id -g)" \\\\
  -v ./esp32-linux-build:/app \\\\
  --env-file settings.cfg \\\\
  --device=/dev/ttyACM0 \\\\
  esp32linuxbase ./rebuild-esp32s3-linux-wifi.sh -c devkit-c1-16m.conf
```

(`/dev/ttyACM0`は実際のポート名に置き換える)

* ビルドには数十分、約20GBのディスク容量が必要(初回のみ。2回目以降は`keep\\\_\\\*`により大幅短縮)
* 何度かEnterキーを求められるので、パーティション書き込みごとに押して進める
* 最後に以下のようなメッセージが出れば成功:

```
  Written contents of file 'build-buildroot-esp32s3\\\_devkit\\\_c1\\\_8m/images/etc.jffs2' at offset 0xb0000
  ```

### よくあるトラブルと対処

|症状|対処|
|-|-|
|`No serial ports found`|コンテナを再起動(ボードのリセット/抜き差し後は`--device`のデバイス番号がズレることがある)|
|`Permission denied: /dev/ttyACMx`|別ターミナルから `docker exec -it -u root esp32s3linux bash` → `chmod 666 /dev/ttyACMx`|
|`Device or resource busy`|ホスト側で `sudo lsof /dev/ttyACMx` を確認。`screen`等が掴んだままの場合が多い。`screen -ls`→該当セッションをkillするか`sudo kill <PID>`|
|チップと通信できない|ボードのBOOTボタンを押しながらRESETボタンを押して離し、BOOTボタンを離す(手動ダウンロードモード)|
|コンテナ内で`root`に入ると`esp-idf`ツールが「未インストール」と出る|`-u root`ではなく `-u "$(id -u):$(id -g)"` で`exec`する(ビルド時と同じユーザーでないと`$HOME/.espressif`が見えない)|

書き込み後、ボードをリセットするとブートログが流れます:

```
ESP-ROM:esp32s3-20210327
...
pp rom version: ...
net80211 rom version: ...
linux ptr = ...
vectors ptr = ...
```

この後、Linuxのブートログ→ログインプロンプトが出れば成功です。**COMポート(UART0側)を115200bpsで監視**してください(ネイティブUSBポート側にはLinuxコンソールは出ません)。

```bash
sudo screen /dev/ttyUSB0 115200   # COMポート側のデバイス名に置き換え
```

\---

## 6\. WiFi設定

ログイン後:

```bash
cat > /etc/wpa\\\_supplicant.conf <<EOF
network={
        ssid="YOUR-SSID"
        psk="YOUR-PASSWORD"
}
EOF
reboot
```

再起動後、SSHで接続可能になります。

## 7\. 動作確認コマンド

```bash
free -m           # メモリ(PSRAM 8MB相当)
cat /proc/mtd      # パーティション一覧(FLASH 16MB相当か確認)
df -h              # ディスク使用率
ip addr show wlan0 # WiFi接続確認
ping -c 3 8.8.8.8
```

\---

## 8\. 今回作成したカスタムファイルの保存方法

次回、別のN16R8ボードに書き込む際に**ビルドを1からやり直さず**に使えるよう、以下の2ファイルを保存しておいてください。

|ファイル|保存場所|役割|
|-|-|-|
|`devkit-c1-16m.conf`|`esp32-linux-build/devkit-c1-16m.conf`|どのカーネル設定・sdkconfigを使うか指定するconfig|
|`sdkconfig.defaults.esp32s3.16m8mpsram`|`esp32-linux-build/build/esp-hosted/esp\\\_hosted\\\_ng/esp/esp\\\_driver/network\\\_adapter/sdkconfig.defaults.esp32s3.16m8mpsram`|FLASH16MB + PSRAM8MB向けのビルド設定|

### バックアップ推奨コマンド

```bash
mkdir -p \\\~/esp32s3-n16r8-configs
cp esp32-linux-build/devkit-c1-16m.conf \\\~/esp32s3-n16r8-configs/
cp esp32-linux-build/build/esp-hosted/esp\\\_hosted\\\_ng/esp/esp\\\_driver/network\\\_adapter/sdkconfig.defaults.esp32s3.16m8mpsram \\\~/esp32s3-n16r8-configs/
```

このディレクトリごとGitリポジトリ化したり、クラウドストレージにバックアップしておくと安心です。

\---

## 9\. 次回・別のN16R8ボードに書き込むとき

`esp32s3-linux`リポジトリを新しくcloneした状態からでも、以下の手順でショートカットできます。

```bash
git clone --recursive https://github.com/hpsaturn/esp32s3-linux.git
cd esp32s3-linux
docker build --build-arg DOCKER\\\_USER=$USER --build-arg DOCKER\\\_USERID=$UID -t esp32linuxbase .
cp settings.cfg.default settings.cfg
cat >> settings.cfg <<'EOF'
keep\\\_toolchain=y
keep\\\_rootfs=y
keep\\\_buildroot=y
keep\\\_bootloader=y
EOF

# バックアップしておいたconfigを配置
cp \\\~/esp32s3-n16r8-configs/devkit-c1-16m.conf esp32-linux-build/

# 一度ビルドしてbuild/esp-hostedディレクトリを生成させる(エラーで止まるのが正常)
docker run --rm -it --name esp32s3linux \\\\
  --user="$(id -u):$(id -g)" \\\\
  -v ./esp32-linux-build:/app \\\\
  --env-file settings.cfg \\\\
  --device=/dev/ttyACM0 \\\\
  esp32linuxbase ./rebuild-esp32s3-linux-wifi.sh -c devkit-c1-16m.conf

# 止まったら、バックアップしておいたsdkconfigを配置
mkdir -p esp32-linux-build/build/esp-hosted/esp\\\_hosted\\\_ng/esp/esp\\\_driver/network\\\_adapter
cp \\\~/esp32s3-n16r8-configs/sdkconfig.defaults.esp32s3.16m8mpsram \\\\
   esp32-linux-build/build/esp-hosted/esp\\\_hosted\\\_ng/esp/esp\\\_driver/network\\\_adapter/

# 本番ビルド・書き込み
docker run --rm -it --name esp32s3linux \\\\
  --user="$(id -u):$(id -g)" \\\\
  -v ./esp32-linux-build:/app \\\\
  --env-file settings.cfg \\\\
  --device=/dev/ttyACM0 \\\\
  esp32linuxbase ./rebuild-esp32s3-linux-wifi.sh -c devkit-c1-16m.conf
```

> 補足: `esp-hosted`のcloneや`dynconfig`/`crosstool-NG`/`buildroot`は`keep\\\_\\\*`設定によりホスト側の`esp32-linux-build/build/`にすでにある場合はスキップされます。まっさらな新規PCで作業する場合は、初回と同様にすべてゼロからのビルドとなり、20GB・数十分程度かかります(2台目以降のN16R8ボードへの書き込みでも、同じPC上で作業するなら`build/`ディレクトリが再利用できるので、ほぼ待ち時間なしで書き込みだけ行えます)。

\---

## 参考リンク

* https://github.com/jcmvbkbc/esp32-linux-build
* https://github.com/hpsaturn/esp32s3-linux
* https://github.com/jcmvbkbc/esp-hosted

