ESP32にAmazon FreeRTOSを入れてAWS-IoTにつなぐ（CentOS, Toolchain 5.2.0）

# はじめに
IoT機器を触ってみようと思い、ESP32-DevKitCを入手して少しずつ試してます。

ボードは秋月電子通商にて以下を入手。
[ESP32-DevKitC-32D](http://akizukidenshi.com/catalog/goods/search.aspx?search=x&keyword=M-13628)

ESP32の入門的な部分はこちらの本で勉強させていただきました。
[IoT開発スタートブック](https://www.amazon.co.jp/dp/4297107368/ref=cm_sw_em_r_mt_dp_U_mtJgFb8470VZ6)

今回はESP32にFreeRTOSを入れてAWSへ接続してみたので、その記録です。

AWSから提供されている手順に沿って進めます。あらかじめ用意されているデモプログラムが、MQTTでAWS IoTへ`Hello world`を送ってくれます。
[Espressif ESP32-DevKitC と ESP-WROVER-KIT の開始方法](https://docs.aws.amazon.com/ja_jp/freertos/latest/userguide/getting_started_espressif.html)

【今回の環境】

- 開発環境：CentOS 7.7
- ボード：[ESP32-DevKitC-32D](http://akizukidenshi.com/catalog/goods/search.aspx?search=x&keyword=M-13628)
- Toolchain 5.2.0

# PCやAWSの環境設定

## 前提条件
AWSコンソールのIAMの設定にて、以下の権限ポリシーをAWSのアカウントに割り当てます。

- AmazonFreeRTOSFullAccess
- AWSIoTFullAccess

## Espressif ハードウェアの設定
ESP32-DevKitCは既に使っていたので省略。

## 開発環境をセットアップする
AWSの手順に記載の通り、Espressif社のToolchain設定手順に沿って進めます。CentOSなので手順はこちら。
[Standard Setup of Toolchain for Linux](https://docs.espressif.com/projects/esp-idf/en/v3.3/get-started-cmake/linux-setup.html)

### Install Prerequisites
CentOS 7用として記載されている以下を実行。

```
sudo yum install git wget ncurses-devel flex bison gperf python pyserial cmake ninja-build ccache
```

ついでに後でpipも必要になるので入れておきます。

```
sudo yum install python3-pip
```

また、CentOS 7.7の標準ではpython2が使われる設定になっていましたが、python3とpip3の組み合わせで使えるようにシンボリックリンクを付け替えておきます。

```
cd /bin
sudo rm python
sudo ln -s python3 python
sudo ln -s pip3 pip
```

### ツールチェーンの設定
wgetでファイルをダウンロードして、展開。

```
cd ~/IoT
wget https://dl.espressif.com/dl/xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz

mkdir -p ~/IoT/esp
cd ~/IoT/esp
tar -xzf ../xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz
```

`~/.bash_profile`を開いてPATHの先頭に`$HOME/IoT/esp/xtensa-esp32-elf/bin`を追加。

これでEspressif社のToolchain設定手順は終了。AWSの手順に戻ります。

## CMake をインストールする

CentOS 7.7標準のcmake (v2.8.12.2)が古かったので、最新のcmakeをダウンロードして使えるようにします。

```
wget https://github.com/Kitware/CMake/releases/download/v3.18.0/cmake-3.18.0-Linux-x86_64.sh
chmod +x cmake-3.18.0-Linux-x86_64.sh
./cmake-3.18.0-Linux-x86_64.sh
```

`~/.bash_profile`を開いてPATHの先頭に`$HOME/IoT/cmake-3.18.0-Linux-x86_64/bin`を追加。

## シリアル接続の確立

ここのページを参考に進めます。
[Establish Serial Connection with ESP32](https://docs.espressif.com/projects/esp-idf/en/v3.3/get-started-cmake/establish-serial-connection.html#linux-dialout-group-cmake)

まず、Silicon LabsのページからVirtual COM Port (VCP) driversをダウンロード（要ユーザ登録）。
[CP210x USB - UART ブリッジ VCP ドライバ]
(https://jp.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers)

zipを解凍し、中に含まれているtxtファイルのRedHat向け手順を参考に、cp210x.koをビルドして所定の位置にセット。

```
make
sudo cp cp210x.ko to /lib/modules/<kernel-version>/kernel/drivers/usb/serial
insmod cp210x.ko
sudo chmod 666 /dev/ttyUSB0
```

なお、Redhat向け手順にある`usbserial.ko`については、CentOSの場合はKernelに含まれているので考慮不要だそう。

## AWSCLIのインストールと設定

以下を参考にインストール。
[Linux での AWS CLI バージョン 2 のインストール](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2-linux.html)

```
cd ~/IoT/
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
```

以下を参考にAWSCLIへクレデンシャルを設定。
[設定の基本]
(https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-quickstart.html)

```
aws configure
```

AWS SDK for Python (boto3) をインストール。

```
pip install tornado nose --user
pip install boto3 --user
```

# FreeRTOSの設定
これで環境設定はほぼ終了したので、FreeRTOSの設定に移ります。

## FreeRTOS をダウンロードして設定する
まずGitHubからFreeRTOSをダウンロード。

```
cd ~/IoT
git clone https://github.com/aws/amazon-freertos.git --recurse-submodules
```

次に以下のファイルをviで開いてWIFI等の情報を設定。
`~/IoT/amazon-freertos/tools/aws_config_quick_start/configure.json`

そして設定スクリプトを実行します。

```
cd ~/IoT/amazon-freertos/tools/aws_config_quick_start
python3 SetupAWS.py setup
```

設定スクリプトを実行すると、機器に対するクレデンシャルを生成し、AWS IoTへ登録してくれます。

```
$ python SetupAWS.py setup
Creating a Thing in AWS IoT Core.
Acquiring a certificate and private key from AWS IoT Core.
Writing certificate ID to: ESP32-DevKitC_cert_id_file
Writing certificate PEM to: ESP32-DevKitC_cert_pem_file
Writing private key PEM to: ESP32-DevKitC_private_key_pem_file
Creating a policy on AWS IoT Core.
Completed prereq operation!
Updated aws_clientcredential.h
Updated aws_clientcredential_keys.h
Completed update operation!
$
```

## FreeRTOS デモプロジェクトをビルド、フラッシュ、実行する

手順にはないですが、FreeRTOSをビルドする際に怒られるので、以下を実行しておきます。

```
python -m pip install --user -r  ~/IoT/amazon-freertos/vendors/espressif/esp-idf/requirements.txt
```

続いて、以下を実行してビルドファイルを作成。

```
cd ~/IoT/amazon-freertos/
mkdir ../FreeRTOS/
cmake -DVENDOR=espressif -DBOARD=esp32_wrover_kit -DCOMPILER=xtensa-esp32 -S . -B ../FreeRTOS/
```

そして、ビルドディレクトリに移り、以下を実行してビルド。

```
cd ../FreeRTOS/
make all -j4
```

## FreeRTOS をフラッシュおよび実行する
まず以下を実行してメモリ内を消去します。

```
cd ~/IoT/amazon-freertos/
./vendors/espressif/esp-idf/tools/idf.py erase_flash -B ../FreeRTOS/
```

最初は以下のエラーが出ましたが、何度かリトライしているうちに成功。

```
A fatal error occurred: Failed to connect to Espressif device: Invalid head of packet (0x2E)
```

削除が終わったら、ビルドしたFreeRTOSを書き込んで実行します。

```
./vendors/espressif/esp-idf/tools/idf.py flash -B ../FreeRTOS/
```

以下で実行状況を確認できます。

```
./vendors/espressif/esp-idf/tools/idf.py monitor -p /dev/ttyUSB0 -B ../FreeRTOS/
```

また、AWSコンソールでは、MQTTでHello worldが送られていることが確認できます。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679422/1be5bdb2-56d8-23d8-1b3f-eb8ba26f67d5.png)

ひとまずデモプログラムはこれで終了。

# （おまけ）Windowsでの環境構築の挫折の記録

最初は、CygwinでFreeRTOSのビルドを試みました。が、環境設定を終え、いよいよFreeRTOSのビルドのところで頓挫。Cygwin上で動くNinjaが参照するパスと、Windows上で動くEspressif Toolchainが参照するパスが食い違っていることが原因と思われます。

```
$ ninja
[0/2] Re-checking globbed directories...
(snip)
xtensa-esp32-elf-gcc.exe: error: /home/hisas/hisas/Downloads/amazon-freertos/vendors/espressif/boards/esp32/components/mbedtls/port/esp_sha256.c: No such file or directory
xtensa-esp32-elf-gcc.exe: fatal error: no input files
compilation terminated.
```

次に、AWSのWindows向け手順に沿ってMSYS2を入れてMinGW32上での環境構築を試みましたが、AWS CLIを入れようと`pip install awscli`を実行したところエラーが発生。復旧方法がわからず、あきらめました。