第 4 章 より高度な処理を行おう 27
4.2 DaOutputDAExを使ったアナログ出力更新の解説
4.2.2 RTLinuxモジュールの動き
ここでは、RTLinuxモジュール(module2.o)の動きに注目して見てみましょう。
RTLinuxモジュールでは、周期サンプリングを実現するために、init_module関数内で、幾つか
リソースを生成しています。それを下表に示します。項 目 内 容
RT-FIFO(FIFO_COMMAND) Linuxプロセスからの指示を受けるためのRT-FIFOです。指示
は、ハンドラmy_handlerに渡されます。
RT-FIFO(FIFO_THRU_CMD)
ハンドラにて、Linuxプロセスから受け取った情報を、アナログ出力更新等の処理を実現するRTLinuxスレッド(my_task)に 渡すためのRT-FIFOです。
ハンドラ(my_handler) Linuxプロセスからの指示を受け取るための処理の入り口で
す。
RT-FIFO経由で送られた情報は、一旦このハンドラが受け
取り、然る処理に回されます。
RTLinuxスレッド(my_task)
アナログ出力更新等の処理を実現するRTLinuxスレッドです。Linuxプロセスから送られる指示は、最終的にここに送られ、
アナログ出力更新を実現します。
次に、生成された各リソースの相互関係と処理の流れを下図に示します。
ハンドラ(my_handler)
RTLinuxスレッド(my_task) FFO_COMMAND
FIFO_THRU_CMD
Linuxプロセス
ID_START ID_STOP
←周期呼び出し 周期実行
DaOutputDAEx関数 コマンド指示
ID_CLEAR_DA
ID_SET_DATA
配列データ
RTLinuxモジュール内で中心となるのは、アナログ出力更新を実現するRTLinuxスレッド(my_task)
です。このスレッドは、Linuxプロセスからの指令により、スタート(ID_START)、ストップ(ID_STOP)、配列データのセット(ID_SET_DATA),配列データのクリア(ID_CLEAR_DATA)を行い
ます。スタート後の実行中、スレッドは周期ごとに1件のDA出力を行います。出力するデータは、ID_SET_DATAにてセットされます。
LinuxプロセスからRTLinuxスレッドへの指示は、ハンドラ(my_handler)を経由して行われます。こ
のサンプルのハンドラは、Linuxプロセスからの指示を、そのまま横流しする単純なものです。以降では、処理順にこれらの処理を眺めてみましょう。
(173〜179行目:RT-FIFOおよびハンドラの生成と初期化)
173〜179行目では、 RTLinuxモジュールおよびLinuxプロセスで使用するRT-FIFOおよび、 Linuxプ
ロセスからの指示を受け取るハンドラを生成しています。
次に、DA製品の制御を開始するために、182行目のDaOpenEx関数を使ってオープンしています。
ここで取得するデバイス番号は、他の関数で共通して使われるため、グローバル変数g_device_no に格納されています。
(195行目:DaSetOutputDAEx関数)
『22ページ
3.3 1件のDA出力を行う』では、 1件のDA出力を行うために、 DaOutputDA関数を使
用していました。ここでは、設定を行うDaSetOutputDAEx関数と、DA出力のみを行うDaOutputDAEx関数のペアを 使用しています。
★何故、DaSetOutputDAEx関数を使うのか?
DaSetOutputDAEx関数とDaOutputDAEx関数の組み合わせは、DaOutputDA関数と、ほぼ同じ処理内容で す。
これは、アナログ出力更新実行時の、1 件の DA 出力の処理負荷を少しでも減らすために用意されてい ます。
つまり、DaSetOutputDAEx関数で、1件のDA出力の処理を行う際に必要な前処理を行い、DaOutputDAEx 関数の呼び出しでは、DA出力の処理のみを行うようデザインされています。
(205〜208行目:アナログ出力更新用データの初期化)
205〜208行目の、 make_sampling_data関数は、アナログ出力更新用データの初期化を行うサブルー
チンを、順次呼び出しています。
サブルーチン本体は、112〜
160行目にあります。処理内容を以下に示します。
項 目 内 容
サイン波データ サイン波データを作成します。
データは、da_sin_wave_data配列に格納されます。
三角波データ 三角波データを作成します。
(211行目:pthread_create関数)
pthread_create関数では、アナログ出力更新等の処理を実行する、 RTLinuxスレッド(my_task)を生成
しています。
(99〜107行目:ハンドラの処理)
ハンドラ(my_handler)の役目は、LinuxプロセスからRT-FIFOを経由して送られる指示を、RTLinux スレッド(my_task)に渡すことにあります。
この処理は、ほとんど定型的なものです。
RT-FIFO RT-FIFO
my_handler
ハンドラ
rtf_get rtf_put
Linuxプロセス側 RTLinuxスレッド側
(34〜86行目:RTLinuxスレッドの処理)
RTLinuxスレッド(my_task)の処理の中心は、この34〜86行のwhileループです。
ここで、Linuxプロセスから与えられた指示によって、データのセット,クリア,アナログ出力更新 の開始と停止を行い(43〜69行の処理)、配列からデータを取り出して(73行目)、周期実行ごとに1 件のDA出力を行っています(76行目のDaOutputDAEx関数)。
処理の決定は、CMD_IDS列挙体の定数値により決定されます。
列挙定数値 内 容
ID_START
smp_period_msメンバ変数の値をms単位の実行周期として、pthread_make_periodic_np関数を呼び出し、自身の実行周期の間隔を指定してい ます。
ID_STOP
pthread_suspend_np関数を呼び出し、自身のスレッドをスリープ状態にしています。
ID_SET_DATA
アナログ出力更新を行うデータ配列に対して、前ページで作成したデータ配列を、data_kindで指定された種類に従って設定します。(59〜66行目)
ID_CLEAR_DATA
アナログ出力更新を行うデータ配列をクリアします。1件のDA出力を行う際に使用するデータ配列は、15行目のda_data配列変数です。
データ配列からの取り出しは、73行目のDA_PTR関数マクロから取り出したポインタにより求め ています。
データ配列のフォーマットは、以下のようになっており、これは、
DAドライバモジュールがアナ
ログ出力更新用に定義するデータバッファのフォーマットと同一です。CH1データ
CH2データ
CH1データ
CH2データ
CH1データ
CH2データ
CH1データ
CH2データ
CH1データ
CH2データ
1件目のデータ
2件目のデータ
3件目のデータ
4件目のデータ
5件目のデータ データ配列の先頭
DA_PTR関数マクロは、sample2.hの22行目で定義しています。これは、以下の引数を与えることで、
データ配列に対する参照(ポインタ)を求められます。
第1引数 データ配列の先頭ポインタ。
第2引数 データ配列にアクセスする件数の指定。
第3引数 データ配列にアクセスするチャンネル番号の指定。
こうすることで、同じようなコードを記述する無駄を省いています。
周期実行の間隔は、smp_period_msの値により決定されます。
例えばここで5の値が指定されると、