ITRON入門 アラームハンドラの概要と使い方

ITRON入門カリキュラム
この記事は約9分で読めます。

こんにちは、ナナです。

2つ目のタイムイベントハンドラについて紹介します。

アラームハンドラは周期ハンドラと同じタイムイベントハンドラの仲間です。周期ハンドラや割り込みについてはこちらの記事を参照してください。

本記事では次の疑問点を解消する内容となっています。

本記事で学習できること
  • アラームハンドラとは何か?
  • アラームハンドラの作り方と使い方とは?
  • アラームの時間延長機能とは?

では、アラームハンドラの仕組みを学んでいきましょう。

スポンサーリンク

ITRONのアラームハンドラの概要

ITRONのアラームハンドラの説明を見てみましょう。

ITRONのアラームハンドラ仕様

4.7.3 アラームハンドラ

アラームハンドラは、指定した時刻に起動されるタイムイベントハンドラである。

アラームハンドラ機能には、アラームハンドラを生成/削除する機能、アラームハンドラの動作を開始/停止する機能、アラームハンドラの状態を参照する機能が含まれる。

アラーム機能は、スマートフォンで目覚まし時計として使われている方は結構多いのではないでしょうか。

ITRONでその機能を提供してくれるのがアラームハンドラです。

アラームは目覚まし時計

使い方については次のように説明されています。

4.7.3 アラームハンドラ

アラームハンドラの生成直後にはアラームハンドラの起動時刻は設定されておらず、アラームハンドラの動作は停止している。

アラームハンドラの動作を開始するサービスコール(sta_alm)が呼び出されると、アラームハンドラの起動時刻を、サービスコールが呼び出された時刻から指定された相対時刻後に設定する。

周期ハンドラと異なり、生成直後から動作を開始することはできないとされています。そのためsta_almというアラーム開始用のサービスコールを別途呼び出す必要があります。

sta_almの呼出し後から指定時刻経過後にアラームハンドラが起動するとされていますね。アラームハンドラは周期性を持たないため開始要求に対して1度だけハンドラが起動されます。

アラームハンドラの生成(CRE_ALM)

周期ハンドラと同様にアラームハンドラはオブジェクトとして存在します。

CRE_ALMの仕様

周期オブジェクトは次の静的APIにて作り出すことができます。

CRE_ALM(ID almid, {ATR almatr, VP INT exinf, FP almhdr} );

引数パラメータを解説しておきます。

IDalmid生成するアラームハンドラのID。整数として一意のIDを割り付ける。
ATRalmatrアラームハンドラの属性。TA_HLNGを指定する。
VP_INTexinfアラームハンドラの引数に渡したい情報があれば指定。なければ0でよい。
FPalmhdrアラームハンドラが実行する関数ポインタ。関数名を書く。

周期ハンドラと異なりかなりシンプルな構成になっています。ATRにはTA_STAといった開始用のパラメータは使えません。

CRE_ALMによるアラームハンドラの生成定義

では、皆さんにアラームハンドラの定義をsystem.cfgに追加していただきましょう。前回の周期ハンドラはそのままで、アラームハンドラの定義を1つ追加しましょう。

追加するアラームハンドラ生成情報

  • IDは「ALMID_ALM1」を指定する。
  • 関数ポインタは「ALM1」を指定する。

system.cfg(一部抜粋)

//------------------------------------------------
//  周期ハンドラ定義
//------------------------------------------------
CRE_CYC(CYCID_CYC1,  {TA_HLNG|TA_STA, 0, CYC1, 5000, 0});

//------------------------------------------------
//  アラームハンドラ定義
//------------------------------------------------

system.cfg(一部抜粋)

//------------------------------------------------
//  アラームハンドラ定義
//------------------------------------------------
CRE_ALM(ALMID_ALM1,  {TA_HLNG, 0, ALM1});

アラームハンドラ関数の定義

アラームハンドラには周期ハンドラと同様にアラーム発生時に起動する関数を指定する必要があります。CRE_ALMで指定したALM1関数をmain.cに追加しましょう。

この関数では、アラーム起動時にグリーンLEDを点灯する処理を記述してください。

main.c(一部抜粋)

//------------------------------------------------
//  概  要:練習用アラームハンドラ関数
//------------------------------------------------
void ALM1(VP_INT exinf)
{

}

main.c(一部抜粋)

//------------------------------------------------
//  概  要:練習用アラームハンドラ関数
//------------------------------------------------
void ALM1(VP_INT exinf)
{
    Led_setLight(D_LED_KIND_GREEN, D_LED_LIGHT_ON);
}

アラームハンドラ関数はmain.hにプロトタイプ宣言を追加しておきましょう。

main.h(一部抜粋)

//------------------------------------------------
//  プロトタイプ宣言(Prototype declaration)
//------------------------------------------------
void MAIN(VP_INT exinf);
void Main_init(VP_INT exinf);
void TASK1(VP_INT exinf);
void TASK2(VP_INT exinf);
void CYC1(VP_INT exinf);
void ALM1(VP_INT exinf);

タスク関数の定義

アラームハンドラの開始要求を行うTASK1関数を作り直しましょう。

今回TASK1に与えるミッションは10ミリ秒周期でスイッチ状態をチェックし、スイッチがONならグリーンLEDを消灯し、アラームを5秒後にセットして開始します。

5秒後にアラームハンドラによりグリーンLEDが点灯します。

TASK1:ミッション内容
  1. スイッチがONかを確認する。
  2. スイッチがONならばグリーンLEDを消灯し、アラームを5秒後に起動する。

※10ミリ秒周期でこの処理を繰り返す。周期処理はdly_tskを利用すればよいものとする。

MAIN関数とTASK2関数は特に役割がないのでdly_tsk(1000);で眠っていただきましょう。皆さんはTASK1の中のミッションを作り出してください。

sta_almサービスコールの仕様

プログラムを作る前にsta_almの仕様を確認しておきましょう。

ER sta_alm(ID almid, RELTIM almtim);

引数として開始するべきアラームIDとアラーム時間(単位:ミリ秒)が設定できるようになっています。簡単に呼び出せそうですね。

それではmain.cのTAKS1関数にミッションをプログラミングしてみてください。

main.c(一部抜粋)

//------------------------------------------------
//  概  要:MAINタスク
//------------------------------------------------
void MAIN(VP_INT exinf)
{
    while(1)
    {
        dly_tsk(1000);
    }

    return;
}

//------------------------------------------------
//  概  要:練習用TASK1関数
//------------------------------------------------
void TASK1(VP_INT exinf)
{
    while(1)
    {

    }

    return;
}

//------------------------------------------------
//  概  要:練習用TASK2関数
//------------------------------------------------
void TASK2(VP_INT exinf)
{
    while(1)
    {
        dly_tsk(1000);
    }

    return;
}

main.c(一部抜粋)

//------------------------------------------------
//  概  要:練習用TASK1関数
//------------------------------------------------
void TASK1(VP_INT exinf)
{
    while(1)
    {
        if (Sw_getPressed() == D_SW_PRESSED_ON)
        {
            Led_setLight(D_LED_KIND_GREEN, D_LED_LIGHT_OFF);
            sta_alm(ALMID_ALM1, 5000);
        }

        dly_tsk(10);
    }

    return;
}

プログラムができたら動かしてみましょう。スイッチを押してから5秒後にグリーンLEDが点灯すれば正常にアラームハンドラが起動できています。

アラームのシーケンス図
スポンサーリンク

アラームハンドラの時間延長機能

先ほど作ったプログラムでスイッチを押すとグリーンLEDが5秒後に点灯しますね。

5秒経過する前に再度スイッチを押してみてください。そうするとスイッチを押し直した時間から5秒後に点灯するのがわかるはずです。

つまり、アラーム時間の起動が延長しています。

ITRONのsta_almの仕様は次のように説明されています。

sta_alm:アラームハンドラの動作開始

対象アラームハンドラに、すでに動作しているアラームハンドラが指定された場合には、以前の起動時刻の設定を解除し、新しい起動時刻を設定する。

この仕様に則り、アラーム発動前にスイッチが再度押されたため、再度TASK1によりsta_almの起動時刻設定がされたということになります。