Quantcast
Channel: Under Power 研究所
Viewing all 201 articles
Browse latest View live

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

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

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

多重割り込み
FreeRTOSConfig.h内で以下の様に定義されている。
/* The priority at which the tick interrupt runs.  This should probably be
   kept at 1. */
#define configKERNEL_INTERRUPT_PRIORITY  1

configKERNEL_INTERRUPT_PRIORITYは、タイムティックを供給している割り込みの優先度。もしconfigMAX_SYSCALL_INTERRUPT_PRIORITYが使われていないのなら、割り込みを使用する全てのAPI関数は、この割り込みの優先度で実行されなければならない。
/* The maximum interrupt priority from which FreeRTOS.org API functions can
   be called.  Only API functions that end in ...FromISR() can be used within
   interrupts. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY  XCHAL_EXCM_LEVEL

XCHAL_EXCM_LEVELはcore_isa.h内に以下の様に定義されている。
#define XCHAL_EXCM_LEVEL  3	/* level masked by PS.EXCM */
	/* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */

※ESP32ではcore_isa.hはプロジェクトの中に複数存在し、どれも3を定義しているが、どのファイルが実際に使われているか解らない。

configMAX_SYSCALL_INTERRUPT_PRIORITYはAPI関数が使用するもっとも高い割り込みの優先度を示す。

※高機能なCPUでは多重割り込みの機能を持つ物が多い。これは割り込み処理自体にも優先度を設定して、より緊急度の高い割り込みは、他の割り込みに実行を邪魔されない為である。
μiTRONでもそうだけれど定義される割り込みには2種類あり、1つはカーネルが管理する割り込み、1つはカーネルが管理しない割り込みとなる。
一般的にカーネルが管理する割り込みでは、割り込みの最後にディスパッチが行われるために割り込みの反応がその分遅れる事が有る。これを許容できないシステムではカーネルが管理しない割り込みを使う事になるが、その場合RTOSが使用する割り込み優先度よりも高い優先度を持つ割り込みを使用する事となる。

ESP32の割り込みレベルを探してみたら、esp_intr_alloc.h内にこんな定義をみつけた。
//Keep the LEVELx values as they are here; they match up with (1<<level)
#define ESP_INTR_FLAG_LEVEL1		(1<<1)	///< Accept a Level 1 interrupt vector (lowest priority)
#define ESP_INTR_FLAG_LEVEL2		(1<<2)	///< Accept a Level 2 interrupt vector
#define ESP_INTR_FLAG_LEVEL3		(1<<3)	///< Accept a Level 3 interrupt vector
#define ESP_INTR_FLAG_LEVEL4		(1<<4)	///< Accept a Level 4 interrupt vector
#define ESP_INTR_FLAG_LEVEL5		(1<<5)	///< Accept a Level 5 interrupt vector
#define ESP_INTR_FLAG_LEVEL6		(1<<6)	///< Accept a Level 6 interrupt vector
#define ESP_INTR_FLAG_NMI			(1<<7)	///< Accept a Level 7 interrupt vector (highest priority)
#define ESP_INTR_FLAG_SHARED		(1<<8)	///< Interrupt can be shared between ISRs
#define ESP_INTR_FLAG_EDGE			(1<<9)	///< Edge-triggered interrupt
#define ESP_INTR_FLAG_IRAM			(1<<10)	///< ISR can be called if cache is disabled
#define ESP_INTR_FLAG_INTRDISABLED	(1<<11)	///< Return with this interrupt disabled

#define ESP_INTR_FLAG_LOWMED	(ESP_INTR_FLAG_LEVEL1|ESP_INTR_FLAG_LEVEL2|ESP_INTR_FLAG_LEVEL3) ///< Low and medium prio interrupts. These can be handled in C.
#define ESP_INTR_FLAG_HIGH		(ESP_INTR_FLAG_LEVEL4|ESP_INTR_FLAG_LEVEL5|ESP_INTR_FLAG_LEVEL6|ESP_INTR_FLAG_NMI) ///< High level interrupts. Need to be handled in assembly.

#define ESP_INTR_FLAG_LEVELMASK	(ESP_INTR_FLAG_LEVEL1|ESP_INTR_FLAG_LEVEL2|ESP_INTR_FLAG_LEVEL3| \
								 ESP_INTR_FLAG_LEVEL4|ESP_INTR_FLAG_LEVEL5|ESP_INTR_FLAG_LEVEL6| \
								 ESP_INTR_FLAG_NMI) ///< Mask for all level flags

この内容なら、一般的に使用される割り込みレベルは1~6までかな?
レベル1~3までの優先度の割り込みはCで書けるが、レベル4~6、NMIはアセンブラで書けよ!とも書いてある。
https://esp-idf.readthedocs.io/en/v2.0/api/system/intr_alloc.html




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
  • メディア: 単行本



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

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

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

資源管理
例えば以下の様な例題を考えてみる。前提としてTaskAとTaskBの2つのタスクがあり、TaskBはTaskAより優先度が高く、通常は何かの待ちをしている。

(1) TaskAはLCDに「Hello world.」を出力しようとしている。

(2) TaskAは「Hello w」を書いたところでTaskBにプリエンプトされてしまう。

(3) TaskBは「Abort, Retry, Fail?」を出力。その後待ち状態へ。

(4) TaskAはディスパッチされて残りの「orld.」を出力。

(5) 結果、LCDに表示された文字は「Hello wAbort, Retry, Fail?orld.」となる。

LCDと言う1つの資源に、同時に2つのタスクがアクセスした、あるある例である。

また次のケースはもっと深刻で、例としてARM7のPORTAの特定のビットを変化させる様な処理について、
POARTA |= 0x01;のアセンブラ出力を見てみると、
esp32_WDT_Message_003.png

一旦メモリから読み出した内容に、修正を加えて、またメモリに書き戻す Read Modify Writeが行われている事が判る。※専用のビット操作命令を持たないマイコンの場合は大概こうなっている。
アセンブラにすると5命令だが、この間に割り込みが入り、プリエンプトされてしまう可能性がある。

例えば以下の様な例題を考えてみる。前提としてTaskAとTaskBの2つのタスクがあり、TaskA、TaskB共にPORTAにアクセスする。TaskBはTaskAより優先度が高く、通常は何かの待ちをしている。

(1) TaskAが現在のPORTAの内容を読み出す処理を行う。例えば0x00が読み出されたとする。

(2) TaskAは変更が完了する前にTaskBにプリエンプトされてしまう。

(3) TaskBは現在のPORTAの内容を読み出し、0x00を0x02に変更し、PORTAに書き戻す。その後TaskBは待ち状態に入る。

(4) TaskAがディスパッチされて中断していた処理を再開する。つまり0x00を0x01に変更してPORTAに書き戻す。

(5) TaskBの努力は、無に帰してしまったようだ。

※上記問題はPORTAの様な汎用ポートだけでなく、大域変数でも起こる。

※Read Modify Write専用の命令があり、1命令で実行できる場合は上記問題は起きない。この辺はアキーテクチャ毎にCPU命令を調べておく必要がある。

※関数が複数のタスクや割り込みから呼び出されても安全に機能するとき、リエントラント性が有ると呼ばれる。全ての変数がスタック(自動変数)上やCPUレジスタ上で動いていれば、リエントラント性は確保できる。一次的にでも大域変数を使う関数は、リエントラント性を確保できない。関数ライブラリのマニュアルを読むとリエントラント性について書かれている。


ESP32のGPIOに関してはARM Cortex-Mと同様、GPIOの個別の端子の出力レジスタ値をSETするレジスタ(GPIO_OUT_W1TS_REG)またはRESETするレジスタ(GPIO_OUT_W1TC_REG)がある。このレジスタは書くだけなので、資源の競合が起きない。
http://hamayan.blog.so-net.ne.jp/2018-02-22 のコードを、以下の様に変更する事ができる。
const int ledPin = 2;
hw_timer_t * timer = NULL;
volatile SemaphoreHandle_t timerSemaphore;

#define  GPIObit0To31OutReg   *((volatile unsigned long *)GPIO_OUT_REG)
#define  GPIObit0To31Set      *((volatile unsigned long *)GPIO_OUT_W1TS_REG)
#define  GPIObit0To31Reset    *((volatile unsigned long *)GPIO_OUT_W1TC_REG)

void IRAM_ATTR onTimer()
{
  // Give a semaphore that we can check in the loop
  xSemaphoreGiveFromISR( timerSemaphore, NULL );
}

void setup()
{
  Serial.begin( 115200 );
  Serial.println( "FreRTOS Test." );
  pinMode( ledPin, OUTPUT );
  digitalWrite( ledPin, LOW );  /* turn off led. */

  // Create semaphore to inform us when the timer has fired
  timerSemaphore = xSemaphoreCreateBinary();

  // Use 1st timer of 4 (counted from zero).
  // Set 80 divider for prescaler (see ESP32 Technical Reference Manual for more
  // info).
  timer = timerBegin( 0, 80, true );
  // Attach onTimer function to our timer.
  timerAttachInterrupt( timer, &onTimer, true );
  // Set alarm to call onTimer function every second (value in microseconds).
  // Repeat the alarm (third parameter)
  timerAlarmWrite( timer, 100 * 1000UL, true );
  // Start an alarm
  timerAlarmEnable( timer );

  /* configure led blink task. */
  xTaskCreatePinnedToCore(
    task1,  /* 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 */
  );
  vTaskDelete( NULL );  /* delete loopTask. */
}

void loop()
{
}

void task1( void *execParam )
{
  while( 1 )
  {
    if( xSemaphoreTake(timerSemaphore, 0) == pdTRUE )
    {
//      digitalWrite( ledPin, ( digitalRead(ledPin) ) ? LOW : HIGH );  /* toggle led. */
        if( GPIObit0To31OutReg & (1UL << ledPin) ) GPIObit0To31Reset = (1UL << ledPin);
        else GPIObit0To31Set   = (1UL << ledPin);
    }
  }
}


※ESP32のesp32_hal_gpio.cの中で以下の様なコードとなっているので、マルチタスクでdigitalWriteを使っても大丈夫と思われる。
extern void IRAM_ATTR __digitalWrite(uint8_t pin, uint8_t val)
{
    if(val) {
        if(pin < 32) {
            GPIO.out_w1ts = ((uint32_t)1 << pin);
        } else if(pin < 34) {
            GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32));
        }
    } else {
        if(pin < 32) {
            GPIO.out_w1tc = ((uint32_t)1 << pin);
        } else if(pin < 34) {
            GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32));
        }
    }
}




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
  • メディア: 単行本


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

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

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

今回は実験
digitalWriteは遅いとか言われるが、果たしてその実力は?
まずこんなコードを用意してみた。digitalWriteを使う場合と、GPIOのSET、RESETレジスタを使う場合。
const int ledPin = 2;
#define  GPIObit0To31OutReg   *((volatile unsigned long *)GPIO_OUT_REG)
#define  GPIObit0To31Set      *((volatile unsigned long *)GPIO_OUT_W1TS_REG)
#define  GPIObit0To31Reset    *((volatile unsigned long *)GPIO_OUT_W1TC_REG)

void setup()
{
  Serial.begin( 115200 );
  Serial.println( "FreRTOS Test." );
  pinMode( ledPin, OUTPUT );
  digitalWrite( ledPin, LOW );  /* turn off led. */
}

void loop()
{
  while( 1 )
  {
    GPIObit0To31Set = 0x04;  /* turn on led. */
    GPIObit0To31Reset = 0x04;  /* turn off led. */
//    digitalWrite( ledPin, HIGH );  /* turn on led. */
//    digitalWrite( ledPin, LOW );  /* turn off led. */
  }
}

とは言え、digitalWriteの中身はピン番号の判断と、やはりSET、RESETレジスタを叩くので、その判断の辺りがペナルティになる程度。
この画像はSET、RESETレジスタを直接操作したもの。およそ10MHz出ている。
ESP32_GPIO_Alternate_001.png


この画像はdigitalWriteを使ったもの。およそ4.3MHz出ている。
ESP32_GPIO_Alternate_002.png


割込み等で周期が乱れていない事を確認する為にジッターを確認。RTOSのタイムティックを生成している1ms周期のタイマー割込みは、ここでは影響していない模様。ウソです、ウソつきました。11μsくらい何かいます。
ESP32_GPIO_Alternate_003.png

ESP32_GPIO_Alternate_test_004.png

ESP32_GPIO_Alternate_test_005.png


遅いと言われるのは、loopの中身を無限ループにしていない為に、別のところ(loopTask)でmicrosの計測を行っている為だと思われる。

ふと思ったのだが、digitalWriteはIRAM_ATTRで修飾されているが、loopTask自体は特にそういった修飾は無いので、もしかしてloopをIRAM_ATTRで修飾してGPIObit0To31Setマクロを使えば、最強?いやでも、キャッシュもあるしなぁ、、、→IRAM_ATTRで修飾しても、10MHzで変わりませんでした!


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
  • メディア: 単行本


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

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

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

カウンティングセマフォ、、、について書く事を忘れていた。
バイナリーセマフォは2値、0と1とか、YesかNoとか、攻めと受けとかで制御を行うが、カウンティングセマフォは1よりも大きい数を使って制御する。

カウンティングセマフォと言えば思い浮かべるのはあれだろうか?イナバの物置には100人乗れるが、101人乗ると崩壊する、、、(イナバに怒られないかな?)とする。
100人まではスムースに屋根の上に乗れるが、101人目は誰かが降りるまでその場に待たされる。誰か一人降りれば、次の方どうぞ!となる。これはつまり誰かが屋根の上の人数を数えていて、100人未満なら100人になるまで乗せる。100人に達したら待ちにさせる動作である。

バイナリーセマフォ同様GiveとTakeの関係で説明すれば、1回Giveする事でカウントが1増える。1回Takeすることでカウントが1減る。カウントが0であればTake側を待たせる。

バイナリーセマフォの長所は、とても小さなリソースやCPU負荷で、タスク間の同期を取れる。
短所は、Takeする側のタスクの優先度が低く、そのタスクの処理に時間が掛かる時、セマフォを取りこぼす可能性がある。
※割り込みは、どのタスクよりも高い優先度を持つタスクとも考えられる。

バイナリーセマフォを使って以下のプログラムを実行すると、Giveは50まで数えるが、Takeは46で停止する。
volatile SemaphoreHandle_t xSemaphore;

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

  // Create semaphore to inform us when the timer has fired
  xSemaphore = xSemaphoreCreateBinary();

  /* configure take task. */
  xTaskCreatePinnedToCore(
    takeTask,  /* 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 give task. */
  xTaskCreatePinnedToCore(
    giveTask,  /* 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 giveTask( void *execParam )
{
  int count = 1;
  while( 1 )
  {
    vTaskDelay( pdMS_TO_TICKS( 500 ) );
    Serial.print( "give count =" ); Serial.println( count, DEC );
    xSemaphoreGive( xSemaphore );
    if( ++count > 50 ) vTaskDelete( NULL );
  }
}

void takeTask( void *execParam )
{
  int count = 1;
  while( 1 )
  {
    if( xSemaphoreTake( xSemaphore, 0 ) == pdTRUE )
    {
      Serial.print( "take count =" ); Serial.println( count++, DEC );
    }
    vTaskDelay( pdMS_TO_TICKS( 550 ) );
  }
}

ESP32_counterSema_001.png


セマフォのタイプをカウンティングセマフォとしたプログラム。この場合はTake側も50で停止する。
volatile SemaphoreHandle_t xSemaphore;

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

  // Create semaphore to inform us when the timer has fired
  xSemaphore = xSemaphoreCreateCounting( 100, 0 );

  /* configure take task. */
  xTaskCreatePinnedToCore(
    takeTask,  /* 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 give task. */
  xTaskCreatePinnedToCore(
    giveTask,  /* 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 giveTask( void *execParam )
{
  int count = 1;
  while( 1 )
  {
    vTaskDelay( pdMS_TO_TICKS( 500 ) );
    Serial.print( "give count =" ); Serial.println( count, DEC );
    xSemaphoreGive( xSemaphore );
    if( ++count > 50 ) vTaskDelete( NULL );
  }
}

void takeTask( void *execParam )
{
  int count = 1;
  while( 1 )
  {
    if( xSemaphoreTake( xSemaphore, 0 ) == pdTRUE )
    {
      Serial.print( "take count =" ); Serial.println( count++, DEC );
    }
    vTaskDelay( pdMS_TO_TICKS( 550 ) );
  }
}

ESP32_counterSema_002.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
  • メディア: 単行本


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

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

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

カウンティングセマフォで使用する関数。

カウンティングセマフォでも、生成、Give、Takeそれぞれの関数を必要とするが、GiveとTakeに関してはバイナリーセマフォと同一の為、生成について解説する。
例によって2つの生成関数があり、1つは必要な領域を動的に生成するxSemaphoreCreateCounting関数。
1つは必要な領域をユーザーが事前に(静的に)生成しておくxSemaphoreCreateCountingStatic関数。
プロトタイプは以下になる。
SemaphoreHandle_t xSemaphoreCreateCounting(
  UBaseType_t uxMaxCount,  
  UBaseType_t uxInitialCount );

(1) uxMaxCountは最大カウント数

(2) uxInitialCountはセマフォ生成時のカウント数の初期値

(3) 戻り値:NULLが返る時はセマフォの生成に失敗している。原因はHEAP領域の不足。それ以外なら成功している。

SemaphoreHandle_t xSemaphoreCreateCountingStatic(
  UBaseType_t uxMaxCount,  
  UBaseType_t uxInitialCount, 
  StaticSemaphore_t pxSempahoreBuffer );

(1) uxMaxCountは最大カウント数

(2) uxInitialCountはセマフォ生成時のカウント数の初期値

(3) pxSempahoreBufferはユーザーが事前に生成した変数StaticSemaphoreのポインター

(4) 戻り値:NULLが返る時はセマフォの生成に失敗している。原因はpxSempahoreBufferがNULLであった。それ以外なら成功している。



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
  • メディア: 単行本


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

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

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

カウンティングセマフォの2つの例

1つはカウンターの初期値が0の場合。
これは既に http://hamayan.blog.so-net.ne.jp/2018-02-26-3 の、発生したイベントの回数を取りこぼさない為に使った例。

1つはカウンターの初期値が0よりも大きい場合。
イナバの物置の例題の様に、資源の数の管理などに使用する。

以下の例は100の資源に対して同一優先度のタスクがそれぞれ資源を1つずつ取得、最後は共に50で終わる。
volatile SemaphoreHandle_t xSemaphore;

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

  xSemaphore = xSemaphoreCreateCounting( 100, 100 );

  /* configure take task1. */
  xTaskCreatePinnedToCore(
    takeTask1,  /* 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(
    takeTask2,  /* 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 */
  );

  vTaskDelete( NULL );  /* delete loopTask. */
}

void loop()
{
}

void takeTask1( void *execParam )
{
  int count = 1;
  while( 1 )
  {
    if( xSemaphoreTake( xSemaphore, 0 ) == pdTRUE )
    {
      Serial.print( "take semaphore 1 : " ); Serial.println( count++,DEC );
    }
    vTaskDelay( pdMS_TO_TICKS( 100 ) );
  }
}

void takeTask2( void *execParam )
{
  int count = 1;
  while( 1 )
  {
    if( xSemaphoreTake( xSemaphore, 0 ) == pdTRUE )
    {
      Serial.print( "take semaphore 2 : " ); Serial.println( count++,DEC );
    }
    vTaskDelay( pdMS_TO_TICKS( 100 ) );
  }
}

ESP32_countingSemaphore_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
  • メディア: 単行本


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

$
0
0
現在実用ガイドを読みながら編集中、、、書いて有る事を信用しない様に!
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
  • メディア: 単行本


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

$
0
0
現在実用ガイドを読みながら編集中、、、書いて有る事を信用しない様に!
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
  • メディア: 単行本



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

$
0
0
現在実用ガイドを読みながら編集中、、、書いて有る事を信用しない様に!
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
  • メディア: 単行本


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

$
0
0
現在実用ガイドを読みながら編集中、、、ある事ない事書いちょりまっす!
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
  • メディア: 単行本


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

$
0
0
現在実用ガイドを読みながら編集中、、、ある事ない事書いちょりまっす!
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
  • メディア: 単行本


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

$
0
0
現在実用ガイドを読みながら編集中、、、ある事ない事書いちょりまっす!
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
  • メディア: 単行本


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

$
0
0
現在実用ガイドを読みながら編集中、、、ある事ない事書いちょりまっす!
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
  • メディア: 単行本


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

$
0
0
現在実用ガイドを読みながら編集中、、、ある事ない事書いちょりまっす!
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
  • メディア: 単行本


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

$
0
0
現在実用ガイドを読みながら編集中、、、ある事ない事書いちょりまっす!
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
  • メディア: 単行本



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

$
0
0
現在実用ガイドを読みながら編集中、、、ある事ない事書いちょりまっす!
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
  • メディア: 単行本


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

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

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

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

〇 命名規則
● 変数名
変数名は、名前の頭にその型が付加されている。’c’はchar型だし、’s’はshort、’l’はlong、で’x’はportBASE_TYPE型、それに他の型(structures, task handles, queue handles, etc.)がある。

もし変数が符号無しであれば’u’を先頭に付加する。もし変数がポインター型であれば、先頭に’p’を付加する。なのでunsigned char型は”uc”、char *型であれば”pc”となる。

● 関数名
関数名は、名前の頭に戻り値の型と、それが書かれているファイルが付加されている。例えば、
  vTaskPrioritySet() returns a void and is defined within task.c.

  xQueueReceive() returns a variable of type portBASE_TYPE and is defined within queue.c.

  vSemaphoreCreateBinary() returns a void and is defined within semphr.h.

※スコープがprivateな関数は”prv”が付加される。

● 書式
1タブは4スペース

● マクロ名
ほとんどのマクロ名は大文字で書かれており、小文字はそれが定義されているファイルを示している。例えばprefixとマクロが定義されているファイルの関係性は、
  port (for example, portMAX_DELAY) → portable.h

  task (for example, taskENTER_CRITICAL()) → task.h 

  pd (for example, pdTRUE) → projdefs.h 

  config (for example, configUSE_PREEMPTION) → FreeRTOSConfig.h

  err (for example, errQUEUE_FULL) → projdefs.h

※セマフォはほとんどマクロで定義されているが、命名規則は関数のそれに従う。

共通マクロと定義
マクロ名と値の対応を以下に示す。
  pdTRUE → 1

  pdFALSE → 0

  pdPASS → 1

  pdFAIL → 0


● なんでこんなにキャストを多用するのか?
FreeRTOSのソースコードは様々なコンパイラでコンパイルされる事を想定しているため、コンパイラの依存性を排除する為にこの様な事になっている。


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
  • メディア: 単行本


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

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

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

タスクスタックの使用状況を動的に知る。
この辺り http://hamayan.blog.so-net.ne.jp/2018-02-18-1 でタスクの状態を知ることができず、困ったなぁ、、、と言う話の解決の1つ。

関数xTaskGetCurrentTaskHandleは、引数のタスクのスタックがあとどれ位残っているかをByte単位で答えてくれる。プロトタイプは以下になる。
  unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask );

(1) 引数xTaskは、スタックサイズの残りを知りたいタスクのハンドル。

(2) 戻り値:タスクスタックの内、使用されていないスタックサイズをByte単位で答える。

loopTaskの様にタスクハンドルを渡さずに生成したタスクでは、そのタスクのハンドルをカーネルから得る必要がある。関数xTaskGetCurrentTaskHandleは実行中のタスクのハンドルを答える。プロトタイプは以下になる。
  TaskHandle_t xTaskGetCurrentTaskHandle( void );

(1) 戻り値:実行中のタスクハンドル。


ここで http://hamayan.blog.so-net.ne.jp/2018-03-08-4 作成したデモプログラムの、それぞれのタスクのスタック使用状況を簡単にモニターしてみる。
xQueueHandle que;
xTaskHandle taskHandle[ 3 ];

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. */
    &taskHandle[ 0 ],   /* 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. */
    &taskHandle[ 1 ],   /* 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. */
    &taskHandle[ 2 ],   /* task handle pointer */
    1       /* core ID */
  );
}

void loop()
{
  unsigned portBASE_TYPE stzckSize;
  stzckSize = uxTaskGetStackHighWaterMark( taskHandle[ 0 ] );
  Serial.print( "task1 remain stack size = " ); Serial.println( stzckSize, DEC );

  stzckSize = uxTaskGetStackHighWaterMark( taskHandle[ 1 ] );
  Serial.print( "task2 remain stack size = " ); Serial.println( stzckSize, DEC );

  stzckSize = uxTaskGetStackHighWaterMark( taskHandle[ 2 ] );
  Serial.print( "task3 remain stack size = " ); Serial.println( stzckSize, DEC );

  TaskHandle_t loopTaskHandle = xTaskGetCurrentTaskHandle();
  stzckSize = uxTaskGetStackHighWaterMark( loopTaskHandle );
  Serial.print( "loopTask remain stack size = " ); Serial.println( stzckSize, DEC );

  vTaskDelay( pdMS_TO_TICKS( 1000 ) );
}

void gateKeeperTask( void *execParam )
{
  char buffer[ 128 ];
  while( 1 )
  {
    char *pvBuffer;
    xQueueReceive( que, (void *)&pvBuffer, portMAX_DELAY );
    strcpy( buffer, pvBuffer );
    Serial.print( buffer );
//    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_stackCheck_001.png

いやいやしかし、gateKeeperTask、task2、task3の3つのタスクには4kbyteのスタック、loopTaskには32kbyteのスタックを設定しているにも関わらず、この残り量のしょぼさは何だろう?
μiTRONであればtask2、task3辺りなら数十~数百Byte程度の設定で済みそうな気がするが。

※いやぁ、でも、目安程度しか使えない気がするなぁ、、、

※スタックサイズがでかすぎる点は、ここでも話題になっているなぁ、、、
https://esp32.com/viewtopic.php?f=2&t=900
あれぇ???ESP32のスタック単位はWORDではなくBYTEって書いてあるぞ!
スタックに使われている型のStackType_tは、portmacro.hの中で以下になっている、、、
#define portSTACK_TYPE  uint8_t

typedef portSTACK_TYPE  StackType_t;

あーん、うーん、なぜFreeRTOS公式と違う!

https://github.com/espressif/esp-idf/blob/master/components/freertos/readme_xtensa.txt
Then, you must also make sure to allocate extra space on the stack for each task that will use the C library reentrant functions. This extra space is to be allocated over and above the actual stack space required by the task itself. The define XT_STACK_EXTRA_CLIB specifies the amount of extra space to be added on to the stack to allow saving the context for the C library as well as the coprocessors if any. E.g. if your task requires 2000 bytes of stack space, you must allocate (2000 + XT_STACK_EXTRA_CLIB) bytes for the stack.


Interrupt Stack --------------- Beginning with port version 1.2, the port uses a separate interrupt stack for handling interrupts. Thus, it is no longer necessary for each task to reserve space on its stack to handle interrupts. The size of the interrupt stack is controlled by the parameter "configISR_STACK_SIZE" defined in FreeRTOSConfig.h. Define this carefully to match your system requirements.





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
  • メディア: 単行本


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

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

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

メモリ管理、、、1

カーネルは、タスクや、データキューや、セマフォが生成されるとき、動的にメモリ割り付けを行う。
標準のmalloc()やfree()のライブラリ関数は使う事ができるが、次に述べる問題を1つ以上抱える事になる。
1.小規模な組み込みシステムでは、常に有効とは限らない。

2.実装すると比較的大きなコード領域を取る。

3.スレッドセーフである事は稀である。

4.They are not deterministic. The amount of time taken to execute the functions will differ from
call to call. 、、、ちょっとうまく訳せん。決定論なんて初めて聞いたし、、、

5.メモリのフラグメンテーションに苦しむ可能性がある。

6.リンカーの設定が複雑になる可能性がある。

さまざまな組み込みシステムではRAMの割り当てとタイミングの要件が異なるため、1つのRAM
割り当てアルゴリズムは、アプリケーションのサブセットにしか適さない。したがって、FreeRTOS
(コアコードベースの一部ではなく)ポータブルレイヤの一部としてメモリ割り当てを処理する。この
個々のアプリケーションが適切なときに固有の実装を提供できるようにする。

カーネルがRAMを必要とするとき、malloc()を直接呼び出すのではなく、代わりにpvPortMalloc()を呼び出す。RAMが不要になったとき、free()を直接呼び出すのではなく、カーネルは代わりにvPortFree()を呼び出す。pvPortMalloc()はmalloc()と同じプロトタイプを持ち、vPortFree()はfree()と同じプロトタイプを持つ。

FreeRTOSには、pvPortMalloc()とvPortFree()の3つの実装例があり、この章で説明していく。 FreeRTOSのユーザーは例題の1つの実装を利用したり、独自に実装する事ができる。

この3つの例は、それぞれheap_1.c、heap_2.c、heap_3.cファイルで定義されている。これらはFreeRTOS\Source\Portable\MemMangディレクトリにある。(1)
FreeRTOSの非常に初期のバージョンで使用されていた、元のメモリプールやブロック割り当て方式は、ブロックとプールの次元を決定するのに努力や理解を必要とするため、削除された。

小規模な組み込みシステムでは、スケジューラーが起動する前に、タスクや、データキューや、セマフォが生成される。アプリケーションが真のリアルタイム機能をスタートし、実行する前に、メモリが動的に割り付けが行われるケースであり、一度割り付けられたメモリは決して開放されない。この意味は選ばれた割り付けの仕組みが、決定論やフラグメンテーションの様なより複雑な問題に対する考慮を必要としない。その代わりコードサイズや単純性の様な属性に対する考慮をするであろう。

※訳がつらい、、、うまく訳せない。

(1) https://github.com/jameswalmsley/FreeRTOS/tree/master/FreeRTOS/Source/portable/MemMang
なんて事でしょう!heap何とかが5つも有る!

※そもそもFreeRTOSの関数リストにはpvPortMalloc()とかvPortFree()は無い。μiTRONの固定長メモリプールとか、可変長メモリプールと同等の関数も存在しない。つまり、heap何とか.cのいずれかをユーザーが選んで、それを使え!と言う話なのであろう。



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
  • メディア: 単行本


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

$
0
0
ちょっと飽きたので、別ネタ

AquesTalk pico for ESP32の評価版を動かしただけ。
https://youtu.be/wouUZ7uchzk

詳細はここ
https://www.a-quest.com/products/aquestalk_pico_esp32.html

とりあえずマルチタスク化だけしたもの。※動作未確認確認済み
https://1drv.ms/u/s!AgxfaDqma1yrgQLu-FZfPKrUhyWa


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
  • メディア: 単行本


Viewing all 201 articles
Browse latest View live