第8章  時間管理機能


本章では,RI600V4が提供している時間管理機能について解説しています。

8.1 概  要

RI600V4における時間管理機能では,一定周期で発生する基本クロック用タイマ割り込みを利用してシステム時刻を操作/参照する機能のほかに,時間に依存した処理を実現する手段(タイマ・オペレーション機能:タスクの遅延タイムアウト周期ハンドラアラーム・ハンドラシステム時刻)を提供しています。

8.2 システム時刻

システム時刻とは,RI600V4が時間管理を行う際に使用する“時間(単位:ミリ秒)”です。

システム時刻は,カーネル初期化部(vsta_knl, ivsta_knl)において0に初期化されたのち,システム情報(system)基本クロック割り込み周期の分母(tic_deno),および基本クロック割り込み周期の分子(tic_nume)で定義された基本クロック周期ごとに更新されます。

8.2.1 基本クロック用タイマ割り込み

RI600V4では,時間管理機能を実現するために,一定周期で発生する割り込み(基本クロック用タイマ割り込み)を使用します。

基本クロック用タイマ割り込みが発生した際は,RI600V4の時間に関連した処理(システム時刻の更新,タスクのタイムアウト/遅延,周期ハンドラの起動,アラーム・ハンドラの起動など)が実行されます。

基本クロック用タイマは,RX MCU内蔵のコンペア・マッチ・タイマ(CMT)のチャネル0〜3のいずれかを使用することを基本としています。どのチャネルを使用するかは,システム・コンフィギュレーション・ファイルの基本クロック割り込み情報(clock)基本クロック用タイマ・チャネルの選択(timer)で指定します。

基本クロック用タイマ割り込みを発生するためのハードウエアの初期化は,cfg600が出力する“ri_cmt.h”で実装されている“void _RI_init_cmt(void)”で行われます。ブート処理関数(PowerON_Reset_PC( ))は,_RI_init_cmt()を呼び出す必要があります。

8.2.2 基本クロック周期

RI600V4のサービス・コールでは時間指定パラメータの単位は「ミリ秒」になっています。

基本クロック用タイマ割り込みの発生周期は1ミリ秒とするのが望ましいですが,ターゲット・システムの性質上(処理能力,必要とする時間分解能など) 1ミリ秒とすることが困難な場合があります。

この場合,システム・コンフィギュレーション・ファイルのシステム情報(system)基本クロック割り込み周期の分母(tic_deno),および基本クロック割り込み周期の分子(tic_nume)で基本クロック用タイマ割り込みの発生周期を指定することができます。

基本クロック周期を指定すると1回の基本クロック用タイマ割り込みで基本クロック周期分の時間が経過したとして処理されます。

8.3 タイマ・オペレーション機能

RI600V4におけるタイマ・オペレーション機能では,時間に依存した処理を実現する手段として“タスクの遅延タイムアウト周期ハンドラアラーム・ハンドラシステム時刻”を提供しています。

8.4 タスクの遅延

タスクの遅延は,一定の時間が経過するまでの間,自タスクをRUNNING状態からWAITING状態(時間経過待ち状態)へと遷移させ,一定の時間が経過した際には,該当タスクをWAITING状態からREADY状態へと遷移させるものです。

なお,遅延起床は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。

dly_tsk

8.5 タイムアウト

タイムアウトとは,タスクから発行された要求条件が即時成立しなかった場合,一定の時間が経過するまでの間,該当タスクをRUNNING状態からWAITING状態(起床待ち状態,資源獲得待ち状態,イベントフラグ待ち状態など)へと遷移させ,一定の時間が経過した際には,要求条件の成立/不成立を問わず,該当タスクをWAITING状態からREADY状態へと遷移させるものです。

なお,タイムアウトは,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。

tslp_tsk  twai_sem  twai_flg  tsnd_dtq
trcv_dtq  trcv_mbx  tloc_mtx  tsnd_mbf
trcv_mbf tget_mpf tget_mpl

8.6 周期ハンドラ

周期ハンドラは,一定の時間ごとに周期的に起動される周期処理専用ルーチンです。

なお,RI600V4では,周期ハンドラを“タスクとは独立したもの(非タスク)”として位置づけています。このため,一定の時間が経過した際には,システム内で最高優先度を持つタスクが処理を実行中であっても,その処理は中断され,周期ハンドラに制御が移ります。

8.6.1 周期ハンドラの基本形

以下に,周期ハンドラを記述する場合の基本型を示します。exinfには,“周期ハンドラ情報(cyclic_hand[])拡張情報(exinf)渡されます。

 #include        "kernel.h"              /*標準ヘッダ・ファイルの定義*/
 #include        "kernel_id.h"           /*cfg600が出力するヘッダ・ファイルの定義*/
 
 void cychdr ( VP_INT exinf )
 {
         ............
         ............
 
         return;                         /*周期ハンドラの終了*/
 }


備考 ハンドラ関数のプロトタイプ宣言は,cfg600がkernel_id.hに出力します。

8.6.2 周期ハンドラ内での処理

- スタック
周期ハンドラは,システム・スタックを使用します。


- サービス・コールの発行
RI600V4では,周期ハンドラを“タスクとは独立したもの(非タスク)”として位置づけています。
周期ハンドラでは,“発行有効範囲”が“非タスク”のサービスコールを発行可能です。



備考 RI600V4では,周期ハンドラ内の処理を高速に終了させる目的から,周期ハンドラ内の処理が完了するまでの間,スケジューラの起動を遅延しています。したがって,周期ハンドラ内でディスパッチ処理(タスクのスケジューリング処理)を伴うサービス・コール(isig_semiset_flgなど)が発行された際には,キュー操作などといった処理が行われるだけであり,実際のディスパッチ処理の実行は“周期ハンドラからの復帰命令(return命令の発行)”が発行されるまで遅延され,一括して行うようにしています。

- 処理開始時のPSW

表8−1  周期ハンドラ処理開始時のPSW

ビット



備考

I

1

IPL

処理開始時より下げてはなりません。

PM

0

スーパバイザ・モード

U

0

システム・スタック

C, Z, S, O

不定

その他

0



8.6.3 周期ハンドラの生成

RI600V4では,周期ハンドラの静的な生成のみサポートしています。処理プログラムからサービス・コールを発行して動的に生成することはできません。

周期ハンドラの静的生成とは,システム・コンフィギュレーション・ファイルで静的API“cyclic_hand[]”を使用して周期ハンドラを定義することをいいます。

静的API“cyclic_hand[]”の詳細は,「19.16 周期ハンドラ情報(cyclic_hand[])」を参照してください。

8.6.4 周期ハンドラの動作開始

周期ハンドラの動作開始は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。

- sta_cycista_cyc
パラメータcycidで指定された周期ハンドラの動作状態を停止状態(STP状態)から動作状態(STA状態)へと遷移させます。これにより,対象周期ハンドラは,RI600V4の起動対象となります。
なお,本サービス・コールの発行から1回目の起動要求が発行されるまでの相対時間間隔は,コンフィギュレーション時に対象周期ハンドラに対してTA_PHS属性(phsatr)を指定しているか否かにより異なります。


- TA_PHS属性を指定した場合
起動位相(phs_counter)起動周期(interval_counter)にしたがって,起動タイミングが設定されます。
ただし,対象周期ハンドラの動作状態が開始状態の場合には,本サービス・コールを発行しても何も処理は行わず,エラーとしても扱いません。
図8−1に,周期ハンドラの起動タイミング・イメージを示します。




図8−1  TA_PHS属性:指定あり



- TA_PHS属性を指定しない場合
本サービス・コールの発行時点を基点とし,起動周期(interval_counter)したがって起動タイミングが設定されます。
なお,起動タイミング設定処理については,対象周期ハンドラの動作状態に関係なく実行されます。
図8−2に,周期ハンドラの起動タイミング・イメージを示します。




図8−2  TA_PHS属性:指定なし



以下に,本サービス・コールの記述例を示します。

 #include        "kernel.h"              /*標準ヘッダ・ファイルの定義*/
 #include        "kernel_id.h"           /*cfg600が出力するヘッダ・ファイルの定義*/
 
 void task ( VP_INT exinf )
 {
         ID      cycid = 1;              /*変数の宣言,初期化*/
 
         ............
         ............
 
         sta_cyc ( cycid );    /*周期ハンドラの動作開始*/
 
         ............
         ............
 }


8.6.5 周期ハンドラの動作停止

周期ハンドラの動作停止は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。

- stp_cycistp_cyc
パラメータcycidで指定された周期ハンドラの動作状態を動作状態(STA状態)から停止状態(STP状態)へと遷移させます。これにより,本サービス・コールの発行からsta_cycまたはista_cycが発行されるまでの間,対象周期ハンドラは,RI600V4の起動対象から除外されます。
以下に,本サービス・コールの記述例を示します。


 #include        "kernel.h"              /*標準ヘッダ・ファイルの定義*/
 #include        "kernel_id.h"           /*cfg600が出力するヘッダ・ファイルの定義*/
 
 void task ( VP_INT exinf )
 {
         ID      cycid = 1;              /*変数の宣言,初期化*/
 
         ............
         ............
 
         stp_cyc ( cycid );              /*周期ハンドラの動作停止*/
 
         ............
         ............
 }


備考 本サービス・コールでは,停止要求のキューイングが行われません。このため,すでに本サービス・コールが発行され,対象周期ハンドラの動作状態が停止状態(STP状態)へと遷移していた場合には,何も処理は行わず,エラーとしても扱いません。

8.6.6 周期ハンドラ詳細情報の参照

周期ハンドラ詳細情報の参照は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。

- ref_cyciref_cyc
パラメータcycidで指定された周期ハンドラの周期ハンドラ詳細情報(現在状態,残り時間)をパラメータpk_rcycで指定された領域に格納します。
以下に,本サービス・コールの記述例を示します。


 #include        "kernel.h"              /*標準ヘッダ・ファイルの定義*/
 #include        "kernel_id.h"           /*cfg600が出力するヘッダ・ファイルの定義*/
 
 void task ( VP_INT exinf )
 {
         ID      cycid = 1;              /*変数の宣言,初期化*/
         T_RCYC  pk_rcyc;                /*データ構造体の宣言*/
         STAT    cycstat;                /*変数の宣言*/
         RELTIM  lefttim;                /*変数の宣言*/
 
         ............
         ............
 
         ref_cyc ( cycid, &pk_rcyc );    /*周期ハンドラ詳細情報の参照*/
 
         cycstat = pk_rcyc.cycstat;      /*現在状態の獲得*/
         lefttim = pk_rcyc.lefttim;      /*残り時間の獲得*/
 
         ............
         ............
 }


備考 周期ハンドラ詳細情報T_RCYCについての詳細は,「【 周期ハンドラ詳細情報T_RCYCの構造 】」を参照してください。

8.7 アラーム・ハンドラ

アラーム・ハンドラは,指定した時間が経過したときに起動されるルーチンです。

なお,RI600V4では,アラーム・ハンドラを“タスクとは独立したもの(非タスク)”として位置づけています。このため,指定した時間が経過した際には,システム内で最高優先度を持つタスクが処理を実行中であっても,その処理は中断され,アラーム・ハンドラに制御が移ります。

8.7.1 アラーム・ハンドラの基本形

以下に,アラーム・ハンドラを記述する場合の基本型を示します。exinfには,アラーム・ハンドラ情報(alarm_hand[])拡張情報(exinf)が渡されます。

 #include        "kernel.h"              /*標準ヘッダ・ファイルの定義*/
 #include        "kernel_id.h"           /*cfg600が出力するヘッダ・ファイルの定義*/
 
 void almhdr ( VP_INT exinf )
 {
         ............
         ............
 
         return;                         /*アラーム・ハンドラの終了*/
 }


備考 ハンドラ関数のプロトタイプ宣言は,cfg600がkernel_id.hに出力します。

8.7.2 アラーム・ハンドラ内での処理

- スタック
アラーム・ハンドラは,システム・スタックを使用します。


- サービス・コールの発行
RI600V4では,アラーム・ハンドラを“タスクとは独立したもの(非タスク)”として位置づけています。
アラーム・ハンドラでは,“発行有効範囲”が“非タスク”のサービスコールを発行可能です。



備考 RI600V4では,アラーム・ハンドラ内の処理を高速に終了させる目的から,アラーム・ハンドラ内の処理が完了するまでの間,スケジューラの起動を遅延しています。したがって,アラーム・ハンドラ内でディスパッチ処理(タスクのスケジューリング処理)を伴うサービス・コール(isig_semiset_flgなど)が発行された際には,キュー操作などといった処理が行われるだけであり,実際のディスパッチ処理の実行は“アラーム・ハンドラからの復帰命令(return命令の発行)”が発行されるまで遅延され,一括して行うようにしています。

- 処理開始時のPSW

表8−2  アラーム・ハンドラ処理開始時のPSW

ビット



備考

I

1

IPL

処理開始時より下げてはなりません。

PM

0

スーパバイザ・モード

U

0

システム・スタック

C, Z, S, O

不定

その他

0



8.7.3 アラーム・ハンドラの生成

RI600V4では,アラーム・ハンドラの静的な生成のみサポートしています。処理プログラムからサービス・コールを発行して動的に生成することはできません。

周期ハンドラの静的生成とは,システム・コンフィギュレーション・ファイルで静的API“alarm_hand[]”を使用して周期ハンドラを定義することをいいます。

静的API“alarm_hand[]”の詳細は,「19.17 アラーム・ハンドラ情報(alarm_hand[])」を参照してください。

8.7.4 アラーム・ハンドラの動作開始

アラーム・ハンドラの動作開始は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。

- sta_almista_alm
almidで指定されたアラーム・ハンドラの起動時刻をalmtimミリ秒後に設定し,動作状態(STA状態)にします。これにより,対象アラーム・ハンドラは,RI600V4の起動対象となります
以下に,本サービス・コールの記述例を示します。


 #include        "kernel.h"              /*標準ヘッダ・ファイルの定義*/
 #include        "kernel_id.h"           /*cfg600が出力するヘッダ・ファイルの定義*/
 
 void task ( VP_INT exinf )
 {
         ID      almid = 1;              /*変数の宣言,初期化*/
 
         ............
         ............
 
         sta_alm ( almid );    /*アラーム・ハンドラの動作開始*/
 
         ............
         ............
 }


備考1 almtimに0を指定すると,次回の基本クロック割り込み時にアラーム・ハンドラが起動されます。

備考2 対象アラーム・ハンドラがすでに動作状態の場合でも,本サービス・コールは起動時刻を再設定します。以前の起動時刻の設定は無効となります。

8.7.5 アラーム・ハンドラの動作停止

アラーム・ハンドラの動作停止は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。

- stp_almistp_alm
パラメータalmidで指定されたアラーム・ハンドラの動作状態を動作状態(STA状態)から停止状態(STP状態)へと遷移させます。これにより,本サービス・コールの発行からsta_almまたはista_almが発行されるまでの間,対象アラーム・ハンドラは,RI600V4の起動対象から除外されます。
以下に,本サービス・コールの記述例を示します。


 #include        "kernel.h"              /*標準ヘッダ・ファイルの定義*/
 #include        "kernel_id.h"           /*cfg600が出力するヘッダ・ファイルの定義*/
 
 void task ( VP_INT exinf )
 {
         ID      almid = 1;              /*変数の宣言,初期化*/
 
         ............
         ............
 
         stp_alm ( almid );              /*周期ハンドラの動作停止*/
 
         ............
         ............
 }


備考 本サービス・コールでは,停止要求のキューイングが行われません。このため,すでに本サービス・コールが発行され,対象アラーム・ハンドラの動作状態が停止状態(STP状態)へと遷移していた場合には,何も処理は行わず,エラーとしても扱いません。

8.7.6 アラーム・ハンドラ詳細情報の参照

アラーム・ハンドラ詳細情報の参照は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。

- ref_almiref_alm
パラメータalmidで指定されたアラーム・ハンドラの周期ハンドラ詳細情報(現在状態,残り時間)をパラメータpk_rcycで指定された領域に格納します。
以下に,本サービス・コールの記述例を示します。


 #include        "kernel.h"              /*標準ヘッダ・ファイルの定義*/
 #include        "kernel_id.h"           /*cfg600が出力するヘッダ・ファイルの定義*/
 
 void task ( VP_INT exinf )
 {
         ID      almid = 1;              /*変数の宣言,初期化*/
         T_RALM  pk_ralm;                /*データ構造体の宣言*/
         STAT    almstat;                /*変数の宣言*/
         RELTIM  lefttim;                /*変数の宣言*/
 
         ............
         ............
 
         ref_alm ( almid, &pk_ralm );    /*周期ハンドラ詳細情報の参照*/
 
         almstat = pk_ralm.almstat;      /*現在状態の獲得*/
         lefttim = pk_ralm.lefttim;      /*残り時間の獲得*/
 
         ............
         ............
 }


備考 アラーム・ハンドラ詳細情報T_RALMについての詳細は,「【 アラーム・ハンドラ詳細情報T_RALMの構造 】」を参照してください。

8.8 システム時刻

8.8.1 システム時刻の設定

システム時刻の設定は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。

なお,システム時刻を変更しても,それ以前に行われた時間管理要求(タスクのタイムアウト,dly_tsk によるタスクの遅延,周期ハンドラ,およびアラーム・ハンドラ)が発生する実時刻は変化しません。

- set_timiset_tim
RI600V4のシステム時刻(単位:ミリ秒)をパラメータp_systimで指定された時間に変更します。
以下に,本サービス・コールの記述例を示します。


 #include        "kernel.h"              /*標準ヘッダ・ファイルの定義*/
 #include        "kernel_id.h"           /*cfg600が出力するヘッダ・ファイルの定義*/
 
 void task ( VP_INT exinf )
 {
         SYSTIM  p_systim;               /*データ構造体の宣言*/
 
         p_systim.ltime = 3600;          /*データ構造体の初期化*/
         p_systim.utime = 0;             /*データ構造体の初期化*/
 
         ............
         ............
 
         set_tim ( &p_systim );          /*システム時刻の設定*/
 
         ............
         ............
 }


備考 システム時刻情報SYSTIMについての詳細は,「【 システム時刻情報SYSTIMの構造 】」を参照してください。

8.8.2 システム時刻の参照

システム時刻の参照は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。

- get_timiget_tim
RI600V4のシステム時刻(単位:ミリ秒)をパラメータp_systimで指定された領域に格納します。
以下に,本サービス・コールの記述例を示します。


 #include        "kernel.h"              /*標準ヘッダ・ファイルの定義*/
 #include        "kernel_id.h"           /*cfg600が出力するヘッダ・ファイルの定義*/
 
 void task ( VP_INT exinf )
 {
         SYSTIM  p_systim;               /*データ構造体の宣言*/
         UW      ltime;                  /*変数の宣言*/
         UH      utime;                  /*変数の宣言*/
 
         ............
         ............
 
         get_tim ( &p_systim );          /*システム時刻の参照*/
 
         ltime = p_systim.ltime;         /*システム時刻(下位32ビット)の獲得*/
         utime = p_systim.utime;         /*システム時刻(上位16ビット)の獲得*/
 
         ............
         ............
 }


備考 システム時刻情報SYSTIMについての詳細は,「【 システム時刻情報SYSTIMの構造 】」を参照してください。

8.9 基本クロック用タイマの初期化

cfg600は,基本クロック用タイマ初期化関数(void _RI_init_cmt(void))が記述されたri_cmt.hを出力します。

基本クロック用タイマ初期化関数は,ブート処理関数(PowerON_Reset_PC( ))から呼び出してください。