LoginSignup
0
0

RP2040マルチコア

Posted at

RP2040のマルチ(デュアル)コア動作を確認する

秋月電子の「RP2040マイコンボードキット」、購入時に意識していなかったが、マルチ(デュアル)コアであることがわかったので、簡単な動作を確認してみた。

何をするか?

あるコアにて定期的にシリアル出力している状態で、別コアにてシリアル入力された内容をシリアル出力するもの。

準備

Arduino IDE環境:Macシリコンプロセッサ

最初はまともにBuildできなかったが、調べると下記内容が見つかる。

これに従い、下記を実行。

$ softwareupdate --install-rosetta

BOOTSELボタン

最初の1回だけ、BOOTSELボタンを押しながらケーブルを接続することが必要のようだ。下記サイトなど、多数情報が見つかる。

検証

マルチコア未使用

まず、マルチコアを使用せず、逐次処理を行ったケース。

ソースコード

#define INTERVAL 2000

void setup() {
  Serial.begin(9600);
  Serial.setTimeout(INTERVAL);
}

void loop() {
  char buf[16];
  memset(buf, 0, sizeof(buf));
  while (1) {
    if ((Serial.readBytesUntil('\n', buf, sizeof(buf))) > 0) {
      Serial.println(buf);
      memset(buf, 0, sizeof(buf));
    } else {
      Serial.println(millis());   
    }
  }
}
  • シリアル入力のタイムアウトを2000msに設定
  • シリアル入力があればそのまま出力
  • シリアル入力がなければ起動からの経過時間(ms)を出力

結果

09:54:42.193 -> 102004
09:54:44.207 -> 104004
09:54:46.185 -> 106004
09:54:50.142 -> =====
09:54:52.155 -> 111951
09:54:54.130 -> 113951
09:54:56.141 -> 115951
09:54:58.151 -> 117951
09:55:00.129 -> 119951
09:55:03.230 -> @@@@
09:55:05.241 -> 125031
09:55:07.220 -> 127031
  • "====="や"@@@@"はシリアル入力の折返し出力
  • シリアル入力がなければ、2000msごとに表示あり
  • シリアル入力があれば、その分の遅れ(時間経過)がわかる

至極まっとうな結果である。次に、これをデュアルコア化したソースコードで検証する。

デュアル(マルチ)コア使用

ソースコード

#define INTERVAL 2000
void setup() {
  Serial.begin(9600);
  Serial.setTimeout(INTERVAL);
}

void setup1() {
}

void loop() {
  Serial.println(millis());
  delay(INTERVAL);
}

void loop1() {
  char buf[16];
  memset(buf, 0, sizeof(buf));
  if ((Serial.readBytesUntil('\n', buf, sizeof(buf))) > 0) {
    Serial.println(buf);
  }
}

RP2040のArduino IDE環境では、デュアルコアソースコードを簡単に記述できる。ネット上に各種情報あり。

  • setup()およびloop()が1つ目のコア用処理
  • setup1()およびloop1()が2つ目のコア用処理
  • loop():定期的にシリアル出力(2000msごと)
  • loop1():シリアル入力を折り返し出力

結果

09:56:46.250 -> 36006
09:56:48.231 -> 38006
09:56:50.243 -> 40006
09:56:50.836 -> =====
09:56:52.253 -> 42006
09:56:54.231 -> 44006
09:56:56.239 -> 46007
09:56:58.250 -> 48007
09:56:59.469 -> @@@@
09:57:00.261 -> 50007
09:57:02.239 -> 52007
  • "====="や"@@@@"はシリアル入力の折返し出力
  • シリアル入力の有無に関わらず、2000msごとに起動からの経過時間(ms)を出力、つまり、デュアルコアが機能していることがわかる。

おまけ:FreeRTOS

上記マルチコア用ソースコードとほぼ同じ内容を、シングルコア上のFreeRTOSで実現してみる。

ソースコード

#include <FreeRTOS.h>
#include <task.h>

#define INTERVAL 2000
TaskHandle_t xKbd, xOnlyPrt;

void TaskKeyBoard(void *arg) {
  char buf[16];
  for (;;) {
    memset(buf, 0, sizeof(buf));
    if ((Serial.readBytesUntil('\n', buf, sizeof(buf))) > 0) {
      Serial.println(buf);
    }
    vTaskDelay(1);
  }
}

void TaskOnlyPrt(void *arg) {
  for (;;) {
    Serial.println(millis());
    vTaskDelay(INTERVAL);         // For task switch
  }
}

void setup() {
  Serial.begin(9600);
  Serial.setTimeout(INTERVAL);
  xTaskCreate(TaskKeyBoard, "TaskKeyBoard", 128, NULL, 1, &xKbd);
  xTaskCreate(TaskOnlyPrt, "TaskOnlyPrt", 128, NULL, 1, &xOnlyPrt);
  //vTaskStartScheduler(); # 存在してはいけない
}

void loop() {
}
  • TaskKeyBoard:キーボードから入力された内容を折返し出力するタスク
  • TaskOnlyPrt:2000msごとに起動からの経過時間(ms)を出力するタスク
  • RP2040では、vTaskStartScheduler()があると動作しないようだ

結果

20:39:23.914 -> 30019
20:39:25.922 -> 32020
20:39:27.703 -> =====
20:39:27.934 -> 34021
20:39:29.909 -> 36022
20:39:31.921 -> 38023
20:39:33.933 -> 40024
20:39:35.909 -> 42025
20:39:36.834 -> @@@@
20:39:37.920 -> 44026
20:39:39.932 -> 46027
20:39:41.943 -> 48028
  • "====="や"@@@@"はシリアル入力の折返し出力
  • キーボード入力タスクTaskKeyBoardのタスクスイッチ時間である1ms分(vTaskDelay(1))だけ、定期出力タスクTaskOnlyPrtの出力が遅れている(2001ms)
  • ただし、1ms以上の遅れが見えたこともある、このあたりはマイコンの精度の話だろう

EOF

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0