ESP32でマルチタスクを行う為の、とりあえずここまで判った事 by freeRTOS 5タスク目 [ESP32]
現在実用ガイドを読みながら編集中、、、書いて有る事を信用しない様に!
http://www.profdong.com/elc4438_spring2016/USINGTHEFREERTOSREALTIMEKERNEL.pdf
ESP32はRTOSができるらしい、、、
FreeRTOSの時間制御
μiTRONならdly_tsk(タスク付属同期機能)辺りの話。
○タイムティック
μiTRONと同様、FreeRTOSでもタイムティックと言う時間の単位の概念がある。
μiTRONの場合は1タイムティックは1msとする事が推奨されている。FreeRTOSではこの辺りのパラメータはportTICK_PERIOD_MSまたはportTICK_RATE_MSで定義されている。
ESP32ではportmacro.hの中で以下の様に定義されている。
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
また、portTICK_RATE_MSはFreeRTOS.hの中で以下の様に定義されている。
#define portTICK_RATE_MS portTICK_PERIOD_MS
configTICK_RATE_HZはFreeRTOSConfig.hの中で以下の様に定義されている。
#define configTICK_RATE_HZ ( CONFIG_FREERTOS_HZ )
CONFIG_FREERTOS_HZは
sdkconfig.hの中で以下の様に定義されている。
#define CONFIG_FREERTOS_HZ 1000
総合すると、タイムティックは1msである。
別のシステムでは、タイムティックは1msであるとは限らない。もっと短くても良いし、長くても良い。タイムティックの供給はタイマー割込みで実現されるので、処理能力の低いCPUの場合1ms周期の割込みは重いかもしれない。処理能力の高いCPUなら、もっと割込み周期を短くして時間分解能を上げられるかもしれない。
portTICK_PERIOD_MSは割込み周期を規定しているのであり、ある待ち時間をこの周期で割れば、何回割込みを数えれば良いか判る。
気の利いたマイコンなら、まあこの場合ARM Cortex-MとかだけどCPUコア側に24bit長のシステムタイマーを持っており、RTOSを組む時はこのタイマーを使ってね~~~って感じである。
※FreeRTOSの時間を扱う関数を見ていると、時間(ms)を計るというより、タイムティックを数えるようだ。なのでしばしば引数を以下の例の様に処理している。
vTaskDelay(ms / portTICK_PERIOD_MS);
※と思ったらpdMS_TO_TICKS( ms );と言うマクロが有った!
○タイムティックカウント
μiTRONではシステムタイマーとして単位をmsとした経過時間の変数を持っている。この変数は48bitで実現され、msで数えてもオーバーフローするまでに9000年くらい掛かる。
FreeRTOSでは、スケジューラーが起動してからのティック割込みの数をカウントしている。そう簡単にはオーバーフローしないらしい。
○時間の使い方
全てのコンピューターがそうとは言わないけれど、多くのコンピューターは意外と暇である。だからこそ宇宙人を探したり、マイニングしたりするのだ。
例えばLEDチカチカと言った場合、LEDの状態を変化させている処理はまさに何かの処理を行っているのだが、その時間は一瞬である。それ以外は何をしているかと言えばdelay関数で待っている。とにかく待っているだけである。
マルチタスクの概念は「そんなに暇ならもっと他の仕事をやらせよう!」だ。
○delay関数
素のArduinoであれば、delay関数に入ったら割込み以外の処理ができない。複数の処理をやろうとしている時に、関数に入ったらCPUの利用権を他に渡さない様な処理は迷惑以外の何物でもない。だが、こちらはRTOSなのでdelay関数に入ったからと言って割込み以外の別の作業ができないと言う訳ではない。
ESP32のdelay関数は、esp32-hal-misc.cの中で以下の様に記述されている。
vTaskDelay関数はFreeRTOSの時間待ちの関数であり、引数で渡された時間BLOCKEDに遷移する。
先の通りportTICK_PERIOD_MSはタイムティック時間であり1msなので引数のms時間だけ待つ事になる。
vTaskDelay関数のプロトタイプは以下の様になる。
void vTaskDelay( portTickType xTicksToDelay );
この関数は、この処理に入った時間からの相対時間分だけ待つ。
つまりvTaskDelay関数はμiTRONのdly_tskに相当する。
○周期起動
μiTRONでは周期起動はハンドラーとして起動する。※タイムティックを供給している割込み処理の中で、登録されたハンドラーが呼ばれる。
FreeRTOSでは以下の様に実現するようである。
vTaskDelayUntil関数を使用する。プロトタイプは以下の様になる。
void vTaskDelayUntil( portTickType * pxPreviousWakeTime, portTickType xTimeIncrement );
この関数を使うと一定周期でタスクが起床と待ちを繰り返す事ができる。
pxPreviousWakeTimeが最後にBLOCKED状態から抜けた時間。
xTimeIncrementが次回の起床までの相対(増加?)時間。
この2つの時間を元に、次にBLOCKED状態から抜ける時間を決める。
前回の起床時間を得る為にはxTaskGetTickCount関数を使用する。この関数はpxPreviousWakeTimeを初期化する為に、1回だけ使われる。プロトタイプは以下の様になる。
portTickType xTaskGetTickCount( void );
この2つの関数の使い方は以下の様になる。
http://www.profdong.com/elc4438_spring2016/USINGTHEFREERTOSREALTIMEKERNEL.pdf
ESP32はRTOSができるらしい、、、
FreeRTOSの時間制御
μiTRONならdly_tsk(タスク付属同期機能)辺りの話。
○タイムティック
μiTRONと同様、FreeRTOSでもタイムティックと言う時間の単位の概念がある。
μiTRONの場合は1タイムティックは1msとする事が推奨されている。FreeRTOSではこの辺りのパラメータはportTICK_PERIOD_MSまたはportTICK_RATE_MSで定義されている。
ESP32ではportmacro.hの中で以下の様に定義されている。
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
また、portTICK_RATE_MSはFreeRTOS.hの中で以下の様に定義されている。
#define portTICK_RATE_MS portTICK_PERIOD_MS
configTICK_RATE_HZはFreeRTOSConfig.hの中で以下の様に定義されている。
#define configTICK_RATE_HZ ( CONFIG_FREERTOS_HZ )
CONFIG_FREERTOS_HZは
sdkconfig.hの中で以下の様に定義されている。
#define CONFIG_FREERTOS_HZ 1000
総合すると、タイムティックは1msである。
別のシステムでは、タイムティックは1msであるとは限らない。もっと短くても良いし、長くても良い。タイムティックの供給はタイマー割込みで実現されるので、処理能力の低いCPUの場合1ms周期の割込みは重いかもしれない。処理能力の高いCPUなら、もっと割込み周期を短くして時間分解能を上げられるかもしれない。
portTICK_PERIOD_MSは割込み周期を規定しているのであり、ある待ち時間をこの周期で割れば、何回割込みを数えれば良いか判る。
気の利いたマイコンなら、まあこの場合ARM Cortex-MとかだけどCPUコア側に24bit長のシステムタイマーを持っており、RTOSを組む時はこのタイマーを使ってね~~~って感じである。
※FreeRTOSの時間を扱う関数を見ていると、時間(ms)を計るというより、タイムティックを数えるようだ。なのでしばしば引数を以下の例の様に処理している。
vTaskDelay(ms / portTICK_PERIOD_MS);
※と思ったらpdMS_TO_TICKS( ms );と言うマクロが有った!
○タイムティックカウント
μiTRONではシステムタイマーとして単位をmsとした経過時間の変数を持っている。この変数は48bitで実現され、msで数えてもオーバーフローするまでに9000年くらい掛かる。
FreeRTOSでは、スケジューラーが起動してからのティック割込みの数をカウントしている。そう簡単にはオーバーフローしないらしい。
○時間の使い方
全てのコンピューターがそうとは言わないけれど、多くのコンピューターは意外と暇である。だからこそ宇宙人を探したり、マイニングしたりするのだ。
例えばLEDチカチカと言った場合、LEDの状態を変化させている処理はまさに何かの処理を行っているのだが、その時間は一瞬である。それ以外は何をしているかと言えばdelay関数で待っている。とにかく待っているだけである。
マルチタスクの概念は「そんなに暇ならもっと他の仕事をやらせよう!」だ。
○delay関数
素のArduinoであれば、delay関数に入ったら割込み以外の処理ができない。複数の処理をやろうとしている時に、関数に入ったらCPUの利用権を他に渡さない様な処理は迷惑以外の何物でもない。だが、こちらはRTOSなのでdelay関数に入ったからと言って割込み以外の別の作業ができないと言う訳ではない。
ESP32のdelay関数は、esp32-hal-misc.cの中で以下の様に記述されている。
void delay(uint32_t ms) { vTaskDelay(ms / portTICK_PERIOD_MS); }
vTaskDelay関数はFreeRTOSの時間待ちの関数であり、引数で渡された時間BLOCKEDに遷移する。
先の通りportTICK_PERIOD_MSはタイムティック時間であり1msなので引数のms時間だけ待つ事になる。
vTaskDelay関数のプロトタイプは以下の様になる。
void vTaskDelay( portTickType xTicksToDelay );
この関数は、この処理に入った時間からの相対時間分だけ待つ。
つまりvTaskDelay関数はμiTRONのdly_tskに相当する。
○周期起動
μiTRONでは周期起動はハンドラーとして起動する。※タイムティックを供給している割込み処理の中で、登録されたハンドラーが呼ばれる。
FreeRTOSでは以下の様に実現するようである。
vTaskDelayUntil関数を使用する。プロトタイプは以下の様になる。
void vTaskDelayUntil( portTickType * pxPreviousWakeTime, portTickType xTimeIncrement );
この関数を使うと一定周期でタスクが起床と待ちを繰り返す事ができる。
pxPreviousWakeTimeが最後にBLOCKED状態から抜けた時間。
xTimeIncrementが次回の起床までの相対(増加?)時間。
この2つの時間を元に、次にBLOCKED状態から抜ける時間を決める。
前回の起床時間を得る為にはxTaskGetTickCount関数を使用する。この関数はpxPreviousWakeTimeを初期化する為に、1回だけ使われる。プロトタイプは以下の様になる。
portTickType xTaskGetTickCount( void );
この2つの関数の使い方は以下の様になる。
void cyclicTask( void *execParam ) { portTickType wakeupTime = xTaskGetTickCount(); while(1) { Serial.print( "wake time = " ); Serial.println( millis() ); vTaskDelayUntil( &wakeupTime, 100 ); } }
ITRONプログラミング入門 H8マイコンとHOSで始める組み込み開発
- 出版社/メーカー: オーム社
- 発売日: 2005/04/23
- メディア: Kindle版
リアルタイムOSと組み込み技術の基礎―実践μITRONプログラミング (TECHI (Vol.17))
- 作者: 高田 広章
- 出版社/メーカー: CQ出版
- 発売日: 2004/02
- メディア: 単行本
2018-02-18 13:08
nice!(0)
コメント(0)
コメント 0