SSブログ

ESP32でマルチタスクを行う為の、とりあえずここまで判った事 by freeRTOS 4タスク目 [ESP32]

現在実用ガイドを読みながら編集中、、、書いて有る事を信用しない様に!
http://www.profdong.com/elc4438_spring2016/USINGTHEFREERTOSREALTIMEKERNEL.pdf

ESP32はRTOSができるらしい、、、

あらためてFreeRTOSのタスクの生成と削除、優先度の変更を調べてみる。

μiTRONならcre_tsk、act_tsk、sta_tsk、ext_tsk、del_tsk、ter_tsk、chg_pri、ref_tsk(タスク管理機能)辺りの話。

FreeRTOSのヘッダーファイルとしては、
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
が有る。Arduino環境では特にインクルードしなくても大丈夫。

○タスク生成
まず基本的に以下のフォーマットの関数をユーザーが作る。
void ATaskFunction( void *pvParameters ) 
{ 
    while( 1 ) 
    { 
    } 
    vTaskDelete( NULL ); 
} 

関数名は任意であり、C言語の規則に則るならなんでも良い。
void型の関数であり、void*型の引数を取る。
pvParametersはxTaskCreate関数でタスクを登録した時に起動時引数として渡された値(ポインター)が入る。
また、多くの組み込みプログラムがそうであるように、whileなどの制御文で無限ループとなるが、必ずしも無限ループである必要は無い。でも大概は無限ループ。
vTaskDelete関数は、引数にNULLを指定する事で自タスクのタスク管理情報を登録先から削除する。その分CPUの処理やメモリの負担は軽くなる。

ちなみにESP Arduinoのmain.cppを見ると以下の様なコードになっている。
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "Arduino.h"

#if CONFIG_AUTOSTART_ARDUINO

#if CONFIG_FREERTOS_UNICORE
#define ARDUINO_RUNNING_CORE 0
#else
#define ARDUINO_RUNNING_CORE 1
#endif

void loopTask(void *pvParameters)
{
    setup();
    for(;;) {
        loop();
    }
}

extern "C" void app_main()
{
    initArduino();
    xTaskCreatePinnedToCore(loopTask, "loopTask", 4096, NULL, 1, NULL, ARDUINO_RUNNING_CORE);
}

#endif

と思ったら微妙に違うソースコードが存在していて、混乱している。
void loopTask(void *pvParameters)
{
    setup();
    for(;;) {
        micros(); //update overflow
        loop();
    }
}

extern "C" void app_main()
{
    initArduino();
    xTaskCreatePinnedToCore(loopTask, "loopTask", 8192, NULL, 1, NULL, ARDUINO_RUNNING_CORE);
}



○タスク登録
FreeRTOSのタスクの登録はxTaskCreate関数を使用する。
これはxTaskCreatePinnedToCore関数のコアの指定を行う引数が無いバージョンである。
ESP32で使用する時はxTaskCreatePinnedToCore関数を使用する。http://hamayan.blog.so-net.ne.jp/2018-02-16 を参照の事。
プロトタイプは以下の様になる。
portBASE_TYPE xTaskCreate(
  pdTASK_CODE pvTaskCode, 
  const signed portCHAR * const pcName,  
  unsigned portSHORT usStackDepth,  
  void *pvParameters,  
  unsigned portBASE_TYPE uxPriority,  
  xTaskHandle *pxCreatedTask  
);

(1) pvTaskCodeは起動時関数であり、上記であればATaskFunctionとなる。

(2) pcNameはFreeRTOSのデバック機能として提供されている、実行中のタスクの状態とか、スタック使用状況をモニターする時に使用するエイリアスみたいな物。ただしESP32ではこのデバック機能が有効化されていない。便利なのにぃ、、、(※1)
文字列の最大サイズは、FreeRTOSCOnfig.h内にconfigMAX_TASK_NAME_LENとして最大長がCONFIG_FREERTOS_MAX_TASK_NAME_LENが規定されているが、そのCONFIG_FREERTOS_MAX_TASK_NAME_LENはsdkconfig.hで定義されており、その値は16である。
必要無いならNULLを代入する事もできる。まぁESP32では必要無いか。と思ったけれど、ESP32ではNULLって書くとコアを履いて停止してしまうので、文字列を入れないなら””の方が良い。NULLの解釈が違うのか?

(3) usStackDepthはスタックサイズ。単位はWORDであり(なぜ?)CPUのintサイズに依存する。32bitCPUなら1WORD=4byte。
※FreeRTOSの公式ドキュメントなら上記だが、ESP32では単位はBYTEの模様。クソぅ!

※サイズをいくつに設定すべきか?実はFreeRTOSCOnfig.h内にconfigMINIMAL_STACK_SIZEと言う最低限のスタックサイズが定義され、安心して動かす為にはこの値以上に設定する。※値は1024かそれ以上、更に更にで参照が多いので自分で調べて!


(4) pvParametersは実行時引数であり、先のpvParameters引数にポインターとして渡される。ESP32では優先度を1とすると、なぜか正しく渡せないので、実行時引数を渡したいなら優先度は2以上を使う事。

(5) uxPriorityはタスク優先度である。

(6) pxCreatedTaskはおそらくタスクの管理領域へのポインターであり、1つのタスクに1つ必要となる。ただしNULLとする事もできる。

(7) 戻り値:タスクの生成に成功すれば pdTRUEが返る。失敗時は errCOULD_NOT_ALLOCATE_REQUIRED_MEMORYが返る。
失敗する原因は、HEAP領域不足。


○FreeRTOSのタスク優先度
ESP32のFreeRTOSConfig.hの中で以下の様に定義されている。
/* This has impact on speed of search for highest priority */
#ifdef SMALL_TEST
#define configMAX_PRIORITIES			( 7 )
#else
#define configMAX_PRIORITIES			( 25 )
#endif

この例では0から24までの優先度を設定でき、数字が小さいほど優先度が低くなる。
実際のところ優先度の数字は変数のサイズを越えない限りいくらでも大きくできるのだが、大きくするとそれだけタスク優先度別の管理領域を必要とする。なので、優先度は必要最低限な値にしておく。ただし、configMAX_PRIORITIESを超える値は自動的にconfigMAX_PRIORITIESに設定される。


○FreeRTOSのタスク優先度の変更と取得
優先度の変更は以下の関数で行う。μiTRONで言えばchg_pri。
動的に優先度を変更してしまう事はどうかと思うけれど、vTaskPrioritySet関数でできる。
プロトタイプは以下の様になる。
void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority );
xTaskはタスクハンドル。自身を指定する時はNULLを使える。
uxNewPriorityは新しい優先度

優先度の取得は以下の関数で行う。μiTRONで言えばget_pri。
プロトタイプは以下の様になる。
UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask );
xTaskはタスクハンドル。自身を指定する時はNULLを使える。
UBaseType_t型がどこで定義されているのか判らなかったけど、まぁ整数型なんでしょう。


○FreeRTOSのスケジューラーの起動
void vTaskStartScheduler( void );
ESP32 Arduinoでは既に起動しているので必要としない。
これはあくまでもスケジューラーの起動である。
μiTRONのsta_tskとかact_tskの様に個別にタスクを起動させる為には、都度xTaskCreate関数を使用する。


○FreeRTOSのタスクの削除
μiTRONで言えばter_tskとかext_tskとかになるのか?
プロトタイプは以下の様になる。
void vTaskDelete( TaskHandle_t xTask );
xTaskはタスクハンドルだが、自分自身を停止したい場合はNULLを入れる。μiTRONのTSK_SELFと同等?
※たとえタスクが待ち状態に入っていても、カーネルの検索リストに入っていたり、メモリを消費したままなので、不必要となったタスクは削除した方がCPUやメモリリソースの消費量を減らす事ができる。


○FreeRTOSのラウンドロビン
μiTRONであれば、周期ハンドラ辺りでrot_rdq()でタスクQUEUEを廻すところ、FreeRTOSでは自動的に同一優先度タスク間でラウンドロビンが実行される。ラウンドロビンの間隔はタイムスライスと呼ばれ、configTICK_RATE_HZとして定義されている。
FreeRTOSConfig.hの中で以下の様に定義されている。
#define configTICK_RATE_HZ ( CONFIG_FREERTOS_HZ )
CONFIG_FREERTOS_HZを探すと、sdkconfig.hの中で以下の様に定義されている。
#define CONFIG_FREERTOS_HZ 1000
1kHzでラウンドロビンが行われる。


○FreeRTOSで協調的マルチタスク
協調的マルチタスクと言えば!Windows3.1とかぁ、Mac OS8以前とかぁ、私作のOSでしょうか。優先度ベースのスケジューリングを行うマルチタスクで、わざわざ協調的マルチタスクにせんでも、、、と思わなくもないですが、できるらしい。
taskYIELD(); /* for Co-operative Scheduling */
タスクを切り替えたいタイミングで上記関数を使う。
http://hamayan.blog.so-net.ne.jp/2016-11-01
それはそれとして、同一優先度のタスクが複数有る場合はラウンドロビンでタスクが切り替えられるが、タスクの中で特にするべき処理が無くなった場合、このtaskYIELD()を呼ぶ事で協調的にCPU時間を振り分ける事ができる。



○FreeRTOSのidleタスク
μiTRON同様、何も動かすタスクが存在しない時、idleタスクが動く事となる。
idleタスクのスタックサイズはconfigMINIMAL_STACK_SIZEで定義される。ESP32の場合は1024以上となっている。もちろん4倍で換算する。

※1
タスク状態のモニター
READYとか、SUSPENDEDとか、BLOCKEDとか、DELETEDとか、優先度とかスタックサイズなんかが判るらしい。
使う為には事前にFreeRTOSConfig.hのconfigUSE_TRACE_FACILITYとconfigUSE_STATS_FORMATTING_FUNCTIONSを共に1に設定しておく。
※なのだけれど、FreeRTOSのライブラリ自体を再構築が必要で、ESP Arduinoではエラーを発生する。残念!
プロトタイプは以下の様になる。
void vTaskList( char *pcWriteBuffer );
pcWriteBufferは出力を格納するポインタ。

とりあえずタスクスタックの使用状況だけでも知りたい
プロトタイプは以下の様になる。
UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );
xTaskは言わずもがなタスクハンドル。
※なぜか0が返って来て、うまく行かない、、、





ITRONプログラミング入門 H8マイコンとHOSで始める組み込み開発

ITRONプログラミング入門 H8マイコンとHOSで始める組み込み開発

  • 出版社/メーカー: オーム社
  • 発売日: 2005/04/23
  • メディア: Kindle版



図解 μITRONによる組込みシステム入門(第2版)

図解 μITRONによる組込みシステム入門(第2版)

  • 作者: 武井 正彦
  • 出版社/メーカー: 森北出版
  • 発売日: 2018/02/17
  • メディア: 単行本(ソフトカバー)



μITRON4.0標準ガイドブック

μITRON4.0標準ガイドブック

  • 作者:
  • 出版社/メーカー: パーソナルメディア
  • 発売日: 2001/11/01
  • メディア: 単行本(ソフトカバー)



リアルタイムOSと組み込み技術の基礎―実践μITRONプログラミング (TECHI (Vol.17))

リアルタイムOSと組み込み技術の基礎―実践μITRONプログラミング (TECHI (Vol.17))

  • 作者: 高田 広章
  • 出版社/メーカー: CQ出版
  • 発売日: 2004/02
  • メディア: 単行本



nice!(0)  コメント(0) 

nice! 0

コメント 0

コメントを書く

お名前:[必須]
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

※ブログオーナーが承認したコメントのみ表示されます。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。