PR

ESP32のdelay関数の中身を深掘りするとRTOSにたどり着く

ESP32のdelay関数の中身を深掘りしてみる 組み込み機器

delay関数の中身ってどうなってるの?

こうした悩みを解決します。

結論から言うと、
delay関数はRTOS上で動作しているタスクをブロック(=wait)させる処理
です。
この間に別のタスクが実行されます。初期状態ではタスクを作ってないので、アイドルタスクでぐるぐる回ってるはず。

※以下の記事はRTOSを知らない時点で書いてます。

立プロ

新卒でメーカーに入り、10年間組み込みの現場で設計を行う。
今は個人事業主として自作の組み込み機器開発や、エージェント様に紹介いただき業務委託を行っています。
C,C#,JavaScript, Vue, PHP, VBA, GAS, Kotlinなど、扱う言語が増えゆく日々。

立プロをフォローする

delay関数の使い方

delay関数は以下のように記述して使います。

delay(1000);

ミリ秒を引数として与えてやることで、その間処理が停止します。

上記の例では1000ミリ秒なので1秒の遅延時間を与えるということになります。

使い方としてはとても簡単ですよね。

delay関数の定義

ではここからdelay関数の中身を見ていきましょう。

void delay(ms){
  vTaskDelay(ms/portTICK_PERIOD_MS);
}

まずこの関数から引数に与えるミリ秒は符号なしの整数で32ビット、つまり4バイトで0~4294967295の大きさが取れることが分かります。

この引数と定数との比をとって、vTaskDelay関数に入れていますね。

ここで定数portTICK_PERIOD_MSの定義をまず見てみましょう。

#define portTICK_PERIOD_MS((TickType_t)1000/configTICK_RATE_HZ)

このように定義されています。

まず(TickType_t)は、1000/configTICK_RATE_HZの結果をTickType_t型にキャスト(=型変換)する、という意味になります。

TickType_t型とは何なのか定義を見てみましょう。

typedefuint32_t TickType_t;

ですので、符号なしの整数で32ビットと同じです。なぜこのように定義したのかは分かりません。

後述しますが、TickType_t型はRTOS特有の型です。
delay関数は突き詰めるとRTOSの制御ということになります。

分子が符号なしの整数32ビットだということが分かったので、このことから分母の定数も同じ符号なしの整数32ビットなんだろうなという予測がつきますね。

では分母の定数の定義を見てみましょう。

#define configTICK_RATE_HZ    (CONFIG_FREERTOS_HZ)

んー…さらに別の定数CONFIG_FREERTOS_HZを参照する必要があります。

#define CONFIG_FREERTOS_HZ    1000

となっていました。

つまり、configTICK_RATE_HZ=CONFIG_FREERTOS_HZ=1000ですね。

ということは遡って

#define portTICK_PERIOD_MS((TickType_t)1000/configTICK_RATE_HZ)

#define portTICK_PERIOD_MS((uint32_t)1000/1000)

であり、

portTICK_PERIOD_MSは符号なしの整数32ビット型の1であるという事が分かりました。

なので、もっと遡って

vTaskDelay(ms/portTICK_PERIOD_MS);

vTaskDelay(ms/1);⇒vTaskDelay(ms);

となりますね。

さて、やっとvTaskDelay関数の引数の詳細が分かったので、vTaskDelay関数の定義を見てみましょ(もう疲れてきた。

void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION;

んー、ん?これはどういう…。よく見たら、FreeRTOSConfig.hに飛んでいる、マルチタスクってことか!

まとめ

delay関数はRTOSでタスク待ちを使っている

コメント

タイトルとURLをコピーしました