以下3つの環境で基本コードのみ実行してみます。
母艦にラズパイ4を使います。
Raspberry Pi Pico のCPU はデュアルコア(2 core)の構成になっています。
2つのコアを使った並列処理をやってみます。
Arduino IDE
ラズパイ4 + Arduino IDE でマルチコアのコードを実行してみます。
この環境でPicoをサポートするため、ボードはRaspberry Pi RP2040 Boards を使います。
Arduino IDE でPi Pico Wの開発用にEarle Philhower版を使う
baseになるコードは以下を参照します。
ファイル ー>スケッチ例ー>rp2040 ー> Multicore
特に何も宣言せずにマルチコアが使えます。
setupとloopの組み合わせを2個使います。setup(),loop() とsetup1(),loop1()。
RP2040 チップの2 つのコアは互いに独立して実行でき、周辺機器とメモリを互いに共有します。 Arduino コードは通常、コア 0 でのみ実行され、2 番目のコアは低電力状態でアイドル状態になります。
setup1() 関数とloop1() 関数をスケッチに追加すると、2 番目のコアを利用できます。 setup1() ルーチンまたはloop1() ルーチン内から呼び出されたものはすべて 2 番目のコアで実行されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
// Demonstrates a simple use of the setup1()/loop1() functions // for a multiprocessor run. // Will output something like, where C0 is running on core 0 and // C1 is on core 1, in parallel. // 11:23:07.507 -> C0: Blue leader standing by... // 11:23:07.507 -> C1: Red leader standing by... // 11:23:07.507 -> C1: Stay on target... // 11:23:08.008 -> C1: Stay on target... // 11:23:08.505 -> C0: Blue leader standing by... // 11:23:08.505 -> C1: Stay on target... // 11:23:09.007 -> C1: Stay on target... // 11:23:09.511 -> C0: Blue leader standing by... // 11:23:09.511 -> C1: Stay on target... // 11:23:10.015 -> C1: Stay on target... // Released to the public domain // The normal, core0 setup void setup() { Serial.begin(115200); delay(5000); } void loop() { Serial.printf("C0: Blue leader standing by...\n"); delay(1000); } // Running on core1 void setup1() { delay(5000); Serial.printf("C1: Red leader standing by...\n"); } void loop1() { Serial.printf("C1: Stay on target...\n"); delay(500); } |
Pico がシングル コア モードで実行されている場合、コア 0 には 8KB のスタック スペースがすべて利用可能です。 マルチコア setup1/loop1 を使用する場合、8KB はコアごとに 1 つずつ、2 つの 4K スタックに分割されます。 この場合、4K の制限を超えると、コア 0 のスタックがコア 1 のスタックを上書きする可能性があります。
コア 1 に別の 8K スタックを割り当てて、両方のコアで 8K スタックを利用できるようにするには、スケッチで次の変数を定義して true に設定するだけです。
bool core1_separate_stack = true;
他のボードの環境下(例:ArducamPico4ML)だと以下の様にmulticoreライブラリをincludeして使います。この場合はCore0からCore1を起動しています(pico-SDK のC/C++ のコードと同じ)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#include <stdio.h> #include "pico/stdlib.h" #include "pico/multicore.h" void core1_entry() { Serial.begin(115200); while (1){ Serial.println("core 1"); sleep_ms(1000); } } // Core 0 void setup() { multicore_launch_core1(core1_entry); // Start core 1 - Do this before any interrupt configuration } void loop() { Serial.println("core 0"); sleep_ms(100); } |
C/C ++
pico-SDK とpico-examples を使ってみます。
pico-examples には多くのサンプルコードが紹介されていて、何かを作りたいという場合のひな型を提供してくれます。
以前もやってます。Pi Pico W でWi-Fi 通信をやってみる(3)
が、あらためて書いてみます。
pico-sdkのインストール
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
sudo apt update sudo apt install -y build-essential cmake gcc-arm-none-eabi git curl mkdir ~/pico cd ~/pico git clone https://github.com/raspberrypi/pico-sdk cd pico-sdk git submodule update --init echo "export PICO_SDK_PATH=$HOME/pico/pico-sdk" >> ~/.bashrc . ~/.bashrc |
pico-examplesをクローンしてcmakeまでやっておき、makeは各サンプルで個別に実行することにします。
1 2 3 4 5 6 7 8 9 10 11 |
cd ~/pico git clone https://github.com/raspberrypi/pico-examples.git --branch master cd pico-examples mkdir build cd build cmake .. |
baseになるコードは以下を参照して使います。
pico-examples -> hello_multicore
マルチコア でHello Core 1 とCore 2 をやってみます。
Hello World サンプルではUSBのシリアルからそのままメッセージを取れるので便利で確認しやすいです。
マルチコアの基本コードはこんな感じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include "pico/multicore.h" void core1_entry() { // Core1で動作させる処理 ... } // main関数はCore0で動作する int main() { // Core1でcore1_entry関数を動作させる multicore_launch_core1(core1_entry); // 以下Core0で動作させる処理 ... } |
まず、Hello World のソースを改変します。
ソースの場所はココです。
~/pico/pico-examples/hello_world/usb/hello_usb.c
こういう感じに変更します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
/** * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. * * SPDX-License-Identifier: BSD-3-Clause */ #include <stdio.h> #include "pico/stdlib.h" #include "pico/multicore.h" void core1_entry() { // Core1 while (true) { printf("Hello, core1!\n"); sleep_ms(2000); } } int main() { //init USB port stdio_init_all(); multicore_launch_core1(core1_entry); while (true) { printf("Hello, core0!\n"); sleep_ms(1000); } } |
次に、CMakeLists.txtにライブラリを追加します。エディターで以下を編集します。
~/pico/pico-examples/hello_world/usb/CMakeLists.txt
下記の様にpico_multicoreを追加
target_link_libraries(hello_usb pico_stdlib pico_multicore)
buildに移動してmakeを実行します。
1 2 3 |
cd ~/pico/pico-examples/build/hello_world/usb make -j4 |
uf2ファイルが生成されます。
~/pico/pico-examples/build/hello_world/usb/hello_usb.uf2
PicoのBOOTSELボタンを押しながらUSBケーブルで母艦(ラズパイ4)に接続。
RPI-RP2フォルダーが開いたらuf2をドラッグ・ドロップ。
シリアルモニターを使って確認します。
Arduino IDE インストール済ならシリアルモニターも簡単に使えます。
Arduino IDE がインストールされていない場合は、minicomを使ってみます。シリアルポートをモニターできます。
1 2 3 |
sudo apt install minicom -y minicom -b 115200 -o -D /dev/ttyACM0 |
MicroPython
Pi Pico にMicroPython 実行用のファームウェアをインストールしておきます。
ラズパイ4ではプレインストールされているThonny をMicroPython のコーディング環境に使います。
baseになるコードは以下を参照して使います。
Multi Thread Coding on the Raspberry Pi Pico in Micropython
MicroPython の界隈ではマルチスレッドと呼んでいるようですが、Pico に限ってはThread = Core と考えていいようです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
import _thread """ Basic multi thread example """ from time import sleep import _thread def core0_thread(): counter = 0 while True: print("core0:" + str(counter) + "\n") counter += 2 sleep(1) def core1_thread(): counter = 1 while True: print("core1:" + str(counter)+ "\n") counter += 2 sleep(2) second_thread = _thread.start_new_thread(core1_thread, ()) core0_thread() |
Next
2つのコア間でコミュニケーションしたり同期処理したりする場合はセマフォやミューテックスなどを使う必要があります。
次回参照
Reference
Leave a Reply