SSブログ

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

ESP32_AquesTalk_Test_02.png

別ネタ

ESP32もBlynkとAquesTalkで行こう!

AquesTalk-ESPでGoogle Home Miniに話掛けられるか?

https://youtu.be/klkQz3_6klg

www、エイプリールフールネタじゃないよ!

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でマルチタスクを行う為の、とりあえずここまで判った事 by freeRTOS 36タスク目 [ESP32]

ESP32_aquesTalk_speaker.jpg

別ネタ

ESP32もBlynkとAquesTalkで行こう!
なにかの資料
ESP32_aquesTalk_speaker.png

元々はPWM波形をアンプする回路なので、前段のフィルターのカットオフも10kHzくらいに設定。

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でマルチタスクを行う為の、とりあえずここまで判った事 by freeRTOS 35タスク目 [ESP32]

Screenshot_2018-03-29-00-31-54.png

別ネタ

ESP32もBlynkとAquesTalkで行こう!

Blynk、はじめに
https://www.blynk.cc/getting-started/

Blynk、サンプルコードジェネレーター
https://examples.blynk.cc/?board=ESP32&shield=ESP32%20WiFi&example=GettingStarted%2FVirtualPinWrite

ゆっくりしていってぬ!
※ソースコードに変更有。Blynkタスクの優先度を1に、タスクdelayをコメントアウト。
※Blynkのターミナルも追加して、任意の言葉を発声できる様に変更。

https://github.com/hamayanShowa-ele/ArduinoShare/tree/main/ESP32freeRTOS_TASK_ID_035

/*************************************************************
  Download latest Blynk library here:
    https://github.com/blynkkk/blynk-library/releases/latest

  Blynk is a platform with iOS and Android apps to control
  Arduino, Raspberry Pi and the likes over the Internet.
  You can easily build graphic interfaces for all your
  projects by simply dragging and dropping widgets.

    Downloads, docs, tutorials: http://www.blynk.cc
    Sketch generator:           http://examples.blynk.cc
    Blynk community:            http://community.blynk.cc
    Follow us:                  http://www.fb.com/blynkapp
                                http://twitter.com/blynk_app

  Blynk library is licensed under MIT license
  This example code is in public domain.

 *************************************************************

  You’ll need:
   - Blynk App (download from AppStore or Google Play)
   - ESP32 board
   - Decide how to connect to Blynk
     (USB, Ethernet, Wi-Fi, Bluetooth, ...)

  There is a bunch of great example sketches included to show you how to get
  started. Think of them as LEGO bricks  and combine them as you wish.
  For example, take the Ethernet Shield sketch and combine it with the
  Servo example, or choose a USB sketch and add a code from SendData
  example.
 *************************************************************/
// hello_aquestalk.ino - AquesTalk pico for ESP32 サンプルプログラム

/* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial

#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include "driver/i2s.h"
#include "aquestalk.h"

/*************************************************************************/
/*  instances and valiables.                                             */
/*************************************************************************/
IPAddress myIP; // self IP address
static unsigned long monitorPrintTim;
volatile xQueueHandle que;

/*************************************************************************/
/*  task prototype defines.                                              */
/*************************************************************************/
xTaskHandle taskHandle[ 2 ];
void blynkTask( void *execParam );
void aquesTalkTask( void *execParam );

/*************************************************************************/
/*  Wi-Fi defines.                                                       */
/*************************************************************************/
const char ssid[] = "ap ssid";
const char pass[] = "ap password";

/*************************************************************************/
/*  blynk defines.                                                       */
/*************************************************************************/
const char auth[] = "your blynk token";

/*************************************************************************/
/*  setup.                                                               */
/*************************************************************************/
void setup()
{
  // Debug console
  Serial.begin( 115200 );
  Serial.print( "FreeRTOS Test. " ); Serial.printf( "ESP32 Chip Revision: %d\r\n\r\n" , ESP.getChipRevision() );

  WiFi.disconnect();
  WiFi.begin( ssid, pass );
  while( WiFi.status() != WL_CONNECTED )
  {
     Serial.print( "." );
     vTaskDelay( pdMS_TO_TICKS( 100UL ) );
  }
  myIP = WiFi.localIP();
  Serial.print( "\r\nIP number assigned by DHCP is " );
  Serial.println( myIP );

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

  /* active the blynk demoTask. */
  xTaskCreatePinnedToCore(
    blynkTask, "",
    configMINIMAL_STACK_SIZE * 4,
    NULL, 1, &taskHandle[ 0 ], 1 );

  /* active the aquesTalk task. */
  xTaskCreatePinnedToCore(
    aquesTalkTask, "",
    (configMINIMAL_STACK_SIZE * 2) + (sizeof(uint32_t) * AQ_SIZE_WORKBUF),
    NULL, 2, &taskHandle[1], 1 );
}

/*************************************************************************/
/*  loop.                                                                */
/*************************************************************************/
void loop()
{
  /* stack monitor. */
  if( (millis() - monitorPrintTim) >= (10 * 1000UL) )
  {
    monitorPrintTim = millis();
    stackMonitor();
  }
}

/*************************************************************************/
/*  stack monitor                                                        */
/*************************************************************************/
static void reportStackSize( TaskHandle_t taskHdl, int count )
{
  unsigned portBASE_TYPE stzckSize = uxTaskGetStackHighWaterMark( taskHdl );
  String msg = "  Task" + String( count ) + " remains stack size = " + String( stzckSize );
  Serial.println( msg );
}

static void stackMonitor()
{
  int i;
  for( i = 0; i < sizeof(taskHandle) / sizeof(taskHandle[ 0 ]); i++ )
  {
    reportStackSize( taskHandle[ i ], i );
  }

  TaskHandle_t loopTaskHandle = xTaskGetCurrentTaskHandle();
  reportStackSize( loopTaskHandle, i );
  Serial.println();
}

/*************************************************************************/
/*  blynk task.                                                          */
/*************************************************************************/
void blynkTask( void *execParam )
{
  Blynk.config( auth );
  while( 1 )
  {
    Blynk.run();
//    vTaskDelay( pdMS_TO_TICKS( 10 ) );
  }
}

// Attach virtual serial terminal to Virtual Pin V4
WidgetTerminal terminal(V4);

/*************************************************************************/
/*  blynk virtual pin 0 function.                                        */
/*************************************************************************/
BLYNK_WRITE( V0 )
{ 
  static const char *talk = "konnnichiwa.";
  int value = param.asInt();
  if( value )
  {
    xQueueSendToBack( que, (const void *)&talk, 0 );
    terminal.println( talk );
    terminal.flush();
  }
}

/*************************************************************************/
/*  blynk virtual pin 1 function.                                        */
/*************************************************************************/
BLYNK_WRITE( V1 )
{ 
  static const char *talk = "korewa;te'_sutode_su.";
  int value = param.asInt();
  if( value )
  {
    xQueueSendToBack( que, (const void *)&talk, 0 );
    terminal.println( talk );
    terminal.flush();
  }
}

/*************************************************************************/
/*  blynk virtual pin 2 function.                                        */
/*************************************************************************/
BLYNK_WRITE( V2 )
{ 
  static const char *talk = "sa'nngatsu/<NUMK VAL=17 COUNTER=nichi> <NUMK VAL=12 COUNTER=ji>/<NUMK VAL=23 COUNTER=funn>.";
  int value = param.asInt();
  if( value )
  {
    xQueueSendToBack( que, (const void *)&talk, 0 );
    terminal.println( talk );
    terminal.flush();
  }
}

/*************************************************************************/
/*  blynk virtual pin 3 function.                                        */
/*************************************************************************/
BLYNK_WRITE( V3 )
{ 
  static const char *talk = "yukkuri_siteittene?";
  int value = param.asInt();
  if( value )
  {
    xQueueSendToBack( que, (const void *)&talk, 0 );
    terminal.println( talk );
    terminal.flush();
  }
}

/*************************************************************************/
/*  blynk virtual pin 4 function.                                        */
/*************************************************************************/
BLYNK_WRITE( V4 )
{ 
  char *talk = (char *)param.getBuffer();
  int length = param.getLength();
  xQueueSendToBack( que, (const void *)&talk, 0 );
  terminal.write( talk, length );
  terminal.println();
  terminal.flush();
}

/*************************************************************************/
/*  aquesTalkTask                                                        */
/*************************************************************************/
void aquesTalkTask( void *execParam )
{
  #define LEN_FRAME 32
  uint32_t workbuf [ AQ_SIZE_WORKBUF ];

  Serial.println( "Initialize AquesTalk" );
  int iret = CAqTkPicoF_Init(workbuf, LEN_FRAME, NULL);  // CAqTkPicoF_Init(workbuf, LEN_FRAME, "licence code");
  if(iret) Serial.println("ERR:CAqTkPicoF_Init");

  DAC_Create();
  Serial.println("D/A start");

  while( 1 )
  {
    char *talk;
    xQueueReceive( que, (void *)&talk, portMAX_DELAY );
    Play( talk );
  }
  DAC_Release();
  Serial.println("D/A stop");
  // vTaskDelete( NULL );  /* delete aquesTalkTask. if you want. */
}


// 一文の音声出力(同期型)
void Play( const char *koe )
{
  Serial.print( "Play:" );
  Serial.println( koe );

  int iret = CAqTkPicoF_SetKoe( (const uint8_t*)koe, 100, 0xffffU );
  if( iret )  Serial.println( "ERR:CAqTkPicoF_SetKoe" );

  for(;;)
  {
    int16_t wav[ LEN_FRAME ];
    uint16_t len;
    iret = CAqTkPicoF_SyntheFrame( wav, &len );
    if( iret ) break; // EOD
    
    DAC_Write( (int)len, wav );
  }
}

////////////////////////////////
//i2s configuration 
const int i2s_num = 0; // i2s port number
i2s_config_t i2s_config =
{
  .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN),
  .sample_rate = 24000,
  .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
  .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
  .communication_format = (i2s_comm_format_t)I2S_COMM_FORMAT_I2S_MSB,
  .intr_alloc_flags = 0,
  .dma_buf_count = 4,
  .dma_buf_len = 384,
  .use_apll = 0
};

void DAC_Create()
{
  AqResample_Reset();

  i2s_driver_install((i2s_port_t)i2s_num, &i2s_config, 0, NULL);
  i2s_set_pin((i2s_port_t)i2s_num, NULL);
}

void DAC_Release()
{
  i2s_driver_uninstall((i2s_port_t)i2s_num); //stop & destroy i2s driver 
}

// upsampling & write to I2S
int DAC_Write( int len, int16_t *wav )
{
  int i = 0;
  for( i = 0; i < len; i++ )
  {
    // upsampling x3
    int16_t wav3[ 3 ];
    AqResample_Conv( wav[ i ], wav3 );
    // write to I2S DMA buffer
    for(int k = 0; k < 3; k++ )
    {
      uint16_t sample[ 2 ];
      uint16_t us = ((uint16_t)wav3[ k ])^0x8000U;  // signed -> unsigned data 内蔵DA Only
      sample[ 0 ] = sample[ 1 ] = us; // mono -> stereo
      int iret = i2s_push_sample((i2s_port_t)i2s_num, (const char *)sample, 100);
      if( iret < 0 ) return iret; // -1:ESP_FAIL
      if( iret == 0 ) break;  //  0:TIMEOUT
    }
  }
  return i;
}



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でマルチタスクを行う為の、とりあえずここまで判った事 by freeRTOS 34タスク目 [ESP32]

別ネタ

ESP32もBlynkで行こう!

Blynk、はじめに
https://www.blynk.cc/getting-started/

Blynk、サンプルコードジェネレーター
https://examples.blynk.cc/?board=ESP32&shield=ESP32%20WiFi&example=GettingStarted%2FVirtualPinWrite

デジタル2番に接続されているLEDをON/OFFするだけ。

https://github.com/hamayanShowa-ele/ArduinoShare/tree/main/ESP32freeRTOS_TASK_ID_034

/*************************************************************
  Download latest Blynk library here:
    https://github.com/blynkkk/blynk-library/releases/latest

  Blynk is a platform with iOS and Android apps to control
  Arduino, Raspberry Pi and the likes over the Internet.
  You can easily build graphic interfaces for all your
  projects by simply dragging and dropping widgets.

    Downloads, docs, tutorials: http://www.blynk.cc
    Sketch generator:           http://examples.blynk.cc
    Blynk community:            http://community.blynk.cc
    Follow us:                  http://www.fb.com/blynkapp
                                http://twitter.com/blynk_app

  Blynk library is licensed under MIT license
  This example code is in public domain.

 *************************************************************

  You’ll need:
   - Blynk App (download from AppStore or Google Play)
   - ESP32 board
   - Decide how to connect to Blynk
     (USB, Ethernet, Wi-Fi, Bluetooth, ...)

  There is a bunch of great example sketches included to show you how to get
  started. Think of them as LEGO bricks  and combine them as you wish.
  For example, take the Ethernet Shield sketch and combine it with the
  Servo example, or choose a USB sketch and add a code from SendData
  example.
 *************************************************************/

/* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial

#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>

/*************************************************************************/
/*  instances and valiables.                                             */
/*************************************************************************/
IPAddress myIP; // self IP address
static unsigned long monitorPrintTim;

/*************************************************************************/
/*  task prototype defines.                                              */
/*************************************************************************/
xTaskHandle taskHandle[ 1 ];
void blynkTask( void *execParam );

/*************************************************************************/
/*  Wi-Fi defines.                                                       */
/*************************************************************************/
const char ssid[] = "your ap ssid";
const char pass[] = "your ap password";

/*************************************************************************/
/*  blynk defines.                                                       */
/*************************************************************************/
const char auth[] = "your auther token";

/*************************************************************************/
/*  setup.                                                               */
/*************************************************************************/
void setup()
{
  // Debug console
  Serial.begin( 115200 );
  Serial.print( "FreeRTOS Test. " ); Serial.printf( "ESP32 Chip Revision: %d\r\n\r\n" , ESP.getChipRevision() );

  WiFi.disconnect();
  WiFi.begin( ssid, pass );
  while( WiFi.status() != WL_CONNECTED )
  {
     Serial.print( "." );
     vTaskDelay( pdMS_TO_TICKS( 100UL ) );
  }
  myIP = WiFi.localIP();
  Serial.print( "\r\nIP number assigned by DHCP is " );
  Serial.println( myIP );

  /* active the blynk demoTask. */
  xTaskCreatePinnedToCore( blynkTask, "", configMINIMAL_STACK_SIZE * 4, NULL, 2, &taskHandle[ 0 ], 1 );
}

/*************************************************************************/
/*  loop.                                                                */
/*************************************************************************/
void loop()
{
  /* stack monitor. */
  if( (millis() - monitorPrintTim) >= (10 * 1000UL) )
  {
    monitorPrintTim = millis();
    stackMonitor();
  }
}

/*************************************************************************/
/*  stack monitor                                                        */
/*************************************************************************/
static void reportStackSize( TaskHandle_t taskHdl, int count )
{
  unsigned portBASE_TYPE stzckSize = uxTaskGetStackHighWaterMark( taskHdl );
  String msg = "  Task" + String( count ) + " remains stack size = " + String( stzckSize );
  Serial.println( msg );
}

static void stackMonitor()
{
  int i;
  for( i = 0; i < sizeof(taskHandle) / sizeof(taskHandle[ 0 ]); i++ )
  {
    reportStackSize( taskHandle[ i ], i );
  }

  TaskHandle_t loopTaskHandle = xTaskGetCurrentTaskHandle();
  reportStackSize( loopTaskHandle, i );
  Serial.println();
}

/*************************************************************************/
/*  blynk task.                                                          */
/*************************************************************************/
void blynkTask( void *execParam )
{
  Blynk.config( auth );
  //Blynk.config( auth, BLYNK_DEFAULT_DOMAIN, BLYNK_DEFAULT_PORT );
  //Blynk.begin( auth, ssid, pass );
  // You can also specify server:
  //Blynk.begin(auth, ssid, pass, "blynk-cloud.com", 8442);
  //Blynk.begin(auth, ssid, pass, IPAddress(192,168,1,100), 8442);
  pinMode( 2, OUTPUT );

  while( 1 )
  {
    Blynk.run();
    vTaskDelay( pdMS_TO_TICKS( 10 ) );
  }
}

/*************************************************************************/
/*  blynk virtual pin 0 function.                                        */
/*************************************************************************/
BLYNK_WRITE( V0 ) //
{ 
  int value = param.asInt();
  if( value == 0 ) digitalWrite( 2, LOW );
  else  digitalWrite( 2, HIGH );
}


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でマルチタスクを行う為の、とりあえずここまで判った事 by freeRTOS 33タスク目 [ESP32]

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

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



nice!(0)  コメント(0) 

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

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



nice!(0)  コメント(2) 

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

現在実用ガイドを読みながら編集中、、、ある事ない事書いちょりまっす!
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 作成したデモプログラムの、それぞれのタスクのスタック使用状況を簡単にモニターしてみる。

https://github.com/hamayanShowa-ele/ArduinoShare/tree/main/ESP32freeRTOS_TASK_ID_030

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.


※APIにxTaskGetHandle()やpcTaskGetName()は存在していない、、、


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でマルチタスクを行う為の、とりあえずここまで判った事 by freeRTOS 29タスク目 [ESP32]

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



nice!(0)  コメント(0) 

ESP32でマルチタスクを行う為の、とりあえずここまで判った事 by freeRTOS 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でマルチタスクを行う為の、とりあえずここまで判った事 by freeRTOS 27タスク目 [ESP32]

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

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

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

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

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

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

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

https://github.com/hamayanShowa-ele/ArduinoShare/tree/main/ESP32freeRTOS_TASK_ID_027

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) 

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。