この章の目次にもどる
前頁:第3章 全般にもどる
次頁:第6章 I-right/V独自の機能にすすむ

第5章 ITRON拡張機能

5.1 拡張機能一覧

新規追加システムコール


        ER vend_exc(void);
        ER vdis_fex(ID tskid, UINT fexcmsk);
        ER vena_fex(ID tskid, UINT fexcmsk);
        ER vdef_fex(ID tskid, FP fexchdr);
        ER vras_fex(ID tskid, INT fexcode);
        ER vdef_brk(FN s_fncd, FP brkhdr);

        ER vdis_wai(ID tskid, UINT waitptn, UINT *tskwait);
        ER vena_wai(ID tskid);

        ER vchg_slt(ID tskid, INT slicetime);

        ER vinf_tsk(T_INFTSK *pk_inftsk, ID tskid, BOOL clr);

        ER vset_tev(ID tskid, INT tskevt);
        ER vwai_tev(INT tevmsk, TMO tmout);

        ER veif_tsk(VP *oldinf, VP newinf, ID tskid);

        ER vref_svc(T_RSVC* pk_rsvc, FN s_fncd);

        ER vpget_bks(VP *p_bks, VP *p_grp, INT nblk, UINT atr);
        ER vrel_bks(VP *p_grp, VP bks);
        ER vatr_bks(UINT *p_atr, VP bks);
        ER vref_bks(T_RBKS *pk_rbks);

        ER vset_pow( UINT pwmode );

        ER vget_otm(SYSTIME *pk_tim);

構造体/定義の追加/変更

        typedef struct t_rtsk {
                VP      exinf;          /* 拡張情報                     */
                PRI     tskpri;         /* 現在の優先度                 */
                UINT    tskstat;        /* タスク状態                   */
                UINT    tskwait;        /* 待ち要因                     */
                ID      wid;            /* 待ちオブジェクトID           */
                INT     wupcnt;         /* 起床要求キューイング数       */
                INT     suscnt;         /* SUSPEND要求ネスト数          */
    →          UINT    waitmask;       /* 禁止待ち要因                 */
    →          INT     slicetime;      /* スライスタイム               */
    →          UINT    fexcmsk;        /* 強制例外ビットマスク         */
    →          UINT    tskevent;       /* タスクイベント発生状態       */
        } T_RTSK;

    →          TTW_EV1 0x01000000      /* タスクイベント#1待ち         */
    →          TTW_EV2 0x02000000      /* タスクイベント#2待ち         */
    →          TTW_EV3 0x04000000      /* タスクイベント#3待ち         */
    →          TTW_EV4 0x08000000      /* タスクイベント#4待ち         */
    →          TTW_EV5 0x10000000      /* タスクイベント#5待ち         */
    →          TTW_EV6 0x20000000      /* タスクイベント#6待ち         */
    →          TTW_EV7 0x40000000      /* タスクイベント#7待ち         */
    →          TTW_EV8 0x80000000      /* タスクイベント#8待ち         */

    →  typedef struct t_inftsk {
    →          UINT    stime;          /* システムタイムカウンタ       */
    →          UINT    utime;          /* ユーザタイムカウンタ         */
    →  } T_INFTSK;

        typedef struct t_rsem {
                VP      exinf;          /* 拡張情報                     */
                BOOL_ID wtsk;           /* 待ちタスクの有無             */
                INT     semcnt;         /* 現在のセマフォカウント値     */
    →          ID      gtsk;           /* ロック型セマフォ獲得タスクID */
        } T_RSEM;

    →          TA_LOCKSEM 0x00010000   /* ロック型セマフォを指定       */

        typedef struct t_rsys {
                INT     sysstat;        /* システム状態                 */
                ID      runtskid;       /* 実行状態にあるタスクの ID    */
                ID      schedtskid;     /* 実行状態にすべきタスクのID   */
    →          INT     cpuload;        /* システムのロード(0-10000)    */
        } T_RSYS;

    →  typedef struct t_rcfg {
    →      INT     timer_period;         /* タイマー割込間隔 (ms) */
    →      INT     default_slice_time;   /* デフォルト連続実行時間 (ms) */
    →  #ifdef i386
    →      UW      cpu_type;             /* CPU タイプ */
    →  #endif
    →  } T_RCFG;

    →  typedef struct t_rsvc {
    →          ATR     svcatr;         /* 拡張SVCハンドラ属性 */
    →  #ifdef V810
    →          VP      textp;          /* テキスト領域先頭アドレス */
    →          VP      globp;          /* グローバル領域先頭アドレス */
    →  #endif
    →  } T_RSVC;

    →  typedef struct t_rbks {
    →          INT     blksz;          /* ブロックサイズ (バイト数) */
    →          INT     total;          /* 全ブロック数 */
    →          INT     free;           /* 残りブロック数 */
    →  } T_RBKS;

    →  #define TPW_DOSUSPEND   1       /* サスペンド状態へ移行 */
    →  #define TPW_DISLOWPOW   2       /* 低消費電力モード切替禁止 */
    →  #define TPW_ENALOWPOW   3       /* 低消費電力モード切替許可 */

エラーコードの追加

    →          EV_DISWAI     (-226)    /* 待ち禁止による待ち解除       */
    →          EV_LOCKSEM    (-227)    /* ロック型セマフォの不正操作   */

5.2 拡張SVCハンドラ機能コード

拡張 SVC の機能コードの下位 8 ビットのみを拡張 SVC 番号とする。 残りの上位ビットは任意に使用できる。 ただし、最上位ビット ( MSB ) は 0 でなければならない。 機能コードを拡張 SVC ハンドラへのパラメータとして追加する。

    i386 の場合
        ER svchdr( VP para, FN s_fncd )

5.3 拡張SVCハンドラ参照機能

    ER vref_svc(T_RSVC* pk_rsvc, FN s_fncd)

s_fncdで示す拡張SVCが定義されていれば、 その定義情報を *pk_rsvc へ返す。

5.4 ラウンドロビンスケジューリング

同一優先度のタスクはラウンドロビンスケジューリングを行う。 タスク毎に設定される最大割り当てタイム(slicetime)を経過すると、 自動的にその優先度のレディキューの最後に回される。

タスク生成時など休止(DORMANT)状態になるとき、 デフォルト値として slicetime = 0 が設定される。

slicetime = 0 のタスクはラウンドロビンとならず、 FCFS(First Come First Service) 方式でスケジューリングされる。

    ER vchg_slt(ID tskid, INT slicetime)

slicetime (単位ミリ秒)を設定する。

    tskid     : TSK_SELF 可
    slicetime : < 0 はエラー

ref_tsk() により現在の slicetime が参照可能。 (T_RTSKslicetime を追加)

ref_cfg() によりデフォルトの slicetime (default_slice_time) が参照可能 (T_RCFG にフィールド追加)。

5.5 タスクイベント待ち機能

タスクに固有なイベントを8個用意し、 その個々のイベントに対して slp_tsk()wup_tsk() と同様な単純なタスクの同期機能をサポートする。

    ER vwai_tev(INT tevmsk, TMO tmout)

tevmsk で指定した、 いずれかのタスクイベント(tskevt = 1〜8)の発生を待つ。 イベントの発生またはタイムアウトで待ちが解除される。 tevmsk は、1 << (tskevt-1) で表わすビット値の OR で指定する。 リターン時に tevmsk で指定したイベントはすべてクリアされる。 イベント発生により待ちが解除されたときには、 リターン値にタスクイベントの発生状況を、 tevmsk と同じビット値の形式で返す。

rel_wai() で待ちは無条件に解除される。 vena_wai(), vdis_wai() が適用される。

    ER vset_tev(ID tskid, INT tskevt)
        tskid : TSK_SELF 不可。
        tskevt : 1 〜 8

タスクのイベントを発生させる。 wup_tsk() と異なり、 同一イベントの発生回数は保持されない(発生の有無のみ保持されます)。

タスクのイベントの発生状態は保存され、 ref_tsk() で参照可能 (T_RTSKtskevent を追加)。 タスクの待ち要因として、 TTW_EV1TTW_EV8 を追加。

5.6 タスクの待ち状態禁止機能

タスクが指定した待ち状態に入ることを禁止する機能。 また、既に禁止する待ち状態に入っていた場合は、待ちを強制解除する機能。

待ち状態禁止機能により、待ちに入らなかった場合、あるいは待ちが強制解除 された場合は、EV_DISWAI ( -226 ) のエラーコードが戻る。

禁止する待ち状態は、以下の待ち要因のパターン (TTW_*) で指定される。

    [TTW_SLP]|[TTW_DLY ]|[TTW_NOD]|[TTW_FLG]|[TTW_SEM]|
    [TTW_MBX]|[TTW_SMBF]|[TTW_MBF]|[TTW_CAL]|[TTW_ACP]|
    [TTW_RDV]|[TTW_MPL ]|[TTW_MPF]|[TTW_PIS]|[TTW_EV1〜TTW_EV8]
TTW_RDVTTW_CAL と共に指定しなくてはいけない。

タスクに対して設定されている禁止待ち状態は、 ref_tsk() で参照可能 (T_RTSKwaitmask を追加)

拡張 SVC 処理中に設定された禁止待ち状態は、 拡張 SVC の処理後に元の状態に戻る。

    ER vdis_wai(ID tskid, UW waitptn, UW *tskwait)

tskid で示されたタスクに対して、 waitptn で指定した待ちを禁止する。 タスクがすでに waitptn に含まれる要因で待ちに入っている場合は待ちを強制解除する。 このシステムコールにより、 タスクの waitmask = waitptn となる。

tskid :
TSK_SELF
waitptn :
禁止する待ち要因のパターン ( TTW_* の組み合わせ )
*tskwait :
この呼び出しによって待ち状態の禁止の処理が行われた直後のタスクの待ち要因が設定される。 待ちに入っていない場合 0 が設定される。 0 以外の場合、タスクは waitmask には含まれない待ち要因で待ち状態になっている。 ref_tsk() で得られる tskwait と同である。
(例)
成立前のランデブは待ちを強制解除したいが、 ランデブ成立後は待ちの強制解除は行いたくない場合。
  vdis_wai(tskid, TTW_CAL, &taskwait);
すでにランデブが成立している場合、taskwait には TTW_RDV が設定される。
    ER vena_wai(ID tskid)

tskid で示されたタスクに対して、待ちを許可する。 このシステムコールにより、 タスクの waitmask = 0 となる。

    tskid : TSK_SELF 可

5.7 タスク強制例外機能

タスク強制例外は、 例外が発生したタスクのコンテキストで、 かつタスク生成時に指定した保護レベル(リング)で、 強制例外ハンドラを実行する機能である。 強制例外ハンドラは、基本的にタスクの一部として実行されるため、 タスクが使用出来るシステムコールはすべて使用可能である。

強制例外には、0〜31 の 32 種類の例外コードがあり、 0 が最も優先度が高く 31 が最も低くなる。 例外コード 0 は特殊で、他の 1〜31 とは異なる特徴を持つ。

例外コード 1〜31
例外コード 0 (復帰不能例外)

タスク生成時の保護レベル(リング)が TA_RNG0 のタスクに対して、強制例外を使用することは出来ない。

    ER vdef_brk(FN s_fncd, FP brkhdr)

拡張SVCのブレーク関数を定義する。 拡張SVCが未登録の時はエラーとなる。 既に定義されていた場合は、後から定義した関数が有効となる。 brkhdr == NADR の時は定義を解除する。

brkhdr()TA_HLNG のみ。 PIC および PID (Position Independent Code/Data) 対応の場合には、 s_fncdの拡張SVCを定義(def_svc) した時に指定したベースアドレスが、 高級言語対応ルーチンで設定される。

    VOID    brkhdr(ID tskid)
    {
            /* taskid  : 対象タスクID */
    }
    ER vdef_fex(ID tskid, FP fexchdr)

指定したタスクに対して強制例外ハンドラを定義する。 強制例外ハンドラはタスクに対して 1 つのみ定義可能で、 既に定義されていた場合は、後から定義した関数が有効となる。 exchdr == NADR の時は定義を解除する。

ペンディングの強制例外要求はクリアされ、 すべての強制例外は禁止状態となる。

強制例外ハンドラは、tskid のタスクのコンテキストで実行される下記の形式の関数です。 ただし、直接 fexchdr() が呼び出されるか否かは、 インプリメントに依存する。 インプリメントによっては、 そのインプリメント固有のエントリールーチンを持つ必要がある (各CPU のインプリメントに関するドキュメントを参照のこと)。

PIC および PID (Position Independent Code/Data) 対応の場合には、 tskid のタスクを生成(cre_tsk) した時に指定したベースアドレスが設定される。

    VOID    fexchdr(INT fexcode)
    {
            /* fexcode : 発生した例外コード 0〜31 */
            :::::
            /* 例外処理の終了 */
            if ( fexcode == 0 ) {
                    ext_tsk() または exd_tsk();
            } else {
                    vend_exc();
                    return または longjmp();
            }
    }
   ER vdis_fex(ID tskid, UINT fexcmsk)
   ER vena_fex(ID tskid, UINT fexcmsk)

指定したタスクに対する強制例外(fexcode : 0〜31) を許可/禁止する。 fexmask の1のビットに対応する強制例外を対象とする。

強制例外ハンドラが定義されていないときは E_NOEXS のエラーとなる。

禁止された強制例外の発生は完全に無視される。

強制例外の許可/禁止状態は ref_tsk() で取り出せる (T_RTSKfexcmsk を追加)。 fexcmsk は ビット単位のマスク(0:LSB 〜 31:MSB) で0で禁止、1で許可。

    ER vras_fex(ID tskid, INT fexcode)

指定したタスクに対して強制例外 (fexcode : 0〜31)を発生させる。

タスクが拡張SVCやSVCを実行している時は、 タスクに戻る時点で強制例外が発生する。 それまでに発生した強制例外はペンディングされ、 タスクに戻った時点で順次例外ハンドラが起動される。

タスクが強制例外ハンドラを実行中の場合は、 vend_exc() が実行されるまで、 強制例外はペンディングされる。 ただし、例外コード0の場合はペンディングされず、 ネストして強制例外ハンドラが実行される。

タスクが拡張SVCを実行中で、 かつ拡張SVCのブレーク関数が定義されている場合は、 ブレーク関数を実行する。

タスクに強制例外要求がペンディングされている時は、 タスクが拡張SVCを実行し、 その中から何らかのSVCを呼び出した時点、 または拡張SVCをネストして呼び出して戻ってきた時点で 拡張SVCのブレーク関数が実行される。 拡張SVCのブレーク関数は、 1つの拡張SVCに対して1回のみ実行される。

    ER vend_exc()

例外ハンドラを終了し、新たな強制例外の発生を許可する。

ペンディングされている強制例外がある場合には、 強制例外ハンドラが実行される。 ペンディングされている強制例外が複数ある場合には、 例外コードの最も小さいものが優先される。

例外コード0の例外ハンドラは、vend_exc() を呼び出すことは出来ない。 例外コード0の強制例外ハンドラは、 ext_tsk() または exd_tsk() によってタスクを終了しなければならない。

5.8 タスク統計情報

タスクが実行されていた時間を計測する。
タイマー割り込みごとに動作していたタスクをカウントする簡易的な方法。 その時のシステムモードによりユーザかシステムかを区別する。

    ER vinf_tsk(T_INFTSK *inf, ID tskid, BOOL clr)

tskid のタスクの統計情報を取り出す。 clr == TRUE の時は、 統計情報を取り出した後にクリアする。

    typedef struct {
            UINT    stime;  /* システム実行時間 (ms) */
            UINT    utime;  /* ユーザー実行時間 (ms) */
    } T_INFTSK;
※ システムモード

タスクがシステムオブジェクトにアクセスできる状態のとき 「システム」、 システムオブジェクトにアクセスすると E_OACV エラーになる状態のとき「ユーザー」となる。

5.9 システムロードの取り出し

システムのCPUロードを計測する。
タイマー割り込みごとに何もタスクが動作していない場合をカウントし、 そのカウント値と全体時間からCPUロードを求める簡易的な方法である。

    T_RSYS に cpuload を追加
        cpuload :  0 〜 10000 の値で、10000 は 100 % を意味する。

ref_sys()で、 前回の ref_sys() 呼び出し以降のCPUロードを取り出す。
前回の ref_sys() から 2^32 ms 以上の間隔をあけると、 その結果は保証されない。

5.10 ランデブの優先度待ち

cre_porporatr の指定において以下をサポートする。

    TA_TPRI         H'0...01        呼出待ちタスクがタスク優先度順

5.11 ロック型セマフォ

タスク終了時に自動的にロックを解放するロック型セマフォ機能。

    セマフォ属性として、以下を追加

    TA_LOCKSEM              0x00010000

TA_LOCKSEM の場合の動作:

ref_sem() により、 ロック型セマフォを獲得しているタスクの ID を知ることができる。

    typedef struct t_rsem {
            VP      exinf;          /* 拡張情報 */
            BOOL_ID wtsk;           /* 待ちタスクの有無 */
            INT     semcnt;         /* 現在のセマフォカウント値 */
            ID      gtsk;           /* ロック型セマフォ獲得タスク ID */
    } T_RSEM;

gtsk はロック型セマフォの場合のみ有効で、 それ以外の場合は常に0を返す。

5.12 タスク拡張情報の変更機能

タスクの拡張情報 (exinf)を変更する機能である。

    ER veif_tsk(VP *oldinf, VP newinf, ID tskid)

指定したタスクの exinf*oldinf に取り出した後、 exinf の値を newinf の値に変更する。

    oldinf == NADR の時は取り出さない
    newinf == NADR の時は変更しない。

5.13 アラームハンドラ

アラームハンドラの実行後のアラーム番号の自動解放を廃止した。

vdef_alm()での自動的に割り付けられる アラーム番号の衝突を避けるため、 実行したアラームハンドラのアラーム番号は自動解放しない。

したがって、vdef_alm() で定義したアラームハンドラは実際にアラームハンドラが 起動されたかどうかに関わらず、 アラームハンドラが不要になった時点で必ず def_alm(NADR) により定義を解除する必要がある。

5.14 ブロック単位のメモリー管理

この機能は、I-right/V には組み込まれていない。

5.15 省電力モード設定

    ER vset_pow( UINT pwmode )
pwmode へ指定する値
TPW_DOSUSPEND1サスペンド状態へ移行
TPW_DISLOWPOW2低消費電力モード切替禁止
TPW_ENALOWPOW3低消費電力モード切替許可
TPW_DOSUSPEND

すべてのタスク及びハンドラの実行を停止し、 周辺回路(タイマーや割込コントローラ)を停止し、 電源を切る(サスペンドする)。 電源オンされたら、周辺回路の再起動をし、 すべてのタスク及びハンドラの実行を再開して、 電源を切る前の状態に復帰(リジューム)し、リターンする。

何らかの理由によりリジュームに失敗したときには、 通常(リセット時)のスタートアップ処理を行い、 新たにシステムを立ち上げなおす。

TPW_DISLOWPOW

ディスパッチャ内で行われる低消費電力モードへの切替を禁止する (low_pow を呼び出さない)。

TPW_ENALOWPOW

ディスパッチャ内で行われる低消費電力モードへの切替を許可する。 (low_powを呼び出す)

ITRON 起動時のデフォルトは切替許可 (TPW_ENALOWPOW) となる。

TPW_DISLOWPOW が指定された場合、その要求回数がカウントされる。 TPW_DISLOWPOW が要求された回数と同じだけ TPW_ENALOWPOW が要求されないと、低消費電力モードは許可されない。

5.16 OS 稼働時間の取得

    ER vget_otm( SYSTIME *pk_tim )

OS 起動時から現在までの通算稼働時間をミリ秒単位で返す。
稼働時間は set_tim() による時刻設定の影響を受けず、 常に単調増加する時間となる。

5.17 論理アドレス空間での動作

下記の条件の元で、論理空間上で動作する。

  1. ITRON 自身が動作する論理アドレス空間は共有空間であり、 タスク切替等による論理空間の切替により影響されないこと。

  2. ITRON がアクセスするメモリ領域は 常にアクセスできることが保証され、 ページアウトされていないこと。


この章の目次にもどる
前頁:第3章 全般にもどる
次頁:第6章 I-right/V独自の機能にすすむ