ESP32 + Amazon FreeRTOS で自分のプロジェクトを作成

# はじめに
こちらの続きです。
[ESP32にAmazon FreeRTOSを入れてAWS-IoTにつなぐ（Windows, Toolchain 8.4.0）](https://qiita.com/hisashij/items/e8944bc87f6dbad9e398)

Amazon FreeRTOSを入手してデモを動かすところまではできましたが、その後、自分のプロジェクトを作るところでつまづいたので、その記録です。`Hello World`を出力することだけします。今回はAWS IoTにつなぎません。

こちらを参考に進めます。
[Using FreeRTOS in your own CMake project for ESP32](https://docs.aws.amazon.com/freertos/latest/userguide/getting_started_espressif.html#getting_started_espressif_cmake_project)

【今回の環境】

- [ESP32-DevKitC-32D](http://akizukidenshi.com/catalog/goods/search.aspx?search=x&keyword=M-13628)
- Amazon FreeRTOS Version 202012.00
- Toolchain v5.2.0
- Windows 10

# フォルダ構成
こうしました。

```
C:\IoT\
 └ ESP-FreeRTOS\
 　  ├ Tools\                   ... Toolkit
 　  ├ FreeRTOS\                ... Amazonからダウンロードしたもの
 　  └ Projects\
 　  　  └ 01_hello_world\      ... 今回のプロジェクト
 　  　  　  ├ CMakeLists.txt
 　  　  　  └ src\
 　  　  　  　  └ main.c
```

# プログラム
mainプログラムは、ESP-IDFに付属のhello_worldを参考に、シンプルなものを用意。
https://github.com/espressif/esp-idf/blob/master/examples/get-started/hello_world/main/hello_world_main.c

```01_hello_world\src\main.c
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"

void app_main()
{
    printf("Hello world!\n");

    for (int i = 10; i >= 0; i--) {
        printf("Restarting in %d seconds...\n", i);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
    printf("Restarting now.\n");
    fflush(stdout);
    esp_restart();
}
```

`CMakeFiles.txt`は、AWSのドキュメントに載っていたものを参考に以下のようにしました。

```01_hello_world\CMakeLists.txt
cmake_minimum_required(VERSION 3.13)

project(hello_world)

add_executable(hello_world src/main.c)

# Tell IDF build to link against this target.
set(IDF_PROJECT_EXECUTABLE hello_world)

# Add FreeRTOS as a subdirectory. AFR_BOARD tells which board to target.
set(AFR_BOARD espressif.esp32_devkitc CACHE INTERNAL "")
add_subdirectory(../../FreeRTOS FreeRTOS)
```

# ビルド（Try & Error）
ビルドしてみます。

```
C:\IoT\ESP-FreeRTOS\Projects\01_hello_world> cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=../../FreeRTOS/tools/cmake/toolchains/xtensa-esp32.cmake -GNinja
-- The C compiler identification is GNU 5.2.0
-- The CXX compiler identification is GNU 5.2.0
-- The ASM compiler identification is GNU
(...snip...)
-- Configuring done
-- Generating done
-- Build files have been written to: C:/IoT/ESP-FreeRTOS/Projects/01_hello_world/build

C:\IoT\ESP-FreeRTOS\Projects\01_hello_world> cmake --build build
(...snip...)
[947/948] Linking CXX executable hello_world
FAILED: hello_world
cmd.exe /C "cd . && C:\IoT\ESP-FreeRTOS\Tools\tools\bin\xtensa-esp32-elf-g++.exe -mlongcalls -nostdlib @CMakeFiles\hello_world.rsp -o hello_world  && cd ."
FreeRTOS/esp-idf/freertos/libfreertos.a(tasks.c.obj):(.literal.xTaskIncrementTick+0x18): undefined reference to `vApplicationTickHook'
FreeRTOS/esp-idf/freertos/libfreertos.a(tasks.c.obj):(.literal.vTaskStartScheduler+0x18): undefined reference to `vApplicationGetIdleTaskMemory'
FreeRTOS/esp-idf/freertos/libfreertos.a(tasks.c.obj):(.literal.prvIdleTask+0x0): undefined reference to `vApplicationIdleHook'
FreeRTOS/esp-idf/freertos/libfreertos.a(tasks.c.obj): In function `xTaskIncrementTick':
C:/IoT/ESP-FreeRTOS/FreeRTOS/freertos_kernel/tasks.c:5248: undefined reference to `vApplicationTickHook'
C:/IoT/ESP-FreeRTOS/FreeRTOS/freertos_kernel/tasks.c:5248: undefined reference to `vApplicationTickHook'
FreeRTOS/esp-idf/freertos/libfreertos.a(tasks.c.obj): In function `vTaskStartScheduler':
C:/IoT/ESP-FreeRTOS/FreeRTOS/freertos_kernel/tasks.c:5248: undefined reference to `vApplicationGetIdleTaskMemory'
FreeRTOS/esp-idf/freertos/libfreertos.a(tasks.c.obj): In function `prvIdleTask':
C:/IoT/ESP-FreeRTOS/FreeRTOS/freertos_kernel/tasks.c:5248: undefined reference to `vApplicationIdleHook'
FreeRTOS/esp-idf/freertos/libfreertos.a(timers.c.obj):(.literal.xTimerCreateTimerTask+0x18): undefined reference to `vApplicationGetTimerTaskMemory'
FreeRTOS/esp-idf/freertos/libfreertos.a(timers.c.obj):(.literal.prvTimerTask+0x0): undefined reference to `vApplicationDaemonTaskStartupHook'
FreeRTOS/esp-idf/freertos/libfreertos.a(timers.c.obj): In function `xTimerCreateTimerTask':
C:/IoT/ESP-FreeRTOS/FreeRTOS/freertos_kernel/timers.c:338: undefined reference to `vApplicationGetTimerTaskMemory'
FreeRTOS/esp-idf/freertos/libfreertos.a(timers.c.obj): In function `prvTimerTask':
C:/IoT/ESP-FreeRTOS/FreeRTOS/freertos_kernel/timers.c:750: undefined reference to `vApplicationDaemonTaskStartupHook'
collect2.exe: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.

C:\IoT\ESP-FreeRTOS\Projects\01_hello_world>
```

いくつか関数定義が足りず、リンクでエラーが出ました。
それぞれFreeRTOSのデモ用のソースコードにあった関数定義を`src\main.c`にコピー。

| 関数 | コピー元 |
|:--|:--|
| `vApplicationTickHook()` | `vendors\espressif\boards\esp32\aws_demos\application_code\main.c` |
| `vApplicationIdleHook()` | `vendors\espressif\boards\esp32\aws_demos\application_code\main.c` |
| `vApplicationDaemonTaskStartupHook()` | `vendors\espressif\boards\esp32\aws_demos\application_code\main.c` |
| `vApplicationGetIdleTaskMemory()` | `demos\demo_runner\aws_demo.c` |
| `vApplicationGetTimerTaskMemory()` | `demos\demo_runner\aws_demo.c` |

再度ビルド。

```
C:\IoT\ESP-FreeRTOS\Projects\01_hello_world> cmake --build build
[0/2] Re-checking globbed directories...
[1/6] Performing build step for 'bootloader'
ninja: no work to do.
[4/4] Generating ../hello_world.bin
esptool.py v2.8

C:\IoT\ESP-FreeRTOS\Projects\01_hello_world>
```

上手くいったようなので、フラッシュしてモニタします。

```
C:\IoT\ESP-FreeRTOS\Projects\01_hello_world> cmake --build build --target flash
(...snip...)
Hard resetting via RTS pin...

C:\IoT\ESP-FreeRTOS\Projects\01_hello_world> python ..\..\FreeRTOS\vendors\espressif\esp-idf\tools\idf.py monitor
(...snip...)
Hello world!
Restarting in 10 seconds...
Restarting in 9 seconds...
Restarting in 8 seconds...
Restarting in 7 seconds...
Restarting in 6 seconds...
Restarting in 5 seconds...
Restarting in 4 seconds...
Restarting in 3 seconds...
Restarting in 2 seconds...
Restarting in 1 seconds...
Restarting in 0 seconds...
Restarting now.
ets Jun  8 2016 00:22:57
(...snip...)
Hello world!
Restarting in 10 seconds...
Restarting in 9 seconds...
Restarting in 8 seconds...
Restarting in 7 seconds...
(...以降繰り返し...)
```

うまく動きました。