#include <M5Unified.h>
// 1 にするとミューテックス有効、0 にすると無効
#define USE_MUTEX 1
SemaphoreHandle_t mutex;
// 複数タスクで共有する資源
int sharedCounter = 0;
void workerTask(void *pvParam) {
const char* taskName = (const char*)pvParam;
while (true) {
#if USE_MUTEX
xSemaphoreTake(mutex, portMAX_DELAY); // 共有資源をロック
#endif
// 共有カウンタを更新(ここも共有資源)
int myNo = ++sharedCounter;
// ここから下は「1つのまとまり」で表示したい処理
Serial.printf("\n[%s] ENTER #%d\n", taskName, myNo);
M5.Display.printf("\n[%s] ENTER #%d\n", taskName, myNo);
for (int i = 1; i <= 5; i++) {
Serial.printf("[%s] step %d/5 (counter=%d)\n", taskName, i, myNo);
M5.Display.printf("[%s] step %d/5 (counter=%d)\n", taskName, i, myNo);
// わざと少し待つことで、排他なしだと混ざりやすくする
vTaskDelay(pdMS_TO_TICKS(200));
}
Serial.printf("[%s] LEAVE #%d\n", taskName, myNo);
M5.Display.printf("[%s] LEAVE #%d\n", taskName, myNo);
#if USE_MUTEX
xSemaphoreGive(mutex); // ロック解除
#endif
// 次の順番まで少し待つ
vTaskDelay(pdMS_TO_TICKS(500));
}
}
void setup() {
auto cfg = M5.config();
cfg.serial_baudrate = 115200;
M5.begin(cfg);
M5.Display.setRotation(3);
M5.Display.setFont(&fonts::lgfxJapanGothic_16);
M5.Display.setTextScroll(true);
M5.Display.clear();
Serial.println("Mutex demo start");
M5.Display.println("Mutex demo start");
M5.Display.println("USE_MUTEX = 1 なら整然、0 なら混ざる");
#if USE_MUTEX
mutex = xSemaphoreCreateMutex();
if (mutex == NULL) {
Serial.println("mutex create failed");
M5.Display.println("mutex create failed");
while (1) { delay(1000); }
}
#endif
// 3つのタスクを起動
xTaskCreatePinnedToCore(workerTask, "TaskA", 4096, (void*)"TaskA", 1, NULL, 1);
xTaskCreatePinnedToCore(workerTask, "TaskB", 4096, (void*)"TaskB", 1, NULL, 1);
xTaskCreatePinnedToCore(workerTask, "TaskC", 4096, (void*)"TaskC", 1, NULL, 1);
}
void loop() {
// タスク側で動くので loop() は何もしない
vTaskDelay(pdMS_TO_TICKS(1000));
}