第10章 時間管理機能
RI600PXにおける時間管理機能では,一定周期で発生する基本クロック用タイマ割り込みを利用してシステム時刻を操作/参照する機能のほかに,時間に依存した処理を実現する手段(タイマ・オペレーション機能:タスクの遅延,タイムアウト,周期ハンドラ,アラーム・ハンドラ,システム時刻)を提供しています。
システム時刻は,カーネル初期化部(vsta_knl, ivsta_knl)において0に初期化されたのち,システム情報(system)の基本クロック割り込み周期の分母(tic_deno),および基本クロック割り込み周期の分子(tic_nume)で定義された基本クロック周期ごとに更新されます。
基本クロック用タイマは,RX MCU内蔵のコンペア・マッチ・タイマ(CMT)のチャネル0~3のいずれかを使用することを基本としています。どのチャネルを使用するかは,システム・コンフィギュレーション・ファイルの基本クロック割り込み情報(clock)の基本クロック用タイマ・チャネルの選択(timer)で指定します。
基本クロック用タイマ割り込みを発生するためのハードウエアの初期化は,ユーザ・オウン・コーディング部として切り出されています。詳細は,「10.9 基本クロック用タイマ初期化ルーチン(_RI_init_cmt_knl( ))」を参照してください。
この場合,システム・コンフィギュレーション・ファイルのシステム情報(system)の基本クロック割り込み周期の分母(tic_deno),および基本クロック割り込み周期の分子(tic_nume)で基本クロック用タイマ割り込みの発生周期を指定することができます。
タスクの遅延は,一定の時間が経過するまでの間,自タスクをRUNNING状態からWAITING状態(時間経過待ち状態)へと遷移させ,一定の時間が経過した際には,該当タスクをWAITING状態からREADY状態へと遷移させるものです。
タイムアウトとは,タスクから発行された要求条件が即時成立しなかった場合,一定の時間が経過するまでの間,該当タスクをRUNNING状態からWAITING状態(起床待ち状態,資源獲得待ち状態,イベントフラグ待ち状態など)へと遷移させ,一定の時間が経過した際には,要求条件の成立/不成立を問わず,該当タスクをWAITING状態からREADY状態へと遷移させるものです。
なお,RI600PXでは,周期ハンドラを“タスクとは独立したもの(非タスク)”として位置づけています。このため,一定の時間が経過した際には,システム内で最高優先度を持つタスクが処理を実行中であっても,その処理は中断され,周期ハンドラに制御が移ります。
- サービス・コールの発行
RI600PXでは,周期ハンドラを“タスクとは独立したもの(非タスク)”として位置づけています。
周期ハンドラでは,“発行有効範囲”が“非タスク”のサービスコールを発行可能です。
RI600PXでは,周期ハンドラを“タスクとは独立したもの(非タスク)”として位置づけています。
周期ハンドラでは,“発行有効範囲”が“非タスク”のサービスコールを発行可能です。
備考 RI600PXでは,周期ハンドラ内の処理を高速に終了させる目的から,周期ハンドラ内の処理が完了するまでの間,スケジューラの起動を遅延しています。したがって,周期ハンドラ内でディスパッチ処理(タスクのスケジューリング処理)を伴うサービス・コール(isig_sem,iset_flgなど)が発行された際には,キュー操作などといった処理が行われるだけであり,実際のディスパッチ処理の実行は“周期ハンドラからの復帰命令(return命令の発行)”が発行されるまで遅延され,一括して行うようにしています。
1 ) システム・コンフィギュレーション・ファイルによる生成
システム・コンフィギュレーション・ファイルで静的API“cyclic_hand[]”を使用して周期ハンドラを生成します。
静的API“cyclic_hand[]”の詳細は,「20.19 周期ハンドラ情報(cyclic_hand[])」を参照してください。
システム・コンフィギュレーション・ファイルで静的API“cyclic_hand[]”を使用して周期ハンドラを生成します。
静的API“cyclic_hand[]”の詳細は,「20.19 周期ハンドラ情報(cyclic_hand[])」を参照してください。
2 ) cre_cycまたはacre_cycサービスコールによる生成
cre_cycは,パラメータpk_ccycが指す領域に設定された周期ハンドラ生成情報にしたがって,パラメータcycidで指定された周期ハンドラIDのタスクを生成します。
acre_cycは,パラメータpk_ccycが指す領域に設定された周期ハンドラ生成情報にしたがって周期ハンドラ生成し,生成された周期ハンドラIDを返します。
指定する周期ハンドラ生成情報は,以下の通りです。
cre_cycは,パラメータpk_ccycが指す領域に設定された周期ハンドラ生成情報にしたがって,パラメータcycidで指定された周期ハンドラIDのタスクを生成します。
acre_cycは,パラメータpk_ccycが指す領域に設定された周期ハンドラ生成情報にしたがって周期ハンドラ生成し,生成された周期ハンドラIDを返します。
指定する周期ハンドラ生成情報は,以下の通りです。
#include "kernel.h" /*標準ヘッダ・ファイルの定義*/ #include "kernel_id.h" /*cfg600pxが出力するヘッダ・ファイルの定義*/ extern void Cychdr1 ( VP_INT exinf ); #pragma task Task1 /*備考参照*/ void Task1 ( VP_INT exinf ); /*備考参照*/ void Task1 ( VP_INT exinf ) { ID cycid; /*変数の宣言*/ T_CCYC pk_ccyc = { /*変数の宣言,初期化*/ TA_STA, /*周期ハンドラ属性(cycatr)*/ 0, /*拡張情報(exinf)*/ (FP)Cychdr1, /*周期ハンドラの開始アドレス(cychdr)*/ 10, /*起動周期(cyctim)*/ 2, /*起動位相(cycphs)*/ }; ............ cycid = acre_cyc ( &pk_ccyc ); /*周期ハンドラの生成*/ ............ } |
#include "kernel.h" /*標準ヘッダ・ファイルの定義*/ #include "kernel_id.h" /*cfg600pxが出力するヘッダ・ファイルの定義*/ #pragma task Task1 /*備考参照*/ void Task1 ( VP_INT exinf ); /*備考参照*/ void Task1 ( VP_INT exinf ) { ID cycid = 8; /*変数の宣言,初期化*/ ............ ............ del_cyc( cycid ); /*周期ハンドラの削除*/ } |
- sta_cyc,ista_cyc
パラメータcycidで指定された周期ハンドラの動作状態を停止状態(STP状態)から動作状態(STA状態)へと遷移させます。これにより,対象周期ハンドラは,RI600PXの起動対象となります。
なお,本サービス・コールの発行から1回目の起動要求が発行されるまでの相対時間間隔は,周期ハンドラの生成時にTA_PHS属性を指定しているか否かにより異なります。
パラメータcycidで指定された周期ハンドラの動作状態を停止状態(STP状態)から動作状態(STA状態)へと遷移させます。これにより,対象周期ハンドラは,RI600PXの起動対象となります。
なお,本サービス・コールの発行から1回目の起動要求が発行されるまでの相対時間間隔は,周期ハンドラの生成時にTA_PHS属性を指定しているか否かにより異なります。
- TA_PHS属性を指定した場合
起動位相および起動周期にしたがって,起動タイミングが設定されます。
ただし,対象周期ハンドラの動作状態が開始状態の場合には,本サービス・コールを発行しても何も処理は行わず,エラーとしても扱いません
図10-1に,周期ハンドラの起動タイミング・イメージを示します。
起動位相および起動周期にしたがって,起動タイミングが設定されます。
ただし,対象周期ハンドラの動作状態が開始状態の場合には,本サービス・コールを発行しても何も処理は行わず,エラーとしても扱いません
図10-1に,周期ハンドラの起動タイミング・イメージを示します。
- TA_PHS属性を指定しない場合
本サービス・コールの発行時点を基点に,起動周期にしたがって起動タイミングが設定されます。
なお,起動タイミング設定処理については,対象周期ハンドラの動作状態に関係なく実行されます。
図10-2に,周期ハンドラの起動タイミング・イメージを示します。
本サービス・コールの発行時点を基点に,起動周期にしたがって起動タイミングが設定されます。
なお,起動タイミング設定処理については,対象周期ハンドラの動作状態に関係なく実行されます。
図10-2に,周期ハンドラの起動タイミング・イメージを示します。
#include "kernel.h" /*標準ヘッダ・ファイルの定義*/ #include "kernel_id.h" /*cfg600pxが出力するヘッダ・ファイルの定義*/ #pragma task Task1 /*備考参照*/ void Task1 ( VP_INT exinf ); /*備考参照*/ void Task1 ( VP_INT exinf ) { ID cycid = 1; /*変数の宣言,初期化*/ ............ ............ sta_cyc ( cycid ); /*周期ハンドラの動作開始*/ ............ ............ } |
- stp_cyc,istp_cyc
パラメータcycidで指定された周期ハンドラの動作状態を動作状態(STA状態)から停止状態(STP状態)へと遷移させます。これにより,本サービス・コールの発行からsta_cycまたはista_cycが発行されるまでの間,対象周期ハンドラは,RI600PXの起動対象から除外されます。
以下に,本サービス・コールの記述例を示します。
パラメータcycidで指定された周期ハンドラの動作状態を動作状態(STA状態)から停止状態(STP状態)へと遷移させます。これにより,本サービス・コールの発行からsta_cycまたはista_cycが発行されるまでの間,対象周期ハンドラは,RI600PXの起動対象から除外されます。
以下に,本サービス・コールの記述例を示します。
#include "kernel.h" /*標準ヘッダ・ファイルの定義*/ #include "kernel_id.h" /*cfg600pxが出力するヘッダ・ファイルの定義*/ #pragma task Task1 /*備考2参照*/ void Task1 ( VP_INT exinf ); /*備考2参照*/ void Task1 ( VP_INT exinf ) { ID cycid = 1; /*変数の宣言,初期化*/ ............ ............ stp_cyc ( cycid ); /*周期ハンドラの動作停止*/ ............ ............ } |
備考1 本サービス・コールでは,停止要求のキューイングが行われません。このため,すでに本サービス・コールが発行され,対象周期ハンドラの動作状態が停止状態(STP状態)へと遷移していた場合には,何も処理は行わず,エラーとしても扱いません。
- ref_cyc,iref_cyc
パラメータcycidで指定された周期ハンドラの周期ハンドラ詳細情報(現在状態,残り時間)をパラメータpk_rcycで指定された領域に格納します。
以下に,本サービス・コールの記述例を示します。
パラメータcycidで指定された周期ハンドラの周期ハンドラ詳細情報(現在状態,残り時間)をパラメータpk_rcycで指定された領域に格納します。
以下に,本サービス・コールの記述例を示します。
#include "kernel.h" /*標準ヘッダ・ファイルの定義*/ #include "kernel_id.h" /*cfg600pxが出力するヘッダ・ファイルの定義*/ #pragma task Task1 /*備考2参照*/ void Task1 ( VP_INT exinf ); /*備考2参照*/ void Task1 ( 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; /*残り時間の獲得*/ ............ ............ } |
なお,RI600PXでは,アラーム・ハンドラを“タスクとは独立したもの(非タスク)”として位置づけています。このため,指定した時間が経過した際には,システム内で最高優先度を持つタスクが処理を実行中であっても,その処理は中断され,アラーム・ハンドラに制御が移ります。
- サービス・コールの発行
RI600PXでは,アラーム・ハンドラを“タスクとは独立したもの(非タスク)”として位置づけています。
アラーム・ハンドラでは,“発行有効範囲”が“非タスク”のサービスコールを発行可能です。
RI600PXでは,アラーム・ハンドラを“タスクとは独立したもの(非タスク)”として位置づけています。
アラーム・ハンドラでは,“発行有効範囲”が“非タスク”のサービスコールを発行可能です。
備考 RI600PXでは,アラーム・ハンドラ内の処理を高速に終了させる目的から,アラーム・ハンドラ内の処理が完了するまでの間,スケジューラの起動を遅延しています。したがって,アラーム・ハンドラ内でディスパッチ処理(タスクのスケジューリング処理)を伴うサービス・コール(isig_sem,iset_flgなど)が発行された際には,キュー操作などといった処理が行われるだけであり,実際のディスパッチ処理の実行は“アラーム・ハンドラからの復帰命令(return命令の発行)”が発行されるまで遅延され,一括して行うようにしています。
1 ) システム・コンフィギュレーション・ファイルによる生成
システム・コンフィギュレーション・ファイルで静的API“alarm_hand[]”を使用してアラーム・ハンドラを生成します。
静静的API“alarm_hand[]”の詳細は,「20.20 アラーム・ハンドラ情報(alarm_hand[])」を参照してください。
システム・コンフィギュレーション・ファイルで静的API“alarm_hand[]”を使用してアラーム・ハンドラを生成します。
静静的API“alarm_hand[]”の詳細は,「20.20 アラーム・ハンドラ情報(alarm_hand[])」を参照してください。
2 ) cre_almまたはacre_almサービスコールによる生成
cre_almは,パラメータpk_calmが指す領域に設定されたアラーム・ハンドラ生成情報にしたがって,パラメータalmidで指定されたアラーム・ハンドラIDのタスクを生成します。
acre_almは,パラメータpk_calmが指す領域に設定されたアラーム・ハンドラ生成情報にしたがってアラーム・ハンドラ生成し,生成されたアラーム・ハンドラIDを返します。
生成されたアラーム・ハンドラは,停止状態(STA状態)となります。
指定するアラーム・ハンドラ生成情報は,以下の通りです。
cre_almは,パラメータpk_calmが指す領域に設定されたアラーム・ハンドラ生成情報にしたがって,パラメータalmidで指定されたアラーム・ハンドラIDのタスクを生成します。
acre_almは,パラメータpk_calmが指す領域に設定されたアラーム・ハンドラ生成情報にしたがってアラーム・ハンドラ生成し,生成されたアラーム・ハンドラIDを返します。
生成されたアラーム・ハンドラは,停止状態(STA状態)となります。
指定するアラーム・ハンドラ生成情報は,以下の通りです。
#include "kernel.h" /*標準ヘッダ・ファイルの定義*/ #include "kernel_id.h" /*cfg600pxが出力するヘッダ・ファイルの定義*/ extern void Almhdr1 (VP_INT exinf); #pragma task Task1 /*備考参照*/ void Task1 ( VP_INT exinf ); /*備考参照*/ void Task1 ( VP_INT exinf ) { ID almid; /*変数の宣言*/ T_CALM pk_calm = { /*変数の宣言,初期化*/ TA_HLNG, /*アラーム・ハンドラ属性(almatr)*/ 0, /*拡張情報(exinf)*/ (FP)Almhdr1 /*アラーム・ハンドラの開始アドレス(almhdr)*/ }; ............ almid = acre_alm ( &pk_calm ); /*アラーム・ハンドラの生成*/ ............ } |
- del_alm
パラメータalmidで指定されたアラーム・ハンドラを削除します。
本サービス・コールは,信頼されたドメインに所属するタスクだけが呼び出せます。
以下に,本サービス・コールの記述例を示します。
パラメータalmidで指定されたアラーム・ハンドラを削除します。
本サービス・コールは,信頼されたドメインに所属するタスクだけが呼び出せます。
以下に,本サービス・コールの記述例を示します。
#include "kernel.h" /*標準ヘッダ・ファイルの定義*/ #include "kernel_id.h" /*cfg600pxが出力するヘッダ・ファイルの定義*/ #pragma task Task1 /*備考参照*/ void Task1 ( VP_INT exinf ); /*備考参照*/ void Task1 ( VP_INT exinf ) { ID almid = 8; /*変数の宣言,初期化*/ ............ ............ del_alm( almid ); /*アラーム・ハンドラの削除*/ } |
- sta_alm,ista_alm
almidで指定されたアラーム・ハンドラの起動時刻をalmtimミリ秒後に設定し,動作状態(STA状態)にします。これにより,対象アラーム・ハンドラは,RI600PXの起動対象となります
以下に,本サービス・コールの記述例を示します。
almidで指定されたアラーム・ハンドラの起動時刻をalmtimミリ秒後に設定し,動作状態(STA状態)にします。これにより,対象アラーム・ハンドラは,RI600PXの起動対象となります
以下に,本サービス・コールの記述例を示します。
#include "kernel.h" /*標準ヘッダ・ファイルの定義*/ #include "kernel_id.h" /*cfg600pxが出力するヘッダ・ファイルの定義*/ #pragma task Task1 /*備考3参照*/ void Task1 ( VP_INT exinf ); /*備考3参照*/ void Task1 ( VP_INT exinf ) { ID almid = 1; /*変数の宣言,初期化*/ ............ ............ sta_alm ( almid ); /*アラーム・ハンドラの動作開始*/ ............ ............ } |
- stp_alm,istp_alm
パラメータalmidで指定されたアラーム・ハンドラの動作状態を動作状態(STA状態)から停止状態(STP状態)へと遷移させます。これにより,本サービス・コールの発行からsta_almまたはista_almが発行されるまでの間,対象アラーム・ハンドラは,RI600PXの起動対象から除外されます。
以下に,本サービス・コールの記述例を示します。
パラメータalmidで指定されたアラーム・ハンドラの動作状態を動作状態(STA状態)から停止状態(STP状態)へと遷移させます。これにより,本サービス・コールの発行からsta_almまたはista_almが発行されるまでの間,対象アラーム・ハンドラは,RI600PXの起動対象から除外されます。
以下に,本サービス・コールの記述例を示します。
#include "kernel.h" /*標準ヘッダ・ファイルの定義*/ #include "kernel_id.h" /*cfg600pxが出力するヘッダ・ファイルの定義*/ #pragma task Task1 /*備考2参照*/ void Task1 ( VP_INT exinf ); /*備考2参照*/ void Task1 ( VP_INT exinf ) { ID almid = 1; /*変数の宣言,初期化*/ ............ ............ stp_alm ( almid ); /*周期ハンドラの動作停止*/ ............ ............ } |
備考1 本サービス・コールでは,停止要求のキューイングが行われません。このため,すでに本サービス・コールが発行され,対象アラーム・ハンドラの動作状態が停止状態(STP状態)へと遷移していた場合には,何も処理は行わず,エラーとしても扱いません。
- ref_alm,iref_alm
パラメータalmidで指定されたアラーム・ハンドラの周期ハンドラ詳細情報(現在状態,残り時間)をパラメータpk_ralmで指定された領域に格納します。
以下に,本サービス・コールの記述例を示します。
パラメータalmidで指定されたアラーム・ハンドラの周期ハンドラ詳細情報(現在状態,残り時間)をパラメータpk_ralmで指定された領域に格納します。
以下に,本サービス・コールの記述例を示します。
#include "kernel.h" /*標準ヘッダ・ファイルの定義*/ #include "kernel_id.h" /*cfg600pxが出力するヘッダ・ファイルの定義*/ #pragma task Task1 /*備考2参照*/ void Task1 ( VP_INT exinf ); /*備考2参照*/ void Task1 ( 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; /*残り時間の獲得*/ ............ ............ } |
#include "kernel.h" /*標準ヘッダ・ファイルの定義*/ #include "kernel_id.h" /*cfg600pxが出力するヘッダ・ファイルの定義*/ #pragma task Task1 /*備考2参照*/ void Task1 ( VP_INT exinf ); /*備考2参照*/ void Task1 ( VP_INT exinf ) { SYSTIM p_systim; /*データ構造体の宣言*/ p_systim.ltime = 3600; /*データ構造体の初期化*/ p_systim.utime = 0; /*データ構造体の初期化*/ ............ ............ set_tim ( &p_systim ); /*システム時刻の設定*/ ............ ............ } |
#include "kernel.h" /*標準ヘッダ・ファイルの定義*/ #include "kernel_id.h" /*cfg600pxが出力するヘッダ・ファイルの定義*/ #pragma task Task1 /*備考2参照*/ void Task1 ( VP_INT exinf ); /*備考2参照*/ void Task1 ( VP_INT exinf ) { SYSTIM p_systim; /*データ構造体の宣言*/ UW ltime; /*変数の宣言*/ UH utime; /*変数の宣言*/ ............ ............ get_tim ( &p_systim ); /*システム時刻の参照*/ ltime = p_systim.ltime; /*システム時刻(下位32ビット)の獲得*/ utime = p_systim.utime; /*システム時刻(上位16ビット)の獲得*/ ............ ............ } |
- 基本クロック用タイマ初期化ルーチンの基本型
以下に,基本クロック用タイマ初期化ルーチンの基本型を示します。
以下に,基本クロック用タイマ初期化ルーチンの基本型を示します。
- 解説
基本クロック用タイマ初期化ルーチンは,vsta_knl,ivsta_knlから呼び出されます。
_RI_CLOCK_TIMERは,cfg600pxがkernel_id.hに出力するマクロです。_RI_CLOCK_TIMERの定義値は,システム・コンフィギュレーション・ファイルの基本クロック用タイマ・チャネルの選択(timer)にしたがって,以下のようになります。
基本クロック用タイマ初期化ルーチンは,vsta_knl,ivsta_knlから呼び出されます。
_RI_CLOCK_TIMERは,cfg600pxがkernel_id.hに出力するマクロです。_RI_CLOCK_TIMERの定義値は,システム・コンフィギュレーション・ファイルの基本クロック用タイマ・チャネルの選択(timer)にしたがって,以下のようになります。
clock.timerに“CMT0”,“CMT1”,“CMT2”,または“CMT3”を指定した場合,cfg600pxはri_cmt.hに基本タイマ用初期化用のインライン関数“void _RI_init_cmt(void)”を出力するので,_RI_init_cmt_knl()はこれを呼び出すように実装してください。