Raspberry Pi Pico おぼえがき
03マルチコア使用と排他制御
Raspberry Pi Pico C/C++ SDKでの開発おぼえがきです。
RP2040(Picoのチップ)、RP2350(Pico2のチップ)はデュアルコアです。
せっかくなので2つのコアを使って同時に別々の処理を動かしてみます。
1. マルチコアを使う
multicore.cpp
#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/multicore.h" // マルチコアを使うために必要
// core1(二つ目のコア)の処理
void core1_process(){ // この関数名は任意
while(true){
printf("[core 1]\n");
}
}
// core0(デフォルトコア)の処理
int main(){
stdio_init_all();
multicore_launch_core1(core1_process); // core1でcore1_process()を開始
while(true){
printf("[core 0]\n");
}
return 0;
}
出力結果(コンソール)
[core 1]
[core 0]
[core 1]
[core 0]
(続く)
猛烈なスピードで表示され続けているはずです。
これでまずは複数のコアを使うことができました。
※ core1の処理はcore0側から呼ぶ必要があります。
※ core0のmain()が終了するとcore1の処理も停止します。
2. Mutexを使った排他処理
全く関係のない別の処理を複数コアにやらせる場合は以上でOKですが、同一のGPIOやグローバル変数に複数コアからアクセスする場合には排他処理が必要となります。
方法はいくつかありますがとりあえず単純そうなMutexを試してみました。
mutex.cpp
#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/multicore.h"
int8_t g_num = 0; // 複数コアからアクセスされるグローバル変数
mutex_t mutex1; // ミューテックスの変数を宣言
// core1(二つ目のコア)の処理
void core1_process(){
while(true){
mutex_enter_blocking(&mutex1); // ミューテックス取得
g_num = 101;
printf("[core 1]: %u\n", g_num);
sleep_ms(5000);
mutex_exit(&mutex1); // ミューテックス解放
}
}
// core0(デフォルトコア)の処理
int main(){
stdio_init_all();
mutex_init(&mutex1); // ミューテックス初期化
multicore_launch_core1(core1_process); // core1の処理を開始
while(true){
mutex_enter_blocking(&mutex1); // ミューテックス取得
g_num = 100;
printf("[core 0]: %u\n", g_num);
sleep_ms(5000);
mutex_exit(&mutex1); // ミューテックス解放
}
return 0;
}
緑色で強調されている箇所が排他制御に関わる部分
出力結果(コンソール)
[core 1]: 101
[core 0]: 100
[core 1]: 101
[core 0]: 100
(続く)
5秒ごとに各行が表示される
mutex_enter_blocking(&mutex1)でmutex取得を試みます。別コアが取得中だった場合は解放を待ってから取得されます。
本来はmutexを握っている時間を出来るだけ短くするため途中でsleep_msを入れたりはしませんが、mutexの動作を目で見るために入れています。
また、自分のコアがmutexを握った状態で再取得を試みた場合のことも考えた時には
mutex_try_enter(&mutex1, &owner)などでmutexのオーナーをチェックする必要がありますが、ここではその可能性がない&単純化のため省略しています。
常に高速で信号を送り続ける必要があるLEDマトリクス表示器やグラフィックLCDのような機器を扱う場合には、マルチコアが扱えるとかなり楽になります。
3. 参考資料(外部リンク)