M5StickCのFreeRTOSタスク情報取得を実現します


M5StickCのFreeRTOSタスク情報取得を実現します!


# 1 はじめに  
タスクがどんな状態か知りたくなり、
タスク情報取得のvtaskListをコールしたらサポート外だった。
気になったのでタスク情報を取得できる方法を探しました

(2021/7/16追記)Espressif32v3.2で確認した記事となります

# 2 準備  

## 2.1 ESP-IDFを準備します
https://qiita.com/Oldcastle/items/c6dfa2a3a09eed58a894
の3.2 esp-idfの準備を参照願います

## 2.2 ESP-IDF.CMDを開きます

## 2.3 ビルドできるプロジェクトへ移動します
cd \exmple\get-start\hello_world

## 2.3 プロジェクト設定メニューを開きます
idf.py menuconfig

## 2.4 freertosへ移動します

![freertos.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/cd517aa0-b6fd-f07d-b3af-62ce8682d807.gif)

## 2.5 vtasklistを有効にするためのオプションを設定します

![vtasklist.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/9980137f-2315-d889-4f90-e48067b34d6d.gif)


## 2.6 vTaskGetRunTimeStatsを有効にするためのオプションを設定します

![time.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1693886/f06ee3b2-c17e-dfad-a989-f6624c1c12f6.gif)


## 2.7 saveして終了します

## 2.8 ビルドします

~~~
idf.py build
~~~

## 2.9 ライブラリをコピーします

念のため、上書きする間にライブラリをバックアップしておくとよいかと思います

コピー元

esp-idf\examples\get-started\hello_world\build\esp-idf\freertos\libfreertos.a

コピー先

platformio\packages\framework-arduinoespressif32\tools\sdk\lib\libfreertos.a


準備は完了です  

# 3 関数説明

## 3.1 タスクの状態取得

関数名
void vTaskList( char *pcWriteBuffer );

説明
https://www.freertos.org/a00021.html#vTaskList

例：結果
~~~
vtasklist
loopTask        R       1       6200    12      1
IDLE0           R       0       1108    6       0
IDLE1           R       0       1092    7       1
Tmr Svc         B       1       1564    8       0
ipc0            B       24      572     2       0
esp_timer       B       22      4148    1       0
ipc1            B       24      540     3       1
~~~

| タスク名 | タスクの実行状態 | 現在のスタックサイズ | タスク番号 |
| - | - | - | - | - |
| xTaskCreateで設定した文字列 | ’B’(Blocked)  ‘R’(Ready)  ‘D’(Deleted:waiting clean up) ‘S’(Suspended, or Blocked without a timeout) | | |

## 3.2 タスクの実行時間  

関数名
void vTaskGetRunTimeStats( char *pcWriteBuffer );

説明
https://www.freertos.org/a00021.html#vTaskGetRunTimeStats

例：結果

~~~
vruntime
loopTask        159393          <1%
IDLE0           36000081                49%
IDLE1           35852602                49%
Tmr Svc         727             <1%
esp_timer       29              <1%
ipc1            21132           <1%
ipc0            2610            <1%
~~~

# 4 サンプル全コード

## 4.1 ヘッダコード

PRIVILEGED_FUNCTIONをコメントアウトします

変更するtask.hのフォルダ
platformio\packages\framework-arduinoespressif32\tools\sdk\include\freertos\freertos\task.h

~~~task.h
void vTaskList( char * pcWriteBuffer );// PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */

void vTaskGetRunTimeStats( char *pcWriteBuffer ); // PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
~~~

## 4.2 ソースコード  

Bボタンを押すたびにタスク情報とタスク時間を出力します  

~~~
#include <M5StickC.h>
#include <LovyanGFX.hpp>

static LGFX lcd;

// button gpio number
const uint8_t buttonA_GPIO = 37;
const uint8_t buttonB_GPIO = 39;

static void buttonA_isr(void) {
  M5.update();
  Serial.printf("%d A interrupt\n", millis() );
}
 
static void buttonB_isr(void) {
  M5.update();
  Serial.printf("%d B interrupt\n", millis() );
}

void setup() {
  char msg_buffer[512];

  // put your setup code here, to run once:
  Serial.begin(115200);
     
  // Initialize the M5Stack object
  M5.begin();
 
  lcd.init();                       // 初期化

  // START
  lcd.fillScreen(BLACK);
  lcd.setCursor(10, 10);
  lcd.setTextColor(WHITE);
  lcd.setTextSize(1);
  lcd.printf("START");

  attachInterrupt(digitalPinToInterrupt(buttonA_GPIO), buttonA_isr, CHANGE);
  attachInterrupt(digitalPinToInterrupt(buttonB_GPIO), buttonB_isr, CHANGE);

  vTaskList(msg_buffer);

  Serial.println("vtasklist");
  Serial.printf("%s", msg_buffer);

}

void loop() {
  // put your main code here, to run repeatedly:

  if(M5.BtnB.wasPressed() != 0 ) {
    char msg_buffer[512];
    Serial.printf("%d was pressB\n", millis() );
    lcd.println("was pressB");
    
    vTaskList(msg_buffer);

    Serial.println("vtasklist");
    Serial.printf("%s", msg_buffer);

    Serial.println("vruntime");
    vTaskGetRunTimeStats(msg_buffer);
    Serial.printf("%s", msg_buffer);

    delay(10);
  }

  delay(1);
}
~~~