ESP32でマルチタスクを行う為の、とりあえずここまで判った事 by freeRTOS 20タスク目 [ESP32]
現在実用ガイドを読みながら編集中、、、書いて有る事を信用しない様に!
http://www.profdong.com/elc4438_spring2016/USINGTHEFREERTOSREALTIMEKERNEL.pdf
ESP32はRTOSができるらしい、、、
排他制御について
〇 クリティカルセクションとスケジューラーの一時停止、、、1
● クリティカルセクションの基本
※ESP32 Arduinoと、FreeRTOSのVersion.10のリファレンスマニュアルでは、クリティカルセクションを扱うマクロまたは関数に大きな違いがある。ESP32 Arduinoではマクロで定義され、引数を持つが、Version.10のリファレンスマニュアルではでは以下の様に関数となっているので、注意が必要。
上記の通りESP32 Arduinoと、FreeRTOSのVersion.10のリファレンスマニュアルで食い違いがあるので、ここではESP32 Arduinoを元にする。
クリティカルセクションの範囲は、taskENTER_CRITICAL()マクロとtaskEXIT_CRITICAL()マクロのそれぞれの呼び出しで囲まれた領域となる。
使い方は以下の様になる。
※μiTRONで言うところのloc_cpu、unl_cpuに該当すると思う。
taskENTER_CRITICALマクロ、taskEXIT_CRITICALマクロはtask.hの中で以下の様に定義されている。
また、portENTER_CRITICALマクロ、portEXIT_CRITICALマクロはportmacro.hの中で以下の様に定義されている。
ただしvTaskEnterCriticalは検索しても見つからないので、ライブラリ化されている?
注意書きとして以下の様に書かれている。
結局portENTER_CRITICALが割り込み禁止なのか、ディスパッチ禁止なのか、いやまぁ割り込みの中からも同等のマクロを使う点から割り込み禁止の様な気がしないでもないが、明確には判らなかった。
※割り込み禁止の様だ!
また、以下の様な記述もあるので、
多重割り込みのところ http://hamayan.blog.so-net.ne.jp/2018-02-26 でも説明したように、カーネル管理外の割り込みは発生する。この割り込みの中ではFreeRTOSの関数は呼ばないように。
Serial.printの様に複数のタスクから呼び出される可能性のある関数を使う時はクリティカルセクションを設定すれば、優先度の低いタスクが文字を出力中に、優先度の高いタスクに邪魔されずに済む。
サンプルコードは以下の様になる。2つのタスクを生成し、優先度の高いタスクが低いタスクのシリアル出力を邪魔をする。
https://github.com/hamayanShowa-ele/ArduinoShare/tree/main/ESP32freeRTOS_TASK_ID_020
以下は排他制御を行わなかった場合
以下は排他制御を行った場合
とまぁ、クリティカルセクションを設定するとカーネル管理の割り込みを停止してしまうので、可能な限りクリティカルセクションに入っている時間を短くする必要がある。また、必ずtaskENTER_CRITICALとtaskEXIT_CRITICALはペアで使う。
クリティカルセクションはカーネルによって呼び出し回数がカウントされている。taskENTER_CRITICAL毎に1カウントされ、これが0に戻るまでクリティカルセクションから抜けない。
※試しにtaskENTER_CRITICALを1回多くしたコードを実行すると、ESP32はある程度走ったところでリセットで再起動してしまう。
http://www.profdong.com/elc4438_spring2016/USINGTHEFREERTOSREALTIMEKERNEL.pdf
ESP32はRTOSができるらしい、、、
排他制御について
〇 クリティカルセクションとスケジューラーの一時停止、、、1
● クリティカルセクションの基本
※ESP32 Arduinoと、FreeRTOSのVersion.10のリファレンスマニュアルでは、クリティカルセクションを扱うマクロまたは関数に大きな違いがある。ESP32 Arduinoではマクロで定義され、引数を持つが、Version.10のリファレンスマニュアルではでは以下の様に関数となっているので、注意が必要。
void taskENTER_CRITICAL( void ); void taskEXIT_CRITICAL( void );
上記の通りESP32 Arduinoと、FreeRTOSのVersion.10のリファレンスマニュアルで食い違いがあるので、ここではESP32 Arduinoを元にする。
クリティカルセクションの範囲は、taskENTER_CRITICAL()マクロとtaskEXIT_CRITICAL()マクロのそれぞれの呼び出しで囲まれた領域となる。
使い方は以下の様になる。
taskENTER_CRITICAL( &mux ); PORTA |= 0x01; taskEXIT_CRITICAL( &mux );
※μiTRONで言うところのloc_cpu、unl_cpuに該当すると思う。
taskENTER_CRITICALマクロ、taskEXIT_CRITICALマクロはtask.hの中で以下の様に定義されている。
#define taskENTER_CRITICAL(mux) portENTER_CRITICAL(mux) #define taskEXIT_CRITICAL(mux) portEXIT_CRITICAL(mux) #define taskENTER_CRITICAL_ISR(mux) portENTER_CRITICAL_ISR(mux) #define taskEXIT_CRITICAL_ISR(mux) portEXIT_CRITICAL_ISR(mux)
また、portENTER_CRITICALマクロ、portEXIT_CRITICALマクロはportmacro.hの中で以下の様に定義されている。
#define portENTER_CRITICAL(mux) vTaskEnterCritical(mux, __FUNCTION__, __LINE__) #define portEXIT_CRITICAL(mux) vTaskExitCritical(mux, __FUNCTION__, __LINE__) #define portENTER_CRITICAL_ISR(mux) vTaskEnterCritical(mux, __FUNCTION__, __LINE__) #define portEXIT_CRITICAL_ISR(mux) vTaskExitCritical(mux, __FUNCTION__, __LINE__)
ただしvTaskEnterCriticalは検索しても見つからないので、ライブラリ化されている?
注意書きとして以下の様に書かれている。
Remark: For the ESP32, portENTER_CRITICAL and portENTER_CRITICAL_ISR both alias vTaskEnterCritical, meaning that either function can be called both from ISR as well as task context. This is not standard FreeRTOS behaviour; please keep this in mind if you need any compatibility with other FreeRTOS implementations.
結局portENTER_CRITICALが割り込み禁止なのか、ディスパッチ禁止なのか、いやまぁ割り込みの中からも同等のマクロを使う点から割り込み禁止の様な気がしないでもないが、明確には判らなかった。
※割り込み禁止の様だ!
また、以下の様な記述もあるので、
Interrupts may still execute on FreeRTOS ports that allow interrupt nesting, but only interrupts whose priority is above the value assigned to the configMAX_SYSCALL_INTERRUPT_PRIORITY constant – and those interrupts are not permitted to call FreeRTOS API functions.
多重割り込みのところ http://hamayan.blog.so-net.ne.jp/2018-02-26 でも説明したように、カーネル管理外の割り込みは発生する。この割り込みの中ではFreeRTOSの関数は呼ばないように。
Serial.printの様に複数のタスクから呼び出される可能性のある関数を使う時はクリティカルセクションを設定すれば、優先度の低いタスクが文字を出力中に、優先度の高いタスクに邪魔されずに済む。
taskENTER_CRITICAL( &mux ) ; Serial.println( "hello world." ); taskEXIT_CRITICAL( &mux );
サンプルコードは以下の様になる。2つのタスクを生成し、優先度の高いタスクが低いタスクのシリアル出力を邪魔をする。
https://github.com/hamayanShowa-ele/ArduinoShare/tree/main/ESP32freeRTOS_TASK_ID_020
void setup() { Serial.begin( 115200 ); Serial.println( "FreRTOS Test." ); /* configure take task1. */ xTaskCreatePinnedToCore( lowerPriorityTask, /* task name */ "", /* task name string */ 1024, /* stack size */ NULL, /* execute parameter */ 2, /* task priority : 0 to 24. 0 is lowest priority. */ NULL, /* task handle pointer */ 1 /* core ID */ ); /* configure take task2. */ xTaskCreatePinnedToCore( upperPriorityTask, /* task name */ "", /* task name string */ 1024, /* stack size */ NULL, /* execute parameter */ 3, /* task priority : 0 to 24. 0 is lowest priority. */ NULL, /* task handle pointer */ 1 /* core ID */ ); vTaskDelete( NULL ); /* delete loopTask. */ } void loop() { } void lowerPriorityTask( void *execParam ) { int count = 1; portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED; while( 1 ) { taskENTER_CRITICAL( &mux ) ; Serial.print( "lowerPriorityTask count = " ); Serial.println( count++,DEC ); taskEXIT_CRITICAL( &mux ); vTaskDelay( pdMS_TO_TICKS( 1 ) ); } } void upperPriorityTask( void *execParam ) { int count = 1; while( 1 ) { Serial.print( "upperPriorityTask count = " ); Serial.println( count++,DEC ); vTaskDelay( pdMS_TO_TICKS( 10 ) ); } }
以下は排他制御を行わなかった場合
以下は排他制御を行った場合
とまぁ、クリティカルセクションを設定するとカーネル管理の割り込みを停止してしまうので、可能な限りクリティカルセクションに入っている時間を短くする必要がある。また、必ずtaskENTER_CRITICALとtaskEXIT_CRITICALはペアで使う。
クリティカルセクションはカーネルによって呼び出し回数がカウントされている。taskENTER_CRITICAL毎に1カウントされ、これが0に戻るまでクリティカルセクションから抜けない。
※試しにtaskENTER_CRITICALを1回多くしたコードを実行すると、ESP32はある程度走ったところでリセットで再起動してしまう。
ITRONプログラミング入門 H8マイコンとHOSで始める組み込み開発
- 出版社/メーカー: オーム社
- 発売日: 2005/04/23
- メディア: Kindle版
リアルタイムOSと組み込み技術の基礎―実践μITRONプログラミング (TECHI (Vol.17))
- 作者: 高田 広章
- 出版社/メーカー: CQ出版
- 発売日: 2004/02
- メディア: 単行本
2018-03-06 11:25
nice!(0)
コメント(0)
コメント 0