delay関数の中身ってどうなってるの?
こうした悩みを解決します。
結論から言うと、
delay関数はRTOS上で動作しているタスクをブロック(=wait)させる処理
です。
この間に別のタスクが実行されます。初期状態ではタスクを作ってないので、アイドルタスクでぐるぐる回ってるはず。
※以下の記事はRTOSを知らない時点で書いてます。
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でタスク待ちを使っている
コメント