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