第 4 章 より高度な処理を行おう 27
4.4 DaStartSamplingを使ったアナログ出力更新の解説
4.4.3 RTLinuxモジュールの動き
ここでは、RTLinuxモジュール(module3.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)
DAドライバモジュールに対して、アナログ出力更新のスタート,ストップ,データのセット,クリアを指示するRTLinuxスレッドです。
コールバック関数
(my_smp_callback)
DAドライバモジュールにてアナログ出力更新中に、何らかのイベン ト事象を検出すると呼び出されるコールバック関数です。
次に、生成された各リソースの相互関係と処理の流れを下図に示します。
ハンドラ(my_handler)
RTLinuxスレッド(my_task) FFO_COMMAND
FIFO_THRU_CMD
Linuxプロセス
ID_START ID_STOP
←周期呼び出し 周期実行
DaGetStatus関数 コマンド指示
ID_CLEAR_DA
ID_SET_DATA
DAドライバモジュール アナログ出力更新
『40ページ
4.2.2 RTLinuxモジュールの動き
』の図と比較してみてください。先のサンプルでは、アナログ出力更新の処理は、RTLinuxスレッド(my_task)にて行っていましたが、こ のサンプルでは、DAドライバモジュール内で行われます。
実際のアナログ出力更新を行っているのは、DAドライバモジュールです。
このサンプルでは、トリガを指定せずにアナログ出力更新しているので、ストップ指令を送らない限 りサンプリングを続けるようになっています。
LinuxプロセスからRTLinuxスレッドへの指示は、ハンドラ(my_handler)を経由して行われます。このサ ンプルのハンドラは、Linuxプロセスからの指示を、そのまま横流しする単純なものです。
以降では、処理順に、これらの処理を眺めてみましょう。
(195〜201行目:RT-FIFOおよびハンドラの生成と初期化)
195〜201行目では、RTLinuxモジュールおよびLinuxプロセスで使用するRT-FIFOおよび、Linuxプロセ スからの指示を受け取るハンドラを生成しています。
次に、DA製品の制御を開始するために、204行目のDaOpenEx関数を使ってオープンしています。ここ で取得するデバイス番号は、他の関数で共通して使われるため、グローバル変数g_device_noに格納さ れています。
第4引数でコールバック関数の関数ポインタ
(上の例では、CallbackFunc)を、第5引数でコールバッ
ク関数の第1引数のパラメータを渡します。例えば、第5引数に123を渡すと、上の例ではuserArg変数に123が渡されます。
(220行目:内部データバッファの設定)
DaSetBoardConfigEx関数は、ドライバが使用する内部データバッファを与えています。
第4引数で、内部データバッファのポインタ(inner_da_buff)を、第2引数でバッファのサイズ
(BUFF_SIZE)を指定しています。
★DaSetBoardConfigExの引数と、内部バッファサイズの関係
DaSetBoardConfigEx関数の第2引数は、内部データバッファのサイズを指定します。
サンプル中の、内部データバッファを確保している行と比較してみましょう。
↓内部データバッファを確保している行。
15: DA_TYPE inner_da_buff[CH_NUM * BUFF_SIZE];
↓DAドライバモジュールに、内部データバッファのサイズを指示している行。
220: ret = DaSetBoardConfigEx(g_device_no, BUFF_SIZE, 0, inner_da_buff);
第2引数で指定するサイズは、データ件数にあたります。
内部データバッファの総バイト数ではありません。
(227〜247行目:アナログ出力更新の条件設定)
DaSetSamplingConfig関数は、アナログ出力更新の条件設定を行います。
どのチャンネルをアナログ出力するか,周波数はいくらで行うのか,リピート回数はいくらか、等の 設定をここで行います。
サンプルでは、
DaGetSamplingConfig関数にて、 DAドライバモジュールが保持するデフォルトの条
件設定パラメータを取得し、これに修正を加える形式を取っています。デフォルトのパラメータは、DAドライバモジュールがオープン時に初期値として持っています。
この値は、「その製品でアナログ出力更新できる、理想的と思われる値」がセットされています。
ここでは、デフォルト値に修正を加える形式にすることで、アナログ出力更新の条件の諸設定を 簡易にしています。
(250〜253行目:アナログ出力更新用データの初期化)
250〜253行目の、 make_sampling_data関数は、アナログ出力更新用データの初期化を行うサブルー
チンを、順次呼び出しています。
サブルーチン本体は、134〜
182行目にあります。処理内容を以下に示します。
項 目 内 容
サイン波データ サイン波データを作成します。
データは、da_sin_wave_data配列に格納されます。
三角波データ 三角波データを作成します。
データは、da_triangle_wave_data配列に格納されます。
のこぎり波データ のこぎり波データを作成します。
データは、da_teeth_saw_wave_data配列に格納されます。
矩形波データ 矩形波データを作成します。
データは、da_rectangle_wave_data配列に格納されます。
(256行目:pthread_create関数)
pthread_create関数では、アナログ出力更新等の処理を実行する、 RTLinuxスレッド(my_task)を生成
しています。
(121〜129行目:ハンドラの処理)
ハンドラ(my_handler)の役目は、LinuxプロセスからRT-FIFOを経由して送られる指示を、RTLinux スレッド(my_task)に渡すことにあります。
この処理は、ほとんど定型的なものです。
RT-FIFO RT-FIFO
my_handler
ハンドラ
rtf_get rtf_put
Linuxプロセス側 RTLinuxスレッド側
(39〜108行目:RTLinuxスレッドの処理)
RTLinuxスレッド(my_task)の処理の中心は、この39〜108行のwhileループです。
ここで、
Linuxプロセスから与えられた指示によって、データのセットとクリア、アナログ出力更
新の開始と停止を行い(48〜98行の処理)、アナログ出力更新の状態をチェック(102行目の
DaGetStatus関数)しています。
処理の決定は、CMD_IDS列挙体の定数値により決定されます。
列挙定数値 内 容
ID_START
53行目のDaStartSampling関数で、DAドライバモジュールに対して、アナログ出力更新の開始を指示しています。
そ の 後 、smp_period_msメ ン バ 変 数 の 値 をms単 位 の 実 行 周 期 と し て 、 pthread_make_periodic_np関数を呼び出し、自身の実行周期の間隔を指定してい ます。
これは、アナログ出力更新の状態をチェックする間隔です。
ID_STOP
65行目のDaStopSampling関数で、DAドライバモジュールに対して、アナログ出力更新の停止を指示しています。
その後、pthread_suspend_np関数を呼び出し、自身のスレッドをスリープ状態に しています。
ID_SET_DATA
アナログ出力更新を行うデータ配列に対して、前ページで作成したデータ配列を、data_kindで指定された種類に従って設定します。(83〜95行目) DAドライバモジュールに対して、データのセットは、92行目の DaSetSamplingData関数にて行っています。
ID_CLEAR_DATA
76行目のDaClearSamplingData関数で、DAドライバモジュールに対して、内部データバッファのクリアを指示しています。
★DaStartSampling関数の同期/非同期指定について
53行目のDaStartSampling関数では、第2引数にFLAG_ASYNCを指定しています。
これは、アナログ出力更新を非同期に行うよう指示するものです。この引数を指定して関数を呼び出す と、処理が完了するのを待たず、すぐ関数の呼び出しから戻ります。
FLAG_SYNCを指定すると、アナログ出力更新を同期で行うよう指示することになります。
100件のアナログ出力更新を行うよう指示していた場合、この関数の呼び出しから戻った時、100件のサ ンプリングが終了しています。
FLAG_ASYNC を指定した場合、アナログ出力更新が終了している保証はありませんので、DaGetStatus
関数やコールバック関数を用いて、アナログ出力更新が終了したことを監視する必要があります。
サンプルでは、リピート回数(236行目のulSmplRepeatメンバ変数)を0として、永久にアナログ出力更新 を繰り返すよう指示しているので、FLAG_SYNC を指定すると、関数の呼び出しから戻らず、永遠にア ナログ出力更新を続けてしまいます。
従って、ここではFLAG_ASYNCを指定しています。
(23〜26行目:コールバック関数の処理)
アナログ出力更新完了時、DAドライバモジュールは、このコールバック関数を呼び出します。
サンプルでは、特に何も処理をしていません。お客様がサンプルに処理を付け加える時、アナロ グ出力更新終了時に、何らかの終了処理を加えたい時、このコールバック関数に処理を加えると 良いでしょう。