So-net無料ブログ作成

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

現在実用ガイドを読みながら編集中、、、ある事ない事書いちょりまっす!
http://www.profdong.com/elc4438_spring2016/USINGTHEFREERTOSREALTIMEKERNEL.pdf

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

データタイプと命名規則、、、1

〇 データタイプ
FreeRTOSが使うデータタイプは以下の通りになる。
  portCHAR  char
  portSHORT  short 
  portLONG  long
  portTickType (1)を参照
  portBASE_TYPE (2)を参照

(1) ティックカウントを保存したり、ブロックするティック数を示したりする。portTickTypeは符号無し16bitまたは符号無し32bit型を取る。何bitにするかはFreeRTOSConfig.hの中のconfigUSE_16_BIT_TICKSに記述されている。
ESP32 Arduinoの定義を見てみると、
  #define configUSE_16_BIT_TICKS  0

となっている、、、えーっときっと32bitなのだろうけれど、sizeof演算子で確かめてみると、、、4(32bit)でした。
  Serial.print( "portTickType size =" ); Serial.println( sizeof(portTickType), DEC );

16bit型の使用は、8bitとか16bitアーキテクチャの効率を格段に改善する。が、ブロックするティック数に厳しい制限が付く。32bitアーキテクチャに16bit型を使うのはセンスが悪い。

(2) これはアーキテクチャにとって、最も効率的な型を定義される。通常、32bitアーキテクチャでは32bit型であり、16bitアーキテクチャでは16bit型、8bitアーキテクチャでは8bit型となる。
portBASE_TYPEは一般的に論理型の限定的な値を返す戻り値として使われる。

※char型はコンパイラそれぞれで符号有り型、符号無し型があり、FreeRTOSではどちらの型の使用も認めている。

※int型は決して使わない。longまたはshort型のみである、、、となっているんだけれど、ESP32 Arduinoのportmacro.hの中では以下の様に記述されている。
  #define portBASE_TYPE  int

おぃ!

ついで。portmacro.hの一部抜き出し。
/* Type definitions. */

#define portCHAR		int8_t
#define portFLOAT		float
#define portDOUBLE		double
#define portLONG		int32_t
#define portSHORT		int16_t
#define portSTACK_TYPE	uint8_t
#define portBASE_TYPE	int

typedef portSTACK_TYPE			StackType_t;
typedef portBASE_TYPE			BaseType_t;
typedef unsigned portBASE_TYPE	UBaseType_t;

#if( configUSE_16_BIT_TICKS == 1 )
	typedef uint16_t TickType_t;
	#define portMAX_DELAY ( TickType_t ) 0xffff
#else
	typedef uint32_t TickType_t;
	#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif



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) 

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

現在実用ガイドを読みながら編集中、、、ある事ない事書いちょりまっす!
http://www.profdong.com/elc4438_spring2016/USINGTHEFREERTOSREALTIMEKERNEL.pdf

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

排他制御について
〇 ゲートキーパータスク(達)

ゲートキーパータスクは、デッドロックや優先度の逆転におびえる事無しに、すっきりとした実装方法を提供する。ゲートキーパータスクはその名の通りタスクであり、資源に対して単一の所有権を持つ。ゲートキーパータスクのみ資源に直接的なアクセスが許可され、他のタスクはゲートキーパータスクのサービスを使って間接的に資源にアクセスする。

ようするに資源にアクセスする専用のタスクを用意するので、資源利用の競合を無くせる。
例えばSPIデバイスに複数のタスクがアクセスする事を考えてみると、ある優先度の低いタスクがSPI通信中に別の優先度の高いタスクにプリエンプトされ、そのタスクがSPI通信してしまうと色々まずい事が起きそうである。

これを排他制御でバイナリーセマフォなり、ミューテックスなりでSPIにアクセス可能なタスクを制限してしまう事は可能だが、そうするとタスクに待ち状態が発生し、それぞれのタスクの処理が寸断されてしまう。

以下の例ではデータキューを使って複数のタスクからメッセージをSerial.printしているが、メッセージをゲートキーパータスクに託したタスクは、そのまま処理を継続できる。※まぁ寝ているけどね。
xQueueHandle que;

void setup()
{
  Serial.begin( 115200 );
  Serial.println( "FreRTOS Test." );

  /* create data queue */
  que = xQueueCreate( 10, sizeof(char *) );

  /* configure take task1. */
  xTaskCreatePinnedToCore(
    gateKeeperTask,  /* task name */
    "",     /* task name string */
    configMINIMAL_STACK_SIZE,   /* stack size */
    NULL,   /* execute parameter */
    1,      /* task priority : 0 to 24. 0 is lowest priority. */
    NULL,   /* task handle pointer */
    1       /* core ID */
  );

  /* configure take task2. */
  xTaskCreatePinnedToCore(
    task2,  /* task name */
    "",     /* task name string */
    configMINIMAL_STACK_SIZE,   /* stack size */
    NULL,   /* execute parameter */
    2,      /* task priority : 0 to 24. 0 is lowest priority. */
    NULL,   /* task handle pointer */
    1       /* core ID */
  );

  /* configure take task3. */
  xTaskCreatePinnedToCore(
    task3,  /* task name */
    "",     /* task name string */
    configMINIMAL_STACK_SIZE,   /* 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 gateKeeperTask( void *execParam )
{
  while( 1 )
  {
    char *pvBuffer;
    xQueueReceive( que, (void *)&pvBuffer, portMAX_DELAY );
    Serial.print( pvBuffer );
  }
}

void task2( void *execParam )
{
  static const char *msg = "this is task2.\r\n";
  while( 1 )
  {
    xQueueSendToBack( que, (const void *)&msg, portMAX_DELAY );
    vTaskDelay( pdMS_TO_TICKS( 250 ) );
  }
}

void task3( void *execParam )
{
  static const char *msg = "this is task3.\r\n";
  while( 1 )
  {
    xQueueSendToBack( que, (const void *)&msg, portMAX_DELAY );
    vTaskDelay( pdMS_TO_TICKS( 500 ) );
  }
}

ESP32_gateKeeper_001.png



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) 

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

現在実用ガイドを読みながら編集中、、、ある事ない事書いちょりまっす!
http://www.profdong.com/elc4438_spring2016/USINGTHEFREERTOSREALTIMEKERNEL.pdf

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

今回は実験、Tick hookはESP32 Arduinoで使えるか?

Tick hookは、Tickを供給している割り込みから、専用の関数をコールバックする機能。これを使う為にはconfigUSE_TICK_HOOKを1にしてからコンパイルする必要がある。

configUSE_TICK_HOOKはFreeRTOSConfig.hの中で以下の様に定義されている。
#define configUSE_TICK_HOOK  ( CONFIG_FREERTOS_LEGACY_TICK_HOOK )

CONFIG_FREERTOS_LEGACY_TICK_HOOKは、、、えー!どこぉ???orz
またしても怪しい感じだが、一応チャレンジしてみる。
この辺とかねー http://hamayan.blog.so-net.ne.jp/2018-02-19

まずコールバックされる関数だが、例によってユーザー独自の関数と言う訳ではなく、関数名やプロトタイプは決まっている。
void vApplicationTickHook( void )
{
  // user codes.
}


そこで以下の様なデモプログラムを作成してみた。
volatile int count = 0;

void vApplicationTickHook( void )
{
  count++;
}

void setup()
{
  Serial.begin( 115200 );
  Serial.println( "FreRTOS Test." );
}

void loop()
{
  while( 1 )
  {
    delay( 1000 );
    Serial.print( "count is = " ); Serial.println( count, DEC );
  }
}

その結果は!、、、orz
ESP32_vApplicationTickHook_001.png



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)  コメント(2) 

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

現在実用ガイドを読みながら編集中、、、ある事ない事書いちょりまっす!
http://www.profdong.com/elc4438_spring2016/USINGTHEFREERTOSREALTIMEKERNEL.pdf

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

排他制御について
〇 ミューテックス(とバイナリーセマフォ)、、、4

● デッドロック
デッドロックは排他制御をした時の他の落とし穴である。デッドロックは別名”Deadly Embrace”(死の抱擁)とも呼ばれる、、、らしい。日本なら「5人の哲学者」であろう。

デッドロックは資源を共有している2つ以上のタスクが、自分でトークンを持ちながら相手のトークンを待つ様な状況の時に発生する。
以下の様な状況を考えてみよう。タスクAとタスクBはそれぞれmutexXとmutexYを待っている。
1.タスクAはmutexXのTakeに成功する。

2.タスクAはタスクBによりプリエンプトされる。

3.タスクBはmutexXのTakeを試みる前に、mutexYのTakeに成功する。しかしmutexXはタスクAが持ったままであり、タスクBはmutexXのTakeは叶わない。この為タスクBはmutexXの待ち状態に入る。

4.タスクAの実行が続けられる。タスクAはmutexYのTakeを試みる、が、mutexYはタスクBが持ったままであり、タスクAはmutexYのTakeは叶わない。この為タスクAはmutexYの待ち状態に入る。

5.全員寝たままで誰も起こさない。


デッドロックを避ける最良の方法は、設計時に充分考慮する事である。また問題が起きないようにシステムをシンプルにすることである。実際には小規模な組込みシステムではデッドロックは大きな問題ではない。何故ならシステム設計者はアプリケーション全体をよりよく知り、デッドロックを起こす様な領域を認識し、避ける事ができるからである。

※大きな組込みシステムでは問題にならない!とは言っていない?

※言うまでも無いだろうけれど、セマフォなりミューテックスをTakeする際に待ち時間の上限時間を設定できるので、かならず上限設定を行って、戻って来た時に戻り値を確認すべき。そうすればデッドロックは避けられる。


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) 

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

現在実用ガイドを読みながら編集中、、、ある事ない事書いちょりまっす!
http://www.profdong.com/elc4438_spring2016/USINGTHEFREERTOSREALTIMEKERNEL.pdf

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

排他制御について
〇 ミューテックス(とバイナリーセマフォ)、、、3

● 優先度の継承
FreeRTOSのミューテックスとバイナリーセマフォはすごく似ている。唯一の違いはミューテックスは優先度継承の機構を持つ点である。優先度継承は、優先度の逆転の負の側面を最小にする枠組みである。固定された優先度の逆転ではなく、単にその影響を軽減する。
ただ、優先度継承はシステムの振舞いの数学的な解析をより複雑にする。その為優先度継承の利用を避けられない状況以外での利用は薦められない。

優先度継承はトークン・ホルダーの優先度を一時的に、資源の利用を待つタスクの中でもっとも高い優先度と同じレベルに上げる。資源の利用が終わり、ミューテックスをGiveすれば、自動的に元の優先度に戻る。


以下のデモプログラムはバイナリーセマフォを使って優先度が低、中、高の3つのタスクを動かした時の出力。文字列に続く数値はmillis()の出力であり、図の1行目と2行目に100msの時間差が発生している。通常は優先度の高いタスクは10ms周期で出力するが、優先度の逆転が起きて優先度が中間のタスクに邪魔をされている。
volatile SemaphoreHandle_t sema;

void setup()
{
  Serial.begin( 115200 );
  Serial.println( "FreRTOS Test." );

  // Create binary semaphore
  sema = xSemaphoreCreateBinary();
  xSemaphoreGive( sema );  /* give one semaphore */

  /* configure take task1. */
  xTaskCreatePinnedToCore(
    lowerPriorityTask,  /* task name */
    "",     /* task name string */
    configMINIMAL_STACK_SIZE,   /* 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(
    middlePriorityTask,  /* task name */
    "",     /* task name string */
    configMINIMAL_STACK_SIZE,   /* stack size */
    NULL,   /* execute parameter */
    3,      /* task priority : 0 to 24. 0 is lowest priority. */
    NULL,   /* task handle pointer */
    1       /* core ID */
  );

  /* configure take task3. */
  xTaskCreatePinnedToCore(
    upperPriorityTask,  /* task name */
    "",     /* task name string */
    configMINIMAL_STACK_SIZE,   /* stack size */
    NULL,   /* execute parameter */
    4,      /* 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 )
{
  while( 1 )
  {
    xSemaphoreTake( sema, portMAX_DELAY );
    Serial.print( "lowerPriorityTask time = " ); Serial.println( millis(), DEC );
    xSemaphoreGive( sema );

    vTaskDelay( pdMS_TO_TICKS( 1 ) );
  }
}

void middlePriorityTask( void *execParam )
{
  while( 1 )
  {
    vTaskDelay( pdMS_TO_TICKS( 20 ) );
//    Serial.print( "middlePriorityTask time = " ); Serial.println( millis(), DEC );
    unsigned long baseMillis = millis();
    while( (millis() - baseMillis) < 100UL ) {}  /* never enter block state. */
  }
}

void upperPriorityTask( void *execParam )
{
  int count = 1;
  while( 1 )
  {
    xSemaphoreTake( sema, portMAX_DELAY );
    Serial.print( "upperPriorityTask time = " ); Serial.println( millis() ,DEC );
    xSemaphoreGive( sema );

    vTaskDelay( pdMS_TO_TICKS( 10 ) );
  }
}

ESP32_mutex_005.png



以下のデモプログラムは、ミューテックスを使って優先度が低、中、高の3つのタスクを動かした時の出力。上のデモプログラムでは40ms近辺で優先度の逆転が起きているが、今回は1行目辺りから見ていくと、およそ100ms間低い優先度のタスクの出力は行われていないが、優先度の高いタスクは10ms周期で出力している。低い優先度のタスクに、優先度の高いタスクの優先度が継承されたと思われる。
volatile xSemaphoreHandle mux;

void setup()
{
  Serial.begin( 115200 );
  Serial.println( "FreRTOS Test." );

  // Create mutex
  mux = xSemaphoreCreateMutex();

  /* configure take task1. */
  xTaskCreatePinnedToCore(
    lowerPriorityTask,  /* task name */
    "",     /* task name string */
    configMINIMAL_STACK_SIZE,   /* 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(
    middlePriorityTask,  /* task name */
    "",     /* task name string */
    configMINIMAL_STACK_SIZE,   /* stack size */
    NULL,   /* execute parameter */
    3,      /* task priority : 0 to 24. 0 is lowest priority. */
    NULL,   /* task handle pointer */
    1       /* core ID */
  );

  /* configure take task3. */
  xTaskCreatePinnedToCore(
    upperPriorityTask,  /* task name */
    "",     /* task name string */
    configMINIMAL_STACK_SIZE,   /* stack size */
    NULL,   /* execute parameter */
    4,      /* 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 )
{
  while( 1 )
  {
    xSemaphoreTake( mux, portMAX_DELAY );
    Serial.print( "lowerPriorityTask time = " ); Serial.println( millis(), DEC );
    xSemaphoreGive( mux );

    vTaskDelay( pdMS_TO_TICKS( 1 ) );
  }
}

void middlePriorityTask( void *execParam )
{
  while( 1 )
  {
    vTaskDelay( pdMS_TO_TICKS( 20 ) );
//    Serial.print( "middlePriorityTask time = " ); Serial.println( millis(), DEC );
    unsigned long baseMillis = millis();
    while( (millis() - baseMillis) < 100UL ) {}  /* never enter block state. */
  }
}

void upperPriorityTask( void *execParam )
{
  int count = 1;
  while( 1 )
  {
    xSemaphoreTake( mux, portMAX_DELAY );
    Serial.print( "upperPriorityTask time = " ); Serial.println( millis() ,DEC );
    xSemaphoreGive( mux );

    vTaskDelay( pdMS_TO_TICKS( 10 ) );
  }
}

ESP32_mutex_006.png


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) 

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

現在実用ガイドを読みながら編集中、、、ある事ない事書いちょりまっす!
http://www.profdong.com/elc4438_spring2016/USINGTHEFREERTOSREALTIMEKERNEL.pdf

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

排他制御について
〇 ミューテックス(とバイナリーセマフォ)、、、2

● 優先度の逆転
前回のデモプログラム http://hamayan.blog.so-net.ne.jp/2018-03-07-1 は、排他制御を行う場合の潜在的な落とし穴がある。デモプログラムを実行すると優先度の高いタスクが優先度の低いタスクに実行を待たされる場面がある。この現象を「優先度の逆転」と呼ぶ。

この望ましくない動作は特に中間の優先度を持つタスクが存在したときに問題になる。

優先度の低いタスクが優先度が中間のタスクにプリエンプトされて待ち状態に入った場合、優先度が中間のタスクが待ち状態に入るなどして優先度の低いタスクが再開されない限り優先度の高いタスクも待ち状態から再開されない。つまり本来は優先度の低いタスクと優先度の高いタスクの間で資源の排他制御を行っていたものが、優先度が中間のタスクが存在する為に優先度の高いタスクまで優先度の中間のタスクの動作に影響を受ける。



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) 

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

現在実用ガイドを読みながら編集中、、、ある事ない事書いちょりまっす!
http://www.profdong.com/elc4438_spring2016/USINGTHEFREERTOSREALTIMEKERNEL.pdf

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

排他制御について
〇 ミューテックス(とバイナリーセマフォ)、、、1?

ミューテックスはバイナリーセマフォの特殊なタイプで、資源を共有する複数のタスク間で資源へのアクセスを制御する。ミューテックスの語源は排他制御の”MUTual EXclusion”、、、そうだったのか!気にした事無かった。

排他制御として使われるミューテックスは、共有される資源に付随するトークンとして考える事ができる。正式に資源にアクセスする為にトークンを"Take"したタスクを、「トークン・ホルダーになる」と言う。トークン・ホルダーが資源の利用を終えたら、"Give"してトークンを戻さなければならない。トークンが戻された場合に限り他のタスクはトークンを得る事ができ、安全に共有資源にアクセスできる。言い換えれば、トークンを得ないタスクは資源にアクセスする事を許可されない。

● xSemaphoreCreateMutex関数
ミューテックスはセマフォのタイプの一つである。xSemaphoreHandleタイプの変数に保存されるFreeRTOSセマフォの全てのタイプを取り扱う 。
ミューテックスは使われる前に生成されなければならない。ミューテックスを生成する為にはxSemaphoreCreateMutex関数を使用する。
プロトタイプは以下となる。
  xSemaphoreHandle xSemaphoreCreateMutex( void );

(1) 戻り値:もしNULLが返って来たら、ミューテックスの生成に失敗している。失敗する原因は、HEAP領域の不足である。NULL以外が返って来た時はミューテックスの生成に成功した。戻ってきた値は、生成したミューテックスへのハンドルである。


例のコードを今度はミューテックスで置き換えてみた。2つのタスク間の排他制御なので、両方のタスクにミューテックスのTakeとGiveを使っている。
xSemaphoreHandle mux;

void setup()
{
  Serial.begin( 115200 );
  Serial.println( "FreRTOS Test." );

  mux = xSemaphoreCreateMutex();
  /* configure take task1. */
  xTaskCreatePinnedToCore(
    lowerPriorityTask,  /* task name */
    "",     /* task name string */
    configMINIMAL_STACK_SIZE,   /* 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 */
    configMINIMAL_STACK_SIZE,   /* 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;
  while( 1 )
  {
    xSemaphoreTake( mux, portMAX_DELAY );
    Serial.print( "lowerPriorityTask count = " ); Serial.println( count++,DEC );
    xSemaphoreGive( mux );

    vTaskDelay( pdMS_TO_TICKS( 1 ) );
  }
}

void upperPriorityTask( void *execParam )
{
  int count = 1;
  while( 1 )
  {
    xSemaphoreTake( mux, portMAX_DELAY );
    Serial.print( "upperPriorityTask count = " ); Serial.println( count++,DEC );
    xSemaphoreGive( mux );

    vTaskDelay( pdMS_TO_TICKS( 10 ) );
  }
}

実行した結果は以下となった。割込み禁止で行った結果と一致する。
ESP32_mutex_001.png



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) 

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

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

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

排他制御について
〇 クリティカルセクションとスケジューラーの一時停止、、、2

● スケジューラーの一時停止
クリティカルセクションはスケジューラーの一時停止でも実現できる。スケジューラーの一時停止はスケジューラーの”Locking”とも知られている、、、?

基本的にクリティカルセクションは、割り込みや他のタスクからコードがアクセスされる領域を保護する。クリティカルセクションの実装をスケジューラーの一時停止で行った場合、他のタスクからのみ領域を保護する。この事はつまり割り込みからのアクセスは有効のままである。

単純に割り込み禁止で実現するクリティカルセクションの実装でその処理の実行時間が掛かる場合、スケジューラーの一時停止で実現するクリティカルセクションに置き換える事ができる。しかしスケジューラーの一時停止ではスケジューラーの再開に時間が掛かるので、それぞれの方法についてどちらを選ぶかは十分考慮する必要がある。

スケジューラーはvTaskSuspendAll関数の呼び出しで一時停止させられる。その時点からコンテキストスイッチ(タスクの切り替え)は停止するが、割り込みは許可されたままである。スケジューラーが一時停止中に割り込みがコンテキストスイッチを要求したなら、コンテキストスイッチの要求はペンディングされ、スケジューラの再開時に実行される。

FreeRTOSの関数はスケジューラーの一時停止中に使われるべきではない。
※一時停止の解除の関数は別だろうけれど。

スケジューラーの再開はxTaskResumeAll関数を呼ぶことで行われる。

● vTaskSuspendAll関数
プロトタイプは以下になる。
  void vTaskSuspendAll( void );


● xTaskResumeAll関数
プロトタイプは以下になる。
  portBASE_TYPE xTaskResumeAll( void );

(1) 戻り値:スケジューラーが一時停止中に受けたコンテキストスイッチの要求はペンディングされ、スケジューラーが再開されたタイミングで行われる。事前にペンディングされたコンテキストスイッチはxTaskResumeAll関数の終了直前に実行され pdTRUEを返す。それ以外のケースでは pdFALSEを返す。

vTaskSuspendAllの呼び出しとxTaskResumeAllの呼び出しはカーネルによってカウントされている。カウントが0に戻る事で、スケジューラーは再開される。

使い方は以下の様になる。
  vTaskSuspendAll();  /* suspend scheduler */
  PORTA |= 0x01;
  xTaskResumeAll();  /* resume scheduler */

※μiTRONで言うところのdis_dsp、ena_dspに該当すると思う。

前回の例題 http://hamayan.blog.so-net.ne.jp/2018-03-06 を作りかえてtaskENTER_CRITICALをvTaskSuspendAllに、taskEXIT_CRITICALをxTaskResumeAllとしたものを動かしてみた。
void setup()
{
  Serial.begin( 115200 );
  Serial.println( "FreRTOS Test." );

  /* configure take task1. */
  xTaskCreatePinnedToCore(
    lowerPriorityTask,  /* task name */
    "",     /* task name string */
    configMINIMAL_STACK_SIZE,   /* 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 */
    configMINIMAL_STACK_SIZE,   /* 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;
  while( 1 )
  {
    vTaskSuspendAll();
    Serial.print( "lowerPriorityTask count = " ); Serial.println( count++,DEC );
    xTaskResumeAll();

    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 ) );
  }
}

が、リセットを繰り返し正常に動かない。
    Serial.print( "lowerPriorityTask count = " ); Serial.println( count++,DEC );

をコメントアウトするとリセットされないので、Serial.printと何かあるのかもしれない。


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) 

ESP32でマルチタスクを行う為の、とりあえずここまで判った事。 20タスク目 [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つのタスクを生成し、優先度の高いタスクが低いタスクのシリアル出力を邪魔をする。
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 ) );
  }
}

以下は排他制御を行わなかった場合
ESP32_criticalSection_001.png

以下は排他制御を行った場合
ESP32_criticalSection_002.png


とまぁ、クリティカルセクションを設定するとカーネル管理の割り込みを停止してしまうので、可能な限りクリティカルセクションに入っている時間を短くする必要がある。また、必ずtaskENTER_CRITICALとtaskEXIT_CRITICALはペアで使う。

クリティカルセクションはカーネルによって呼び出し回数がカウントされている。taskENTER_CRITICAL毎に1カウントされ、これが0に戻るまでクリティカルセクションから抜けない。
※試しにtaskENTER_CRITICALを1回多くしたコードを実行すると、ESP32はある程度走ったところでリセットで再起動してしまう。


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) 

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

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

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

排他制御について
※この内容は、資源管理 http://hamayan.blog.so-net.ne.jp/2018-02-26-1 の続きとなる。

タスク間や、タスクと割り込みの間で共有資源にアクセスする時、排他制御が必要となる。
FreeRTOSには排他制御を利用する為のいくつかの機能が提供されている。だがもっとも良い排他制御の方法は、アプリケーションが資源を共有しない、または1つのタスクのみ資源にアクセスする、、、おぃ!

この章は、読者により良い理解してもらう事を目的としている。
● 何時?何故?資源の管理と制御が必要となるのか?

● クリティカルセクションとは?

● 排他制御とは?

● スケジューラーを一時停止する意味とは?

● どのようにミューテックスを使うのか?

● どの様にゲートキーパータスクを生成するのか?

● 優先度逆転とは?どの様に優先度継承の影響を減らすか?


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)