Amazon FreeRTOSのHello World用のリポジトリを作ってみた(WindowsとESP-WROOM-32にて作業)

FreeRTOSのビルド環境を勉強していましたが、最小限のHello Worldから始めたくて、作ったリポジトリです。

github.com

前提条件

以下が前提条件となります。

  • Windows10
  • Python3
  • Git

以下の ESP-WROOM-32 で動作確認しています。

ビルド作業

全てのCLI作業はコマンドプロンプトから行います。

リポジトリの取得

Cloneしてきます。この際に --recursive を付けてsubmoduleも全てCloneするようにします。

git clone --recursive https://github.com/yomon8/amazon-freertos-helloworld-esp32.git
cd amazon-freertos-helloworld-esp32

なお、最初に通常通りCloneしてしまった場合は以下のようにサブモジュールを取得してください。

git clone https://github.com/yomon8/amazon-freertos-helloworld-esp32.git
cd amazon-freertos-helloworld-esp32
git submodule update --init --recursive

なお現時点ではFreeRTOSの 202012.00 のタグを組み込んでいます。

ESP-IDF v4.2 のインストール

AWSの手順にも v3.3v4.2 の2パターンの記述がありますが、ここでは v4.2 で話を進めます。

以下のようにインストーラーを実行する前に、 version.txt というファイルを準備することで、指定したバージョンのESP-IDFをインストールできます。

echo v4.2 > amazon-freertos\vendors\espressif\esp-idf\version.txt
amazon-freertos\vendors\espressif\esp-idf\install.bat

export.bat を実行することでESP-IDF利用のための変数が設定されます。

amazon-freertos\vendors\espressif\esp-idf\export.bat

export.bat 実行後にcmakeの場所を確認してみると、ホーム配下にインストールされたcmakeを指していることが確認できます。

> where cmake
C:\Users\your.user.name\.espressif\tools\cmake\3.13.4\bin\cmake.exe

ビルドファイルの生成

引続きリポジトリのディレクトリで作業します。

以下のコマンドでビルド用のファイルを準備します。

cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=amazon-freertos\tools\cmake\toolchains\xtensa-esp32.cmake -GNinja

デバイスへ書き込み

USBにデバイスを接続して、書き込みます。

環境変数 ESPPORT にてCOMのポートを指定します。

set ESPPORT=COM6
cmake --build build --target flash

動作確認

idf.py を使って動作を確認します。

set ESPPORT=COM6
idf.py monitor

以下のようにHello Worldのメッセージが表示されるはずです。

Start
HelloWorld! 0
HelloWorld! 1
HelloWorld! 2
HelloWorld! 3
HelloWorld! 4
HelloWorld! 5
HelloWorld! 6
HelloWorld! 7
HelloWorld! 8
HelloWorld! 9
Restart
...

補足

M5StickC Plusでの動作確認

転送レートを ESPBAUD で指定すると書き込めます。

set ESPBAUD=115200
set ESPPORT=COM5
cmake --build build --target flash
main.c

Cのソースで重要というか独自の部分はここだけです。

void vHelloWorld(void *pvParams)
{
    for (int i = 0; i < 10; i++)
    {
        printf("HelloWorld! %d\n", i);
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
    printf("Restart\n");
    esp_restart();
}

void app_main()
{
    printf("Start\n");
    xTaskCreate(vHelloWorld, "HelloWorld", configMINIMAL_STACK_SIZE * 2, NULL, tskIDLE_PRIORITY, NULL);
}

後はAWSのBlackBeltの資料を見ると書き方わかると思います。

この辺りは以下で定義されてました。ESP32での書き方と認識です。

https://github.com/espressif/esp-afr-sdk/blob/1d2d93acd1dfd00a63309cdeb109a467efbcb327/components/esp32/freertos_hooks.c#L35-L64

extern void esp_vApplicationTickHook();
void IRAM_ATTR vApplicationTickHook()
{
    esp_vApplicationTickHook();
}

extern void esp_vApplicationIdleHook();
void vApplicationIdleHook()
{
    esp_vApplicationIdleHook();
}

以下は部分はこちらのURLに記載されている内容です。

FreeRTOS Static Memory Allocation FreeRTOS - The Free RTOS configuration constants and configuration options - FREE Open Source RTOS for small real time embedded systems

/* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an
 * implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
 * used by the Idle task. */
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
                                   StackType_t **ppxIdleTaskStackBuffer,
                                   uint32_t *pulIdleTaskStackSize)
{
    static StaticTask_t xIdleTaskTCB;
    static StackType_t uxIdleTaskStack[configMINIMAL_STACK_SIZE];
    *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
    *ppxIdleTaskStackBuffer = uxIdleTaskStack;
    *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
/*-----------------------------------------------------------*/

/**
 * @brief This is to provide the memory that is used by the RTOS daemon/time task.
 *
 * If configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an
 * implementation of vApplicationGetTimerTaskMemory() to provide the memory that is
 * used by the RTOS daemon/time task.
 */
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
                                    StackType_t **ppxTimerTaskStackBuffer,
                                    uint32_t *pulTimerTaskStackSize)
{
    static StaticTask_t xTimerTaskTCB;
    static StackType_t uxTimerTaskStack[configTIMER_TASK_STACK_DEPTH];

    *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
    *ppxTimerTaskStackBuffer = uxTimerTaskStack;
    *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}

参考URL

AWS公式

docs.aws.amazon.com

途中で 見つけたEXAMPLEリポジトリ。

github.com

参考になったIssue

github.com