ラズピコ wでのマルチコアの使い方(Arduino IDE)

ラズピコはマルチコアになっていて、MicroPythonでもマルチコアを使えるけれど、実行速度考えたらArdunino言語を使った方が高速だろうから、

https://ameblo.jp/pta55/entry-12798012318.html

で見つけたやり方を参考に、Lチカアプリをマルチコア使って他のコアにメッセージを送ってみた

ここでは固定値message_sをfifoで送信していますが、受信側で使われるglobal変数はloop1のfifo受信処理で書き換えられています(最初のブレークポイントではグローバル変数の初期値999ですが、その後のブレークでは1になります(fifoバッファーのデータ有無チェックしてるのに初期値になるのは変!

https://arduino-pico.readthedocs.io/en/latest/multicore.html

には、

int rp2040.fifo.available()

Returns the number of values available to read in this core’s FIFO.

とありますが

// constants won't change. Used here to set a pin number:
const int ledPin = LED_BUILTIN;  // the number of the LED pin

// Variables will change:
int ledState = LOW;  // ledState used to set the LED

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;  // will store last time LED was updated

// constants won't change:
const long interval = 500;  // interval at which to blink (milliseconds)

uint32_t message = 999;

void setup() {
  // set the digital pin as output:
  pinMode(ledPin, OUTPUT);
}

void setup1(){
}

void loop() {
  // here is where you'd put code that needs to be running all the time.

  // check to see if it's time to blink the LED; that is, if the difference
  // between the current time and last time you blinked the LED is bigger than
  // the interval at which you want to blink the LED.
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);

    // send message via FIFO
    uint32_t message_s = 0;
    rp2040.fifo.push(message_s);
  }
}

void loop1(){
  if (rp2040.fifo.available()>0){
    message = rp2040.fifo.pop();
    message += 1;
  }
}

マルチコアの使い方は、

① コアごとの動作はsetup/setup1、loop/loop1で指定する

② コアプロセス間の通信はfifo(rp2040.fifo)を使って行う、データ幅は4バイトで長さは8らしい(ソフト的なfifoなら任意に設定できるはずなのでこれはハードレジスタ)、受信するデータはglobal変数で定義しないといけない、送信側はlocal変数でもglobal変数でも大丈夫

デバッガで動かしてみると、マルチコア動作が確認できるのと、sync.hなるファイルが自動で生成されています、これはステップイン機能(停止したポイントの関数の中も追える)ですね

 

画面を見ればわかるようにコア二個分のデバッグ情報を見ることができます

 

admin

 

Raspberry piのDebug Probeを使う(Arduino IDE)

中身はラズピコのDebug Probeを使ってみる、もう一枚ラズピコでファームインストでも良いけど、かさばらないでスマートだから専用品の方が良い

Debug Probeの公式ページは、

https://www.raspberrypi.com/documentation/microcontrollers/debug-probe.html

<動作環境>

M1 MacBook Air/Arduino IDE 2.3.3

USBケーブルはswdの場合にはどちらもダウンロードはデバッガ経由なのでターゲットは電源供給だけで問題ないそうです、実際にはどちらからのダウンロードも使うから最初からデータ転送できるケーヌルにしとけば良いと思いますが、macからの見え方は、

Arduino IDEのToolsの設定は、デバッガーポートが認識されている状態では以下のような選択と見え方です

一点ハマったのは、デバッグ用のglobeボードの捺印のあるコネクタにswd信号はつながっていない事、wでない普通のボードはつながっているのかもしれないけど(ケーブルの色はオレンジ:SWCLK、黒:GND、黄色:SWDIOに対応してます)

でPCB上のviaにピン立てて受けにしてケーブル接続

swdインターフェースがアクティブならば、オレンジと黄色のledが点灯状態になって、Arduino IDEのデバッグも機能します

P.S. 2024/12/1

デバッガーのswdコネクタの半抜け注意

何故か急に繋がらないなと思ったら、コネクタが半抜け状態、この状態では最初にorange/yellow ledが点灯してすぐに消える(エラーになる)

奥まで押し込んだら回復、

<追記:2024/12/24>

デバッグできない(一度止めるとエラー出た)ので、何かと調べるとシリアルポートの設定をこのようにしないといけなかった

% ls /dev/cu.*
/dev/cu.Bluetooth-Incoming-Port	/dev/cu.usbmodem11102
/dev/cu.ESP32			/dev/cu.usbmodem11201

となっているから、デバッグ用にシリアルポートは正しく設定しましょう、このポートはmacのリブートなどで変わるんだろうね

 

admin

ラズピコ wでのLチカから始める

すでにもう1年以上経過しましたが、

ラズパイPico WのRust

のフォローで、embassyを使ったサンプルプログラムでLチカを動かしてみた、とはいっても、ほぼ

https://qiita.com/Azi/items/422c654bb476e0abf118

の手順に則っています、Cargo.tomlのライブラリ版数を最新にしたのと、ソースファイルは通常通りsrcディレクトリ直下に配置しています

全体的に感じるのは、Lチカだけなのに環境構築は作業項目多いし、コードの分量も結構あるということで、MicroPyhtonやArduino言語に比較すると事前の手間がかかるということ

ディレクトリ構成はこんな感じで、config.tomlのrunnerはデバッガ使わないときには修正必要です

今回はデバッグプローブ使うのでデフォルト(対象部分だけ抜き出し)のまま、

[target.'cfg(all(target_arch = "arm", target_os = "none"))']
runner = "probe-rs run --chip RP2040"

build.rsの役割は、

//! This build script copies the `memory.x` file from the crate root into
//! a directory where the linker can always find it at build time.
//! For many projects this is optional, as the linker always searches the
//! project root directory -- wherever `Cargo.toml` is. However, if you
//! are using a workspace or have a more complicated build setup, this
//! build script becomes required. Additionally, by requesting that
//! Cargo re-run the build script whenever `memory.x` is changed,
//! updating `memory.x` ensures a rebuild of the application with the
//! new memory settings.

memory.xはテキストファイルで、picoのメモリの使い方(マッピング)を指定するファイルに見えます

pico用のサンプルプログラムは、

https://github.com/embassy-rs/embassy/tree/main/examples/rp

に他の機能用のサンプルも存在するのでやってみるか

気づきは、① ビルドのオプションで–releaseを指定してもバイナリサイズは変わらないということ、組み込み用のバイナリだとそうなるのかもしれない、② targetディレクトリのサイズが巨大であること、今回の事例でも2.3GB程度の容量になっています

いずれにしろサンプルプログラム動かしてみるのはまだしも、実際にオリジナルのコードを書いたときにはデバッグ環境が必須だから、そこも当たり始めないと組み込みでは使い物にはならない

一番ポピュラーなのはラズパイ財団から出ているデバッグプローブを使うことだろう、今回はバイナリの転送にデバッグプローブ使ってるだけですが、

https://www.switch-science.com/products/8708

 

admin