第8章 時間管理機能
本章では,RI600V4が提供している時間管理機能について解説しています。
システム時刻とは,RI600V4が時間管理を行う際に使用する“時間(単位:ミリ秒)”です。
RI600V4では,時間管理機能を実現するために,一定周期で発生する割り込み(基本クロック用タイマ割り込み)を使用します。
基本クロック用タイマ割り込みが発生した際は,RI600V4の時間に関連した処理(システム時刻の更新,タスクのタイムアウト/遅延,周期ハンドラの起動,アラーム・ハンドラの起動など)が実行されます。
基本クロック用タイマ割り込みを発生するためのハードウエアの初期化は,cfg600が出力する“ri_cmt.h”で実装されている“void _RI_init_cmt(void)”で行われます。
ブート処理関数(PowerON_Reset_PC( ))は,_RI_init_cmt()を呼び出す必要があります。
RI600V4のサービス・コールでは時間指定パラメータの単位は「ミリ秒」になっています。
基本クロック用タイマ割り込みの発生周期は1ミリ秒とするのが望ましいですが,ターゲット・システムの性質上(処理能力,必要とする時間分解能など) 1ミリ秒とすることが困難な場合があります。
基本クロック周期を指定すると1回の基本クロック用タイマ割り込みで基本クロック周期分の時間が経過したとして処理されます。
タスクの遅延は,一定の時間が経過するまでの間,自タスクをRUNNING状態からWAITING状態(時間経過待ち状態)へと遷移させ,一定の時間が経過した際には,該当タスクをWAITING状態からREADY状態へと遷移させるものです。
なお,遅延起床は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。
タイムアウトとは,タスクから発行された要求条件が即時成立しなかった場合,一定の時間が経過するまでの間,該当タスクをRUNNING状態からWAITING状態(起床待ち状態,資源獲得待ち状態,イベントフラグ待ち状態など)へと遷移させ,一定の時間が経過した際には,要求条件の成立/不成立を問わず,該当タスクをWAITING状態からREADY状態へと遷移させるものです。
なお,タイムアウトは,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。
周期ハンドラは,一定の時間ごとに周期的に起動される周期処理専用ルーチンです。
なお,RI600V4では,周期ハンドラを“タスクとは独立したもの(非タスク)”として位置づけています。このため,一定の時間が経過した際には,システム内で最高優先度を持つタスクが処理を実行中であっても,その処理は中断され,周期ハンドラに制御が移ります。
#include "kernel.h" /*標準ヘッダ・ファイルの定義*/
#include "kernel_id.h" /*cfg600が出力するヘッダ・ファイルの定義*/
void cychdr ( VP_INT exinf )
{
............
............
return; /*周期ハンドラの終了*/
}
|
備考 ハンドラ関数のプロトタイプ宣言は,cfg600がkernel_id.hに出力します。
- スタック
周期ハンドラは,システム・スタックを使用します。
- サービス・コールの発行
RI600V4では,周期ハンドラを“タスクとは独立したもの(非タスク)”として位置づけています。
周期ハンドラでは,“発行有効範囲”が“非タスク”のサービスコールを発行可能です。
備考 RI600V4では,周期ハンドラ内の処理を高速に終了させる目的から,周期ハンドラ内の処理が完了するまでの間,スケジューラの起動を遅延しています。したがって,周期ハンドラ内でディスパッチ処理(タスクのスケジューリング処理)を伴うサービス・コール(
isig_sem,
iset_flgなど)が発行された際には,キュー操作などといった処理が行われるだけであり,実際のディスパッチ処理の実行は“周期ハンドラからの復帰命令(return命令の発行)”が発行されるまで遅延され,一括して行うようにしています。
RI600V4では,周期ハンドラの静的な生成のみサポートしています。処理プログラムからサービス・コールを発行して動的に生成することはできません。
周期ハンドラの静的生成とは,システム・コンフィギュレーション・ファイルで静的API“cyclic_hand[]”を使用して周期ハンドラを定義することをいいます。
周期ハンドラの動作開始は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。
-
sta_cyc,
ista_cyc
パラメータ
cycidで指定された周期ハンドラの動作状態を停止状態(STP状態)から動作状態(STA状態)へと遷移させます。これにより,対象周期ハンドラは,RI600V4の起動対象となります。
なお,本サービス・コールの発行から1回目の起動要求が発行されるまでの相対時間間隔は,コンフィギュレーション時に対象周期ハンドラに対して
TA_PHS属性(phsatr)を指定しているか否かにより異なります。
- TA_PHS属性を指定しない場合
本サービス・コールの発行時点を基点とし,
起動周期(interval_counter)にしたがって起動タイミングが設定されます。
なお,起動タイミング設定処理については,対象周期ハンドラの動作状態に関係なく実行されます。
図8−2に,周期ハンドラの起動タイミング・イメージを示します。
#include "kernel.h" /*標準ヘッダ・ファイルの定義*/
#include "kernel_id.h" /*cfg600が出力するヘッダ・ファイルの定義*/
void task ( VP_INT exinf )
{
ID cycid = 1; /*変数の宣言,初期化*/
............
............
sta_cyc ( cycid ); /*周期ハンドラの動作開始*/
............
............
}
|
周期ハンドラの動作停止は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。
-
stp_cyc,
istp_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状態)へと遷移していた場合には,何も処理は行わず,エラーとしても扱いません。
周期ハンドラ詳細情報の参照は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。
-
ref_cyc,
iref_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; /*残り時間の獲得*/
............
............
}
|
アラーム・ハンドラは,指定した時間が経過したときに起動されるルーチンです。
なお,RI600V4では,アラーム・ハンドラを“タスクとは独立したもの(非タスク)”として位置づけています。このため,指定した時間が経過した際には,システム内で最高優先度を持つタスクが処理を実行中であっても,その処理は中断され,アラーム・ハンドラに制御が移ります。
#include "kernel.h" /*標準ヘッダ・ファイルの定義*/
#include "kernel_id.h" /*cfg600が出力するヘッダ・ファイルの定義*/
void almhdr ( VP_INT exinf )
{
............
............
return; /*アラーム・ハンドラの終了*/
}
|
備考 ハンドラ関数のプロトタイプ宣言は,cfg600がkernel_id.hに出力します。
- スタック
アラーム・ハンドラは,システム・スタックを使用します。
- サービス・コールの発行
RI600V4では,アラーム・ハンドラを“タスクとは独立したもの(非タスク)”として位置づけています。
アラーム・ハンドラでは,“発行有効範囲”が“非タスク”のサービスコールを発行可能です。
備考 RI600V4では,アラーム・ハンドラ内の処理を高速に終了させる目的から,アラーム・ハンドラ内の処理が完了するまでの間,スケジューラの起動を遅延しています。したがって,アラーム・ハンドラ内でディスパッチ処理(タスクのスケジューリング処理)を伴うサービス・コール(
isig_sem,
iset_flgなど)が発行された際には,キュー操作などといった処理が行われるだけであり,実際のディスパッチ処理の実行は“アラーム・ハンドラからの復帰命令(return命令の発行)”が発行されるまで遅延され,一括して行うようにしています。
RI600V4では,アラーム・ハンドラの静的な生成のみサポートしています。処理プログラムからサービス・コールを発行して動的に生成することはできません。
周期ハンドラの静的生成とは,システム・コンフィギュレーション・ファイルで静的API“alarm_hand[]”を使用して周期ハンドラを定義することをいいます。
アラーム・ハンドラの動作開始は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。
-
sta_alm,
ista_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 対象アラーム・ハンドラがすでに動作状態の場合でも,本サービス・コールは起動時刻を再設定します。以前の起動時刻の設定は無効となります。
アラーム・ハンドラの動作停止は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。
-
stp_alm,
istp_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状態)へと遷移していた場合には,何も処理は行わず,エラーとしても扱いません。
アラーム・ハンドラ詳細情報の参照は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。
-
ref_alm,
iref_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; /*残り時間の獲得*/
............
............
}
|
システム時刻の設定は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。
なお,システム時刻を変更しても,それ以前に行われた時間管理要求(タスクのタイムアウト,dly_tsk によるタスクの遅延,周期ハンドラ,およびアラーム・ハンドラ)が発生する実時刻は変化しません。
-
set_tim,
iset_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 ); /*システム時刻の設定*/
............
............
}
|
システム時刻の参照は,以下に示したサービス・コールを処理プログラムから発行することにより実現されます。
-
get_tim,
iget_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ビット)の獲得*/
............
............
}
|
cfg600は,基本クロック用タイマ初期化関数(void _RI_init_cmt(void))が記述されたri_cmt.hを出力します。