SNSへはこちら

Raspberry Pi Picoでマルチコアを触ってみる

またラズピコの記事です。最近はラズピコばっかりいじっています。

今回は何故かみんなやっていないマルチコアプログラミングを楽しんでいきます。

RP2040のCPUコア

自分は結構注目していたことですが、このマイコンには ARM Cortex-M0+ CPU が2つ積んであります。データシート上での図では、プロセッササブシステムは以下のようになっています。

GPIO のピン出力が SIO という名前で独立していることが既に驚きですが(ペリフェラルではない)、Core0 と Core1 という2つの CPU コアがあります
これはどちらも Cortex-M0+ のものであり、AHB バスに独立してアクセスすることが出来ます(ただしデータの衝突には注意。mutex(sdk 内に同梱されている)を使う必要があるかも)。

また、コア同士はイベント(Event)を通して同期できます。これは pico-sdk の fifo と名前のついたマルチコアライブラリに対応します。このイベントはブロッキング処理を伴う 1word のデータ送受信です。ちょっとクセありますかね(まあシェル芸等で行われるパイプのようなものだと考えればいいでしょう)。実のところマルチスレッドプログラミングをやったことが無いので分かりませんが。

ユーザープログラムはデフォルトで Core0 で動きます。ユーザーがライブラリを用いて Core1 で動かす関数を指定すると、Core1 はその関数をエントリポイントとして動作し始めます。

Lチカの動作例

毎回恒例Lチカですが、Core0 でLEDをチカチカさせる回数を UART で入力し、その値を Event(FIFO) として Core1 に渡すプログラムを作りました。

注意点として、マルチコアライブラリは通常の pico-stdlib に入っていないので、CMakeLists.txt に追記する必要があります。また、printf を USB シリアルに出力する記述もお忘れなく。

target_link_libraries(${proj_name} pico_stdlib pico_multicore)

# enable usb output, disable uart output
pico_enable_stdio_usb(${proj_name} 1)
pico_enable_stdio_uart(${proj_name} 0)

ではそのプログラムを以下に示します。

#include <stdio.h>
#include <stdlib.h>
#include "pico/stdlib.h"
#include "pico/multicore.h"

void core1_main(void) {
    gpio_init(25);
    gpio_set_dir(25, true);
    gpio_put(25, false);

    while(1) {
        const uint32_t loop = multicore_fifo_pop_blocking();

        for(int i = 0; i < loop; i++) {
            gpio_put(25, true);
            sleep_ms(100);
            gpio_put(25, false);
            sleep_ms(100);
        }
    }
}

int main() {
    stdio_init_all();

    multicore_launch_core1(core1_main);
    while(1) {
        char buf[10];
        printf(">>> ");
        uint32_t blink_times;
        scanf("%9ld", &blink_times);

        printf("LED will blink %ld times.\n", blink_times);
        multicore_fifo_push_blocking(blink_times);
    }
    return 0;
}

できればローカルエコーのある端末で実行することが望ましいですが、別になくても出来ます。
>>> のプロンプト表示時に好きな数字を打つと、その回数だけ LED がピコピコします。

ここでポイントですが、printf とLEDチカチカは別コア・別スレッドで行っているため、先に実行しているLEDチカチカが終わっていなくとも、データを入力することが可能です。データはブロッキング処理で相手のコアに送信しているため、流石に3重でデータを打ち込むことは出来ませんがね。

ということで、Raspberry Pi Pico(RP2040 マイコン) を用いたマルチスレッドプログラミングの例を提示しました。
流石 SDK と言わんばかりの簡単さで、割りとすぐに実装が完了しました。

今回は直接コアにデータを送るだけでしたが、実際に多くのデータを送るとなると上のようには行きません。グローバル変数を用いる方法にシフトするはずです。するとイベントとして送るデータは取り扱うデータそのものではなく、何らかのシグナルとして意味を成す値となるでしょう。
その際にはデータの Read, Modify, Write のシークエンス中で衝突が起こらないよう、mutex を使うことが必要です。mutex は pico-sdk のリファレンスマニュアルに載っていますので、ぜひそちらもチェックしてみてください。

...何度も言いますが、現時点でネットに何でこのマルチコア構成をやっている記事が全然無いんだ??

コメント

  1. jujurou より:

    マルチコアネタ。こっちの方が記事が古いから探せてないだけではないかな?
    https://homemadegarbage.com/pipico07

    • shima-529 より:

      ありましたね。情報ありがとうございます。
      日本語記事で見つけたのは初でした。検索スキルが無いだけですねw