Lチカ
セマフォ
Cortex-M4
Cortex-M0
PSoC6
PSoCDay 10

PSoC 6 のデュアルコアでLチカ (7)

これは、PSoC Advent Calendar 2017の10日目に突っ込まれた記事です。

前回までのあらすじ

前回の記事では、二つのCPUが競合するアプリケーションを作成し、セマフォを使う事によって解決を行いました。
今回は、気になったところをちょいと手直ししました。

Cortex-M0+側のプログラム

Cortex-M0+側のプログラムで変更したのは、以下の二点です。

main_cm0p.c
bool Int_Clear_flag = false;  /* 割り込みありフラグ */

/* Clear 割り込みの処理ルーチン */
void Int_Clear_isr(void) {
    /* フラグを立てる */
    Int_Clear_flag = true;
}

前回は、割り込み処理ルーチン(ISR)の中にセマフォの獲得・解放とGPIOの制御を直接入れていました。GPIOの処理は、決められた時間内に戻ってくる内容ですが、セマフォの操作は、セマフォが獲得可能になるまでの待ち時間が定まっていません。そのため、別のCPUがセマフォを取りっぱなしにするだけでこのプログラムはISRでブロックされ動作が停止してしまいます。

このような事態を防止するために、ISRの中にはフラグを立てるだけの処理を入れました。フラグは、メインループで参照されクリアされます。

main_cm0p.c
    for (;;) {
        if (Int_Clear_flag) {
            /* セマフォを獲得する */
            if (
                Cy_IPC_Sema_Set(SEMAPHORE_LED, false) == CY_IPC_SEMA_SUCCESS
            ) {
                /* GPIO 出力をクリア (Low) する。 */
                Cy_GPIO_Clr(Pin_LEDR_PORT, Pin_LEDR_NUM);
                /* セマフォを解放する */
                while (
                    Cy_IPC_Sema_Clear(SEMAPHORE_LED, false) != CY_IPC_SEMA_SUCCESS
                ) ;
                /* 使用済みフラグを折る */
                Int_Clear_flag = false;
            }
        }
    }

メインループの中には、if文が一つだけあります。フラグが立っていた場合に限り、if文の中身が実行されます。

if文の中にさらにif文があり、セマフォを獲得しています。これまでのプロジェクト例ではセマフォが獲得できるまでwhile文で待っていたのですが、今回は「獲得できなかったら次回に期待する」方針を取るべく、そのままメインループの中に抜けていきます。メインループの中に複数のタスクが存在していれば、セマフォが獲得できない場合には先に他のタスクに制御を渡すことができるので、全体の処理効率が上がることになります。

内側のif文の内部では、GPIOを操作した後、セマフォを解放しています。セマフォを解放するwhile文で待ち時間が発生するように見えますが、そもそも自分で確保したセマフォが解放できないというのは、他のタスクに横取りされたという事なので、もっと根の深いシステムエラーと考えられます。最後に使用済みのフラグを回収して一連の動作は終了です。

Cortex-M4側のプログラム

Cortex-M4側のプログラムも、同様の変更を行っています。

main_cm4.c
bool Int_Set_flag = false;  /* 割り込みありフラグ */

/* Set 割り込みの処理ルーチン */
void Int_Set_isr(void) {
    /* フラグを立てる */
    Int_Set_flag = true;
}
main_cm4.c
    for (;;) {
        if (Int_Set_flag) {
            /* セマフォを獲得する */
            if (
                Cy_IPC_Sema_Set(SEMAPHORE_LED, false) == CY_IPC_SEMA_SUCCESS
            ) {
                /* GPIO 出力をセット (High) する。 */
                Cy_GPIO_Set(Pin_LEDR_PORT, Pin_LEDR_NUM);
                /* セマフォを解放する */
                while (
                    Cy_IPC_Sema_Clear(SEMAPHORE_LED, false) != CY_IPC_SEMA_SUCCESS
                ) ;
                /* 使用済みフラグを折る */
                Int_Set_flag = false;
            }
        }
    }

こちらも、セマフォの処理を入れただけの変更です。

関連文献

AN215656 – PSoC 6 MCU Dual-Core CPU System Design
AN217666 - PSoC 6 MCU Interrupts
CE216795 - PSoC(R) 6 MCU Dual-Core Basics
PSoC 6 MCU: PSoC 63 with BLE Architecture Technical Reference Manual

関連記事

PSoC 6 のデュアルコアでLチカ (1)
PSoC 6 のデュアルコアでLチカ (2)
PSoC 6 のデュアルコアでLチカ (3)
PSoC 6 のデュアルコアでLチカ (4)
PSoC 6 のデュアルコアでLチカ (5)
PSoC 6 のデュアルコアでLチカ (6)