第9章 時間管理機能
RI850V4における時間管理機能では,一定周期で発生する基本クロック用タイマ割り込みを利用してシステム時刻を操作/参照する機能のほかに,時間に依存した処理を実現する手段(タイマ・オペレーション機能:遅延起床,タイムアウト,周期ハンドラ)を提供しています。
なお,システム時刻は,カーネル初期化部において,初期化されたのち,システム・コンフィギュレーション・ファイル作成時に基本クロック用タイマ割り込みの例外コードtim_intnoで定義されたEIレベル・マスカブル割り込みが発生した際,基本クロック周期tim_baseを単位とした更新が行われます。
基本クロック用タイマ割り込みの割り込み要因は,システム・コンフィギュレーション・ファイル作成時に基本クロック用タイマ割り込みの例外コードtim_intnoで定義されたEIレベル・マスカブル割り込みとなります。
備考 RI850V4では,基本クロック用タイマ割り込みに対応した処理に制御を移す際,プライオリティ・マスク・レジスタPMRのPMnビット,プログラム・ステータス・ワードPSWのIDビットに対する操作,およびeiret命令の発行(イン・サービス・プライオリティ・レジスタISPRのクリア)を行い,EIレベル・マスカブル割り込みの受け付けを許可しています。
したがって,該当処理内でEIレベル・マスカブル割り込みが発生した際には,該当割り込みは受け付けられます。
したがって,該当処理内でEIレベル・マスカブル割り込みが発生した際には,該当割り込みは受け付けられます。
基本クロック用タイマ割り込みの発生周期は,システム・コンフィギュレーション・ファイル作成時に基本クロック周期tim_baseで定義することができます。基本クロック周期を指定すると1回の基本クロック用タイマ割り込みで基本クロック周期分の時間が経過したとして処理されます。
遅延起床とは,一定の時間が経過するまでの間,自タスクをRUNNING状態からWAITING状態(時間経過待ち状態)へと遷移させ,一定の時間が経過した際には,該当タスクをWAITING状態からREADY状態へと遷移させるものです。
タイムアウトとは,タスクから発行された要求条件が即時成立しなかった場合,一定の時間が経過するまでの間,該当タスクをRUNNING状態からWAITING状態(起床待ち状態,資源獲得待ち状態,イベントフラグ待ち状態など)へと遷移させ,一定の時間が経過した際には,要求条件の成立/不成立を問わず,該当タスクをWAITING状態からREADY状態へと遷移させるものです。
なお,RI850V4では,周期ハンドラを“タスクとは独立したもの(非タスク)”として位置づけています。このため,一定の時間が経過した際には,システム内で最高優先度を持つタスクが処理を実行中であっても,その処理は中断され,周期ハンドラに制御が移ります。
また,RI850V4では,周期ハンドラを管理するに当たり,周期ハンドラと一対一に対応した管理オブジェクト(周期ハンドラ管理ブロック)を用いることにより,周期ハンドラが取り得る状態の管理,および周期ハンドラ自体の管理を行っています。
- 周期ハンドラの基本型
周期ハンドラを記述する場合,VP_INT型の引き数を1つ持ったvoid型の関数として記述します。
なお,引き数exinfには“周期ハンドラ情報で指定した拡張情報”が設定されます。
以下に,周期ハンドラをC言語で記述する場合の基本型を示します。
周期ハンドラを記述する場合,VP_INT型の引き数を1つ持ったvoid型の関数として記述します。
なお,引き数exinfには“周期ハンドラ情報で指定した拡張情報”が設定されます。
以下に,周期ハンドラをC言語で記述する場合の基本型を示します。
#include <kernel.h> /*標準ヘッダ・ファイルの定義*/ #include <kernel_id.h> /*システム情報ヘッダ・ファイルの定義*/ void cychdr ( VP_INT exinf ) { ............ ............ return; /*周期ハンドラの終了*/ } |
- 記述方法
C言語,またはアセンブリ言語で記述します。
C言語で記述する際は通常のvoid型関数と同様に記述することができます。
アセンブリ言語で記述する際は使用するコンパイラの呼び出し規約にのっとって作成してください。
C言語,またはアセンブリ言語で記述します。
C言語で記述する際は通常のvoid型関数と同様に記述することができます。
アセンブリ言語で記述する際は使用するコンパイラの呼び出し規約にのっとって作成してください。
- スタックの切り替え
RI850V4では,周期ハンドラに制御を移す際,基本情報において指定されたシステム・スタックへの切り替え処理を,周期ハンドラから周期ハンドラの起動要因となる基本クロック用タイマ割り込みが発生した処理プログラムに制御を戻す際に該当スタックへの切り替え処理を行っています。したがって,周期ハンドラ内でスタックの切り替えに関する記述を行う必要がありません。
RI850V4では,周期ハンドラに制御を移す際,基本情報において指定されたシステム・スタックへの切り替え処理を,周期ハンドラから周期ハンドラの起動要因となる基本クロック用タイマ割り込みが発生した処理プログラムに制御を戻す際に該当スタックへの切り替え処理を行っています。したがって,周期ハンドラ内でスタックの切り替えに関する記述を行う必要がありません。
- サービス・コールの発行
RI850V4では,周期ハンドラを“タスクとは独立したもの(非タスク)”として位置づけています。このため,周期ハンドラでは,“非タスク内から発行可能なサービス・コール”のみが発行可能となります。
RI850V4では,周期ハンドラを“タスクとは独立したもの(非タスク)”として位置づけています。このため,周期ハンドラでは,“非タスク内から発行可能なサービス・コール”のみが発行可能となります。
備考1 RI850V4では,周期ハンドラ内の処理を高速に終了させる目的から,周期ハンドラ内の処理が完了するまでの間,スケジューラの起動を遅延しています。したがって,周期ハンドラ内でディスパッチ処理(タスクのスケジューリング処理)を伴うサービス・コール(isig_sem,iset_flgなど)が発行された際には,キュー操作などといった処理が行われるだけであり,実際のディスパッチ処理の実行は“周期ハンドラからの復帰命令(return命令の発行)”が発行されるまで遅延され,一括して行うようにしています。
- EIレベル・マスカブル割り込みの受け付け状態
RI850V4では,周期ハンドラに制御を移す際,プライオリティ・マスク・レジスタPMRのPMnビット,プログラム・ステータス・ワードPSWのIDビットに対する操作,およびeiret命令の発行(イン・サービス・プライオリティ・レジスタISPR)を行い,EIレベル・マスカブル割り込みの受け付けを許可しています。
したがって,周期ハンドラ内でEIレベル・マスカブル割り込みが発生した際には,該当割り込みは受け付けられます。
RI850V4では,周期ハンドラに制御を移す際,プライオリティ・マスク・レジスタPMRのPMnビット,プログラム・ステータス・ワードPSWのIDビットに対する操作,およびeiret命令の発行(イン・サービス・プライオリティ・レジスタISPR)を行い,EIレベル・マスカブル割り込みの受け付けを許可しています。
したがって,周期ハンドラ内でEIレベル・マスカブル割り込みが発生した際には,該当割り込みは受け付けられます。
#include <kernel.h> /*標準ヘッダ・ファイルの定義*/ #include <kernel_id.h> /*システム情報ヘッダ・ファイルの定義*/ void task ( 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> /*システム情報ヘッダ・ファイルの定義*/ 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ビット)の獲得*/ ............ ............ } |
- sta_cyc,ista_cyc
パラメータcycidで指定された周期ハンドラの動作状態を停止状態(STP状態)から動作状態(STA状態)へと遷移させます。これにより,対象周期ハンドラは,RI850V4の起動対象となります。
なお,本サービス・コールの発行から1回目の起動要求が発行されるまでの相対時間間隔は,コンフィギュレーション時に対象周期ハンドラに対してTA_PHS属性を指定しているか否かにより異なります。
パラメータcycidで指定された周期ハンドラの動作状態を停止状態(STP状態)から動作状態(STA状態)へと遷移させます。これにより,対象周期ハンドラは,RI850V4の起動対象となります。
なお,本サービス・コールの発行から1回目の起動要求が発行されるまでの相対時間間隔は,コンフィギュレーション時に対象周期ハンドラに対してTA_PHS属性を指定しているか否かにより異なります。
- “指定あり”の場合
コンフィギュレーション時に定義した起動位相(初期起動位相cycphs,起動周期cyctim)で対象周期ハンドラに対する起動タイミング設定処理が行われます。
ただし,対象周期ハンドラの動作状態が開始状態の場合には,本サービス・コールを発行しても何も処理は行わず,エラーとしても扱いません。
図9-1に,周期ハンドラの起動タイミング・イメージを示します。
コンフィギュレーション時に定義した起動位相(初期起動位相cycphs,起動周期cyctim)で対象周期ハンドラに対する起動タイミング設定処理が行われます。
ただし,対象周期ハンドラの動作状態が開始状態の場合には,本サービス・コールを発行しても何も処理は行わず,エラーとしても扱いません。
図9-1に,周期ハンドラの起動タイミング・イメージを示します。
- “指定なし”の場合
本サービス・コールの発行を基準点とした起動位相(起動周期cyctim)で対象周期ハンドラに対する起動タイミング設定処理が行われます。
なお,起動タイミング設定処理については,対象周期ハンドラの動作状態に関係なく実行されます。
図9-2に,周期ハンドラの起動タイミング・イメージを示します。
本サービス・コールの発行を基準点とした起動位相(起動周期cyctim)で対象周期ハンドラに対する起動タイミング設定処理が行われます。
なお,起動タイミング設定処理については,対象周期ハンドラの動作状態に関係なく実行されます。
図9-2に,周期ハンドラの起動タイミング・イメージを示します。
#include <kernel.h> /*標準ヘッダ・ファイルの定義*/ #include <kernel_id.h> /*システム情報ヘッダ・ファイルの定義*/ void task ( VP_INT exinf ) { ID cycid = ID_CYC1; /*変数の宣言,初期化*/ |
............ ............ sta_cyc ( cycid ); /*周期ハンドラの動作開始*/ ............ ............ } |
- stp_cyc,istp_cyc
パラメータcycidで指定された周期ハンドラの動作状態を動作状態(STA状態)から停止状態(STP状態)へと遷移させます。これにより,本サービス・コールの発行からsta_cyc,またはista_cycが発行されるまでの間,対象周期ハンドラは,RI850V4の起動対象から除外されます。
以下に,本サービス・コールの記述例を示します。
パラメータcycidで指定された周期ハンドラの動作状態を動作状態(STA状態)から停止状態(STP状態)へと遷移させます。これにより,本サービス・コールの発行からsta_cyc,またはista_cycが発行されるまでの間,対象周期ハンドラは,RI850V4の起動対象から除外されます。
以下に,本サービス・コールの記述例を示します。
#include <kernel.h> /*標準ヘッダ・ファイルの定義*/ #include <kernel_id.h> /*システム情報ヘッダ・ファイルの定義*/ void task ( VP_INT exinf ) { ID cycid = ID_CYC1; /*変数の宣言,初期化*/ ............ ............ stp_cyc ( cycid ); /*周期ハンドラの動作停止*/ ............ ............ } |
備考 本サービス・コールでは,停止要求のキューイングが行われません。このため,すでに本サービス・コールが発行され,対象周期ハンドラの動作状態が停止状態(STP状態)へと遷移していた場合には,何も処理は行わず,エラーとしても扱いません。
- ref_cyc,iref_cyc
パラメータcycidで指定された周期ハンドラの周期ハンドラ詳細情報(現在状態,残り時間など)をパラメータpk_rcycで指定された領域に格納します。
以下に,本サービス・コールの記述例を示します。
パラメータcycidで指定された周期ハンドラの周期ハンドラ詳細情報(現在状態,残り時間など)をパラメータpk_rcycで指定された領域に格納します。
以下に,本サービス・コールの記述例を示します。
#include <kernel.h> /*標準ヘッダ・ファイルの定義*/ #include <kernel_id.h> /*システム情報ヘッダ・ファイルの定義*/ void task ( VP_INT exinf ) { ID cycid = ID_CYC1; /*変数の宣言,初期化*/ T_RCYC pk_rcyc; /*データ構造体の宣言*/ STAT cycstat; /*変数の宣言*/ RELTIM lefttim; /*変数の宣言*/ ATR cycatr; /*変数の宣言*/ RELTIM cyctim; /*変数の宣言*/ RELTIM cycphs; /*変数の宣言*/ ............ ............ ref_cyc ( cycid, &pk_rcyc ); /*周期ハンドラ詳細情報の参照*/ cycstat = pk_rcyc.cycstat; /*現在状態の獲得*/ lefttim = pk_rcyc.lefttim; /*残り時間の獲得*/ cycatr = pk_rcyc.cycatr; /*属性の獲得*/ cyctim = pk_rcyc.cyctim; /*起動周期の獲得*/ cycphs = pk_rcyc.cycphs; /*初期起動位相の獲得*/ ............ ............ } |