﻿/* RTP_sp_3-4 */
/*
 *  タイマー割込み
 *
 *  OS: T-Kernel
 */

#include <tk/tkernel.h>  /* T-Kernel ヘッダ */
#include <tm/tmonitor.h> /* tm_printf() など */
#include "tmrb.h"        /* タイマーBのハードウェア定義 */
#include <trace/trace.h> /* タスクトレーサ */

/* オブジェクト ID 番号 */
LOCAL ID tidA;           /* タスク A の ID */

/* タイマーを設定する */
LOCAL void set_timer(void)
{
    TBxEN(4) = 0x80;     /* タイマーにクロック供給 */
    TBxRUN(4) = 0;       /* タイマー停止 */
    TBxRG1(4) = 18000;   /* 周波数 (18 MHz / 1) / 18000 = 1000 Hz */
    TBxFFCR(4) = 0x03;   /* パルス発生不要 */
    TBxMOD(4) = (1 << 6) | (1 << 3) | (1 << 0); /* 1: 1/1分周 */
    TBxIM(4)  = 0x05;    /* 割込みあり */
    TBxRUN(4) = 0x05;    /* タイマー動作 */
}

/* 割込みハンドラ A */
LOCAL void inthdrA(UINT intno)
{
    /* タスク A を起床する */
    tk_wup_tsk(tidA);

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

/* タスク A */
LOCAL void taskA(INT stacd, void *exinf)
{
    INT i;

    /* タイマーを設定する */
    set_timer();

    /* タイマー割込みを許可する */
    EnableInt(INTTB(4), INTPRI_GROUP(5, 0));

    for (i = 0; i < 1000; i++) {
        /* 割込みハンドラから起床されるまで待つ */
        tk_slp_tsk(TMO_FEVR);
    }

    /* タイマー割込みを禁止する */
    DisableInt(INTTB(4));

    /* メッセージを表示する */
    tm_printf((UB*)"interrupt %d times\n", i);

    tk_exd_tsk(); /* 自タスク終了・削除 */
}

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

    /* 割込みハンドラ A を定義する */
    di.intatr = TA_HLNG;     /* 割込みハンドラ属性 */
    di.inthdr = inthdrA;     /* 割込みハンドラアドレス */
    er = tk_def_int(INTTB(4), &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(INTTB(4), NULL);
e2: return er;
}
