物理タイマ機能は、複数のハードウェアタイマが使えるシステムにおいて、タイマ割込み間隔(TTimPeriod)よりも細かい単位の時間経過を条件とした処理を行う場合に有効な機能である。
物理タイマとは、一定の時間間隔で、0から1つずつカウント値が単調増加していくハードウェアのカウンタである。カウント値が、物理タイマごとに指定された特定の値(上限値)に達すると、物理タイマ毎に指定されたハンドラ(物理タイマハンドラ)を起動するとともに、カウント値が0に戻る。
システムで利用可能なハードウェアタイマの数に応じて、複数個の物理タイマが利用できる。利用可能な物理タイマの個数は実装依存である。通常のμT-Kernelの実装では、時間管理機能を実現するためにハードウェアタイマを1つ使用するので、残りのハードウェアタイマを物理タイマ機能で使用することを想定している。
物理タイマ番号としては、1, 2, ...のように正の整数を小さい方から使う。たとえば、4個のハードウェアタイマがある場合、このうちの1個はμT-Kernelの時間管理機能で使うため、残り3個の物理タイマが利用でき、物理タイマ番号は1, 2, 3となる。
μT-Kernel/SMの物理タイマ機能において、個々の物理タイマと、それを使用するタスク等との対応を管理することはない。複数のタスク等が1つの物理タイマを共用したい場合は、アプリケーション側で排他制御などの調整を行う必要がある。
補足事項 | |
---|---|
μT-Kernelの時間管理機能では、標準システム構成情報項の「タイマ割込み間隔」(TTimPeriod)で指定された時間間隔で起動されるハンドラの中で、カーネルがアラームハンドラや周期ハンドラの起動、タイムアウトの処理など、複数の要求に対する処理を行っている。これに対して、物理タイマ機能は、ハードウェアタイマの設定、カウント値の読み出し、割込み発生といったプリミティブな機能を標準化して提供するだけのものであり、時間管理機能のように複数の要求を処理するわけではない。こういった点から、従来の時間管理機能よりも抽象度が低く、ハードウェアの階層に近い機能であるという意味で、「物理タイマ(Physical Timer)」の名称とした。 上記のような位置付けから、物理タイマ機能はできるだけシンプルで最小限の仕様とし、オーバーヘッドの少ないライブラリ関数で実現することを想定している。動的なID番号ではなく静的に固定された物理タイマ番号を使う仕様や、要求元タスクとの対応の管理や複数タスクからの要求の調整を一切行わないといった仕様も、この方針を反映したものである。 物理タイマの関数は、タイマ(カウンタ)というデバイスを操作するためのAPIを標準化したものである。ただし、タイマというデバイスでは、細かい時間経過に応じて割込みハンドラを呼び出すなど、時間関連の動作に直接関わる部分が多く、この点で他のデバイス(ストレージや通信など)よりもカーネルとの結び付きが強い。こういった理由から、タイマについては、デバイスドライバの仕様として標準化するのではなく、μT-Kernel/SMの一部として仕様を標準化し、より汎用性の高い機能として提供する。 物理タイマ機能はμT-Kernel/SMの機能なので、μT-Kernel/SMの【全般的な注意・補足事項】が適用される。 物理タイマとして利用するハードウェアタイマは、32ビット以下を想定している。そのため、カウント値や上限値を表すデータタイプは32ビットのUWを使っている。将来、64ビットの関数を追加することは可能である。 |
物理タイマ機能の有効性が高い例を以下に示す。
2500マイクロ秒毎に行うべき周期的な処理Xと、1800マイクロ秒毎に行うべき周期的な処理Yがあるとする。これを、物理タイマで効率よく実現する。
2つの物理タイマを使い、その一方は、ちょうど2500マイクロ秒毎に物理タイマハンドラが起動されるように設定する。
たとえば、物理タイマのクロック周波数が10MHzであれば、1クロックが0.1マイクロ秒(=100ナノ秒)なので、物理タイマの上限値(limit
)として24999(=25000-1)を設定し、カウント値が24999から0になる時に物理タイマハンドラが起動されるようにする。
周期的に繰り返す処理なので、StartPhysicalTimer の mode
では TA_CYC_PTMR を指定する。
この物理タイマハンドラの中で処理Xを行う。
これと同様に、もう一方の物理タイマを使って、ちょうど1800マイクロ秒毎に起動される物理タイマハンドラを設定し、この中で処理Yを行う。
μT-Kernelの時間管理機能が使うタイマ割込み間隔(TTimPeriod)は、物理タイマ機能とは無関係なので、デフォルト値(10ミリ秒)のままでよい。
物理タイマハンドラの代わりに、マイクロ秒が指定可能なμT-Kernel 3.0のシステムコール(tk_cre_cyc_u)を使って、2500マイクロ秒毎に起動される周期ハンドラを定義し、その中で処理Xを行う。また、1800マイクロ秒毎に起動される周期ハンドラを定義し、その中で処理Yを行う。
しかし、この場合には、2500マイクロ秒毎および1800マイクロ秒毎という時間がいずれも正確に処理されるように、μT-Kernelの時間管理機能が使うタイマ割込み間隔を十分に短く設定する必要がある。具体的には、2500マイクロ秒と1800マイクロ秒の公約数である100マイクロ秒のタイマ割込み間隔とすることにより、2500マイクロ秒毎の処理も、1800マイクロ秒毎の処理も、ほぼ正確な時間間隔で実現できる。
物理タイマ機能を使った(b)の方法であれば、μT-Kernelの時間管理機能は使わないので、タイマ割込み間隔はデフォルト(10ミリ秒毎)のままでよい。このほかに、物理タイマによる割込みが2500マイクロ秒毎および1500マイクロ秒毎に入り、その中から呼ばれる物理タイマハンドラの中で処理Xや処理Yを行うことになるが、これら以外に時間に関係した無駄な割込みが入ることはない。
一方、物理タイマ機能を使わない(c)の方法では、タイマ割込み間隔を短くする必要があるため、タイマ割込みの回数が増え、その分のオーバーヘッドが増加する。たとえば、10ミリ秒の間に入ってくる時間関係の割込みの回数で比較すると、(b)では時間管理機能のためのタイマ割込みが1回(=10ミリ秒÷10ミリ秒)、処理Xのための物理タイマの割込みが4回(=10ミリ秒÷2500マイクロ秒)、処理Yのための物理タイマの割込みが6回(=10ミリ秒÷1500マイクロ秒)、合計11回であるのに対し、(c)では時間管理機能のためのタイマ割込みが100回(=10ミリ秒÷100マイクロ秒)となる。時間の正確さとのトレードオフになるが、処理Xと処理Yの周期や位相の差によっては、タイマ割込み間隔をさらに短くする必要があり、もっと大きなオーバーヘッドを生じる可能性もある。このようなケースにおいて、物理タイマ機能の有効性が高い。
ただし、物理タイマ機能が有効なのは、時間に依存した処理の数が少なくて静的に決まっており、それに対して十分な数のハードウェアタイマが存在する場合である。物理タイマ機能は、文字通り、物理的なハードウェア資源の制約を受ける機能なので、ハードウェアタイマが少なければ、物理タイマ機能が十分に使えない。また、時間に依存した処理が動的に増えてくるようなケースには対応しにくい。そのようなケースでは、周期ハンドラやアラームハンドラなど従来の時間管理機能を使う方が、柔軟な対応が可能である。
マイクロ秒単位の時間管理機能と、物理タイマの機能は、用途の重複する面もあるが、上記のように特性の異なる面もあるため、ハードウェア構成やアプリケーションに応じて適切な方を利用できるとよい。物理タイマの機能は、このような理由で追加されたものである。
ptmrno
で指定された物理タイマのカウント値を0とした後、カウントを開始する。本関数の実行後は、タイマのクロック周波数の逆数の時間間隔ごとに、カウント値が1ずつ増加する。
limit
ではカウント値の上限値を指定する。カウント値が上限値に達した後、さらにクロック周波数の逆数の時間が経つと、カウント値は0に戻る。この時、この物理タイマに対する物理タイマハンドラが定義されていた場合には、そのハンドラが起動される。StartPhysicalTimer の発行により物理タイマがカウントを始めてから、次にカウント値が0になるまでの時間は、(クロック周波数の逆数の時間)×(上限値+1)である。
limit
が0の場合は E_PAR のエラーになる。
mode
では次の指定を行う。
ptmrno
で指定された物理タイマのカウントを停止する。
本関数の実行後、物理タイマのカウント値はそのまま保持される。すなわち、本関数の実行後に GetPhysicalTimerCount を実行した場合には、本関数実行直前の物理タイマのカウント値が返る。
既にカウントを停止している物理タイマに対して、本関数を実行しても、何も起こらない。エラーにもならない。
使用の終わった物理タイマを動かしたままにしておいた場合、プログラムの動作上の不都合はなくても、クロックを無駄に使い、省電力などの面で望ましくない可能性がある。そのため、使用していない物理タイマに対しては、本関数を実行し、カウントを停止しておく方が望ましい。
本関数の発行が有効なのは、StartPhysicalTimer の mode
として TA_CYC_PTMR を指定した物理タイマの使用が終了した場合である。mode
として TA_ALM_PTMR を指定した場合は、カウント値が上限値から0に戻った後で自動的にカウントを停止し、本関数を実行した後と同じ状態になる。この場合は、本関数を別途発行する必要はない。発行しても問題はないが、何も変化しない。
ptmrno
で指定された物理タイマの現在のカウント値を取得し、リターンパラメータ count
として返す。
UINT |
ptmrno
| Physical Timer Number | 物理タイマ番号 |
CONST T_DPTMR* |
pk_dptmr
| Packet to Define Physical Timer Handler | 物理タイマハンドラ定義情報 |
pk_dptmr
の内容
pk_dptmr
が NULL でない場合は、ptmrno
で指定された物理タイマに対する物理タイマハンドラを定義する。物理タイマハンドラは、タスク独立部として実行されるハンドラであり、物理タイマのカウント値が StartPhysicalTimer の limit
で指定された上限値から0に戻る時に起動される。
物理タイマハンドラのプログラム形式は、周期ハンドラやアラームハンドラと同様である。すなわち、TA_HLNG 属性が指定された場合は、高級言語対応ルーチンを経由して物理タイマハンドラが起動され、関数からのリターンによって終了する。TA_ASM 属性が指定された場合の物理タイマハンドラの形式は実装依存である。いずれの属性を指定した場合も、物理タイマハンドラの起動時のパラメータとして exinf
を渡す。
pk_dptmr
が NULL の場合は、ptmrno
で指定された物理タイマに対する物理タイマハンドラの定義を解除する。システム起動直後は、すべての物理タイマに対する物理タイマハンドラの定義が解除された状態となっている。
ptmrno
で指定された物理タイマに対する物理タイマハンドラを定義できない場合(GetPhysicalTimerConfig の pk_rptmr
->defhdr
で FALSE を返す場合)は、E_PAR のエラーになる。ptmrno
で指定された番号を持つ物理タイマが存在しない場合や、利用できない場合にも、E_PAR のエラーになる。
実装上は、物理タイマの機能を実現するための割込みハンドラを μT-Kernel/SMの内部で定義し、物理タイマのカウント値が上限値から0に戻る時に、この割込みハンドラが起動されるように設定しておく。この割込みハンドラの中では、本関数で定義された物理タイマハンドラを呼び出すとともに、物理タイマの実装に関わる処理(たとえば、TA_ALM_PTMR と TA_CYC_PTMR に関する処理など)を行う。
pk_rptmr
の内容
ptmrno
で指定された物理タイマに関するコンフィグレーション情報を取得する。
取得可能なコンフィグレーション情報には、物理タイマのクロック周波数 ptmrclk
、最大カウント値 maxcount
、物理タイマハンドラサポートの有無 defhdr
がある。
ptmrclk
は、対象物理タイマのカウントアップに使用されるクロックの周波数である。ptmrclk
が1の場合はクロックが1Hz、ptmrclk
が (232-1) の場合は (232-1)Hz、すなわち約4GHzである。1Hz未満の長いクロックの場合は、ptmrclk
が0となる。ptmrclk
が0以外の場合は、ptmrclk
の逆数の時間間隔ごとに、物理タイマのカウント値が0から上限値 limit
の値まで単調増加していく。
maxcount
は、対象物理タイマでカウント可能な最大値であり、上限値として設定可能な最大値でもある。一般的には、16ビットのタイマカウンタの場合は maxcount
が(216-1)、32ビットのタイマカウンタの場合は maxcount
が(232-1)となるが、ハードウェアやシステム構成によっては、それ以外の値をとる場合もある。
defhdr
が TRUE の場合は、対象物理タイマのカウント値が上限値に達した時に起動される物理タイマハンドラを定義できる。defhdr
が FALSE の場合は、この物理タイマに対する物理タイマハンドラを定義することはできない。
ptmrno
で指定された番号を持つ物理タイマが存在せず、利用できない場合には、E_PAR のエラーになる。物理タイマ番号は正の整数を小さい方から使っていくため、N個の物理タイマが使えるシステムでは、ptmrno
が0または(N+1)以上の場合に E_PAR のエラーになる。
本関数の「コンフィグレーション」の名称にも見られるとおり、本関数で取得する ptmrclk
, maxcount
, defhdr
の情報は、ハードウェアあるいはシステム起動時の設定により静的に固定されたものであり、システム動作中の変更がないことを想定している。しかしながら、将来あるいは実装依存の追加機能として、物理タイマのコンフィグレーション、たとえばクロック周波数を積極的に設定あるいは変更する機能を導入する可能性はあり、その場合は、本関数で取得する情報についても、システム動作中に変化する動的な情報となる。このような使い方の差異は、運用や用途に依存する部分が大きく、μT-Kernelの仕様として決めるよりは、物理タイマを使った上位のライブラリ等の中で吸収するのがよいと考えられる。したがって、μT-Kernelの仕様としては、本関数で取得するコンフィグレーション情報がシステムの動作中に変化する可能性について、特に定めないことにする。すなわち、本関数で取得した情報が途中で変化する可能性があるかどうかは、実装依存である。