前園ソフトウェア開発ロゴ

前園ソフトウェア開発

記号 タイトル 作成日
0009 RaspberryPi-Pico + freeRTOSで遊んでみる
「LCDを利用して出力する②改」
2026/01/01

先に掲載のコードをイベントキューを利用した一般的なプロセス間通信で実装してみた。

main.cpp以外に変更点はないので、main.cpp以外は先の掲載分をご参考ください。

挙動も同様なので、記載を割愛する。

【改良版main.cpp】main (CPP 4.26KB)

/*既存のsample04と挙動が同じだが
 * プロセス間制御を適用してイベントキューにタッチイベントをエンキューして、それを定期的にデキューすることで、画面遷移するように改良した。
 *
 */


#include <stdio.h>
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "pico/stdlib.h"
#include "LCD_driver.h"

// 【IPC仕様】プロセス間通信用キュー
QueueHandle_t xTouchQueue = NULL;
// 【排他仕様】SPIバス保護用セマフォ(Mutexの代わりに使用)
SemaphoreHandle_t xDisplaySemaphore = NULL;

// ---------------------------------------------------------
// Task 1: [P1] スキャナプロセス (20ms周期)
// ---------------------------------------------------------
void vScanTask(void *pvParameters) {
    vTaskDelay(pdMS_TO_TICKS(2000));
    printf("[T1] P1: Input Scanner Online\n");

    int event_signal = 1;
    bool last_state = false;

    while (true) {
        bool current_state = false;

        // セマフォでバスを確保
        if (xDisplaySemaphore != NULL && xSemaphoreTake(xDisplaySemaphore, portMAX_DELAY) == pdTRUE) {
            current_state = is_touched();
            xSemaphoreGive(xDisplaySemaphore);
        }

        // 変化点検知
        if (current_state && !last_state) {
            xQueueSend(xTouchQueue, &event_signal, 0);
        }
        last_state = current_state;

        vTaskDelay(pdMS_TO_TICKS(20));
    }
}

// ---------------------------------------------------------
// Task 2: [P2]制御 & [P4]TFT描画 (1000ms周期)
// ---------------------------------------------------------
void vDisplayTask(void *pvParameters) {
    printf("[T2] Initializing TFT...\n");

    LCD_Driver lcd;

    // 初期化をセマフォで保護
    if (xDisplaySemaphore != NULL && xSemaphoreTake(xDisplaySemaphore, portMAX_DELAY) == pdTRUE) {
        lcd.init();
        lcd.drawHSBBackground();
        xSemaphoreGive(xDisplaySemaphore);
        printf("[T2] TFT Initialization Complete\n");
    }

    int total_count = 0;
    int received_val;

    printf("[T2] P2&P4: Display Controller Online\n");

    while (true) {
        vTaskDelay(pdMS_TO_TICKS(1000));

        bool has_event = false;
        while (xQueueReceive(xTouchQueue, &received_val, 0) == pdPASS) {
            total_count++;
            has_event = true;
        }

        if (has_event) {
            printf("[P2] Control: Event Detected. Total Count = %d\n", total_count);

            // 描画処理をセマフォで保護
            if (xDisplaySemaphore != NULL && xSemaphoreTake(xDisplaySemaphore, portMAX_DELAY) == pdTRUE) {
                update_hue_on_tap();
                lcd.drawHSBBackground();
                xSemaphoreGive(xDisplaySemaphore);
                printf("[P4] TFT Draw Update Done\n");
            }
        }
    }
}

// ---------------------------------------------------------
// Main
// ---------------------------------------------------------
int main() {
    stdio_init_all();
    sleep_ms(2000);
    printf("\n====================================\n");
    printf("   IPC Specification: Semaphore Model \n");
    printf("====================================\n");

    // 【IPC仕様】キュー作成
    xTouchQueue = xQueueCreate(100, sizeof(int));

    // 【修正】xSemaphoreCreateMutex がエラーになるため、
    // バイナリセマフォを作成し、即座に Give して「空き」状態にする
    xDisplaySemaphore = xSemaphoreCreateBinary();
    if (xDisplaySemaphore != NULL) {
        xSemaphoreGive(xDisplaySemaphore);
    }

    if (xTouchQueue != NULL && xDisplaySemaphore != NULL) {
        xTaskCreate(vDisplayTask, "Display", 4096, NULL, 1, NULL);
        xTaskCreate(vScanTask, "Scanner", 1024, NULL, 2, NULL);

        printf("[Main] Starting Scheduler...\n");
        vTaskStartScheduler();
    }

    while(1) {
        tight_loop_contents();
    }
}

// Hooks
extern "C" {
    void vApplicationIdleHook(void) {}
    void vApplicationTickHook(void) {}
    void vApplicationMallocFailedHook(void) {
        printf("[CRITICAL] Malloc Failed!\n");
        for(;;);
    }
    void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) {
        printf("[CRITICAL] Stack Overflow in: %s\n", pcTaskName);
        for(;;);
    }
}