﻿/* RTP_sp_6-4 */
/*
 *  セマフォによる同期
 *
 *  OS: T-Kernel
 *
 */

#include <tk/tkernel.h>  /* T-Kernel ヘッダ */
#include <tm/tmonitor.h> /* tm_printf() など */
#include <tk/sysdef.h>   /* ハードウェア定義 */

/* オブジェクト ID 番号 */
LOCAL ID semid; /* セマフォの ID */
LOCAL ID tidA;  /* タスク A の ID */

/* 割込みハンドラ A */
LOCAL void inthdrA(UINT intno)
{
    /* セマフォに資源返却する */
    tk_sig_sem(semid, 1);

    /* 割込みをクリアする */
    CLKCTRL_CGICRCG = intno;
    ClearInt(intno);
}

/* タスク A */
LOCAL void taskA(INT stacd, void *exinf)
{
    /* SW3 (PA3) から入力するように設定する */
    PIO_CR(A) &= ~(1 << 3);
    PIO_IE(A) |= (1 << 3);

    /* SW3 (INT3) の割込みのモード設定を行う : 立ち下がりエッジ(1→0) */
    CLKCTRL_CGIMCGA = (CLKCTRL_CGIMCGA & ~(7 << (8 * 3 + 4))) | (2 << (8 * 3 + 4));

    /* SW3 (INT3) の割込みを許可する */
    CLKCTRL_CGIMCGA |= (1 << (8 * 3));
    ClearInt(3);
    EnableInt(3, INTPRI_GROUP(5, 0));

    for (;;) {
        /* セマフォから資源獲得待ち */
        tk_wai_sem(semid, 1, TMO_FEVR);

        /* メッセージを表示する */
        tm_printf((UB*)"SW3: 1->0\n");
    }

    /* このタスクは終了しない */
}

/* 初期化処理 */
EXPORT INT usermain(void)
{
    ER     er;
    T_CSEM cs;
    T_DINT di;
    T_CTSK ct;

    /* セマフォを生成する */
    cs.exinf = 0;                    /* 拡張情報 */
    cs.sematr = TA_TFIFO | TA_FIRST; /* セマフォ属性 */
    cs.isemcnt = 0;                  /* セマフォの初期値 */
    cs.maxsem = 10;                  /* セマフォの最大値 */
    semid = tk_cre_sem(&cs);
    if (semid < E_OK) { er = semid; goto e3; }

    /* 割込みハンドラ A を定義する */
    di.intatr = TA_HLNG;            /* 割込みハンドラ属性 */
    di.inthdr = inthdrA;            /* 割込みハンドラアドレス */
    er = tk_def_int(3, &di);        /* 割込みハンドラ A を定義 */
    if (er < E_OK) goto e2;

    /* タスク A を生成する */
    ct.exinf = (void*)('t' | 's' << 8 | 'k' << 16 | 'A' << 24); /* 拡張情報 */
    ct.tskatr = TA_HLNG | TA_RNG0;  /* タスク属性 */
    ct.task = taskA;                /* タスク起動アドレス */
    ct.itskpri = 1;                 /* タスク起動時優先度 */
    ct.stksz = 1024;                /* スタックサイズ */
    tidA = tk_cre_tsk(&ct);         /* タスク A を生成 */
    if (tidA < E_OK) { er = tidA; goto e1; } /* タスク生成失敗時 */

    tk_sta_tsk(tidA, 0);            /* タスク A を起動 */

    return E_OK;

e1: tk_def_int(3, NULL);
e2: tk_del_sem(semid);
e3: return er;
}
