STM32のFreeRTOSを使ってみる

FreeRTOSの開始



STコア用のFreeRTOSはこ ちらに公開されていま す。
他のライブラリと同じようにライブラリマネージャーでAtduino-IDEに組み込むだけで使えるようになります。
なお、STコアをアップデートした場合、STM32FreeRtosもアップデートしないと動かなくなる場合が有ります。

STM32でFreeRTOSがどのように動くのか、良く分からなかったのでSTのエンジニアに聞いてみました。
STのエンジニアが丁寧に教えてくれました。
最初に以下のコードを書き込みます。
何の変哲もない、Arduinoのコードですが、STM32FreeRTOS.hをインクルードしています。
#include <STM32FreeRTOS.h>

// Task Body
void task(void *pvParameters)
{
    UBaseType_t prio;
    TickType_t nowTick;

    prio = uxTaskPriorityGet( NULL );
    nowTick = xTaskGetTickCount();
    printf("[%s:%d] start Priority=%d\n",pcTaskGetName(0),nowTick,(int)prio);
    vTaskDelay(10000 / portTICK_PERIOD_MS);
    nowTick = xTaskGetTickCount();
    printf("[%s:%d] end\n",pcTaskGetName(0),nowTick);
    vTaskDelete( NULL );
}


//------------------------------------------------------------------------------
void setup() {
  portBASE_TYPE xTask;

  Serial.begin(115200);
  Serial.println("setup() start");
  Serial.print("configTICK_RATE_HZ:");
  Serial.println(configTICK_RATE_HZ);
  Serial.print("portTICK_PERIOD_MS:");
  Serial.println(portTICK_PERIOD_MS);
  Serial.print("freeRTOS version:");
  Serial.println(tskKERNEL_VERSION_NUMBER);

  xTask = xTaskCreate(task, "Task", configMINIMAL_STACK_SIZE, NULL, 2, NULL);
  configASSERT( xTask );

#if 0 
  // start scheduler
  Serial.println("Start Scheduler.....");
  vTaskStartScheduler();
#endif

  while (1) {
    Serial.println("setup alive...");
    delay(1000);
  }
}

//------------------------------------------------------------------------------
// WARNING loop() called from vApplicationIdleHook(), so don't use this function.
// loop must never block
void loop() {
  // Not used.
}

実行すると、setup()の最後で1秒毎の表示を繰り返します。




次にコードの以下の部分を有効にします。
#if 1
  // start scheduler
  Serial.println("Start Scheduler.....");
  vTaskStartScheduler();
#endif

STM32の場合、setup()の最後でFreeRTOSのスケジューラーを「自分で」起動する必要が有ります。
vTaskStartScheduler()の説明がこちらに有ります。

Starts the RTOS scheduler. After calling the RTOS kernel has control over which tasks are executed and when.
The idle task and optionally the timer daemon task are created automatically when the RTOS scheduler is started.
vTaskStartScheduler() will only return if there is insufficient RTOS heap available to create the idle or timer daemon tasks.
All the RTOS demo application projects contain examples of using vTaskStartScheduler(), normally in the main() function within main.c.

RTOSスケジューラを起動します。 RTOSカーネルを呼び出した後、どのタスクがいつ実行されるかを制御できます。
RTOSスケジューラが起動されると、アイドルタスクとオプションでタイマーデーモンタスクが自動的に作成されます。
vTaskStartScheduler()は、アイドルまたはタイマーデーモンタスクを作成するために使用可能なRTOSヒープが不十分な場合 にのみ戻ります。
すべてのRTOSデモアプリケーションプロジェクトには、通常main.c内のmain()関数にvTaskStartScheduler()を 使用した例が含まれています。

実行すると以下の表示となります。
Taskが起動されています。
スケジューラが正しく起動されると、vTaskStartScheduler()からは戻ってこないので、これ以降のコードは実行されません。


FreeRTOSのバージョンは[9.0.0]、TickRateは1000Hz(1Tick=1mSec)で動いていることが分かります。

メモリ不足などでスケジューラが起動できないときだけ、vTaskStartScheduler()から戻ってくるので、
FreeRTOSのサンプルコードでは以下の様になっています。
この様になコードにしておくのがいいです。
  // start scheduler
  vTaskStartScheduler();
  Serial.println("Insufficient RAM");
  while(1);



スケジューラーが起動すると、loop()関数の扱いが変わります。
「STM32FreeRTOS/src/STM32FreeRTOS.c」に以下のコードが有ります。(STのエンジニアに教えてもらいました)
 #if ( configUSE_IDLE_HOOK == 1 )
     /** vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set
     to 1 in FreeRTOSConfig.h.  It will be called on each iteration of the idle
     task.  It is essential that code added to this hook function never attempts
     to block in any way (for example, call xQueueReceive() with a block time
     specified, or call vTaskDelay()).  If the application makes use of the
     vTaskDelete() API function (as this demo application does) then it is also
     important that vApplicationIdleHook() is permitted to return to its calling
     function, because it is the responsibility of the idle task to clean up
     memory allocated by the kernel to any task that has since been deleted. */
 void  __attribute__((weak)) vApplicationIdleHook( void ) {
   void loop();
   loop();
 }
 #endif /* configUSE_IDLE_HOOK == 1 */


loop()はvApplicationIdleHook()の中で呼び出されるようになります。
vApplicationIdleHook()はCPUがアイドル状態の時の呼び出される関数で、この関数には何もコードを書かないのが一般的で す。

続く....