• 検索結果がありません。

周期的なデータ送受信を行うプログラムの解説

第 4 章  より高度な処理を行おう 37

4.2  周期的なデータ送受信を行うプログラムの解説

それでは、先程のプログラムの解説を行います。

プログラムの大まかな動きを、下図に示します。

Linuxプロセス RTLinuxモジュール(GP-IB I/Oモジュール)

スタート指令

ストップ指令

GP-IB機器の初期化 IFC送出,REN設定等

500ms周期

Agilent34401A

データ送信

データ受信

"MEASure:VOLTage:DC?"

データ送信

データ受信

計測した電圧値のデータ 

計測

データ送信

データ受信

“:Measure:Voltage:DC?¥r¥n”

データ送信

データ受信

計測した電圧値のデータ 

計測 データ送付

データ送付

・・

・・

周期的なデータ送受信プログラムの動作概要

RTLinuxモジュールを組み込んだ段階で、IFC送出,REN設定を行い、RTLinuxスレッド(trans_task

関数)の起動直後に、“*RST”コマンド,“*CLS”コマンドを送信して、

Agilent34401Aの初期化を行っ

ています。その後、

Linuxプロセスから指示があるまで、RTLinuxスレッドを眠らせておきます。

Linuxプロセスからスタート指示があると、 RTLinuxスレッドからAgilent34401Aに対して、電圧値

を 測 定 す る コ マ ン ド

“MEASure:VOLTage:DC?”

が 送 信 さ れ ま す 。 コ マ ン ド を 受 け 取 っ た

Agilent34401Aは現在の電圧値を計測します。その電圧値をRTLinuxスレッドで受信し、RT-FIFO

を介してLinuxプロセスにデータを送付します。これらの処理を周期的に行います。

繰り返しデータを受信し、Linuxプロセスに10回分の電圧値が送られれば、Linuxプロセスから、

RTLinuxモジュールに対してストップ指示を出します。

Agilent34401Aへのデータ送受信,Linuxプロセスへのデータ送付はRTLinuxスレッド(trans_task関

数)で行っています。

Linuxプロセスの仕事は、 Agilent34401Aへのデータ送受信を行うRTLinuxモジュールに対する周期

処理のスタート指令,ストップ指令, Agilent34401Aから受信した電圧値のデータを、RT-FIFO経由 で受け取ることです。

次に、LinuxプロセスとRTLinuxモジュールの関係を、下図に示します。

main

init̲module cleanup̲module

trans̲task my̲handler

生成

生成 指令

受信データ 破棄

破棄 カーネル空間

ユーザ空間

Linux プロセス(pt̲datadisp̲app)

RTLinux モジュール(pt̲transtask.o) FIFO̲COMMAND

FIFO̲RESULT FIFO̲THRU̲CMD

指令の転送

LinuxプロセスとRTLinuxモジュールの相関関係

LinuxプロセスからRTLinuxモジュールに対する指示は、RT-FIFOを経由して、一旦ハンドラ (my_handler)に送られ、そこから別のRT-FIFOを介してRTLinuxスレッド(trans_task)に送られます。

trans_task関数では、 RT-FIFOからの指令を受け取り、 ID_START指令ならば周期処理をスタートさ

せ、Agilent34401Aからの受信データを、RT-FIFOを経由してLinuxプロセスに対して送ります。

ID_STOP指令ならば、周期処理をストップさせます。

4.2.1 共通定義ファイルの役割

共通定義ファイル

(pt_control.h)は、 LinuxプロセスとRTLinuxモジュールのコードの内、共通で使用

する定義の内容を抜き出したものです。

共通定義ファイルでは、以下の設定を行っています。

行番号  内  容 

13〜 20行目 #define宣言>

RT-FIFOの番号の定義と、各関数で使用する定数値を指定。

24~27行目 enum宣言>

LinuxプロセスからRTLinuxモジュールに対して指令を出す際のコマンドのID値

を指定。

30〜 35行目 struct宣言>

LinuxプロセスからRTLinuxモジュールに対して指令を出す際のコマンドの構造

を指定。

ここで重要なのが、

LinuxプロセスからRTLinuxモジュールに対して指令を出すために使用される、

コマンドの構造体

(CMD_STRUCT)です。

Linuxプロセスでは、この構造体に値をセットしてRTLinuxモジュールのハンドラに渡します。

ハンドラでは、この構造体ごと受け取って、指示された内容に従って処理を行います。

Linux プロセス

RTLinux モジュール struct CMD̲STRUCT {     enum CMD̲IDS id;

    long smp̲period̲ms;

};

LinuxプロセスからRTLinuxモジュールのハンドラへのコマンドの流れ

コマンドの構造体は、RTLinuxモジュールが行う作業の指示を行うID値(idメンバ変数)と、ID値に 補足する情報(smp_period_msメンバ変数)によって構成されます。

作業の指示を行うID値の種類は、CMD_IDS列挙体にて定義されています。

id変数

内  容

ID_START smp_period_msで指定した時間間隔(ms)で、 RTLinuxモジュール内のRTLinuxスレッ

ド(trans_task)をスタートする。

ID_STOP RTLinuxスレッド(trans_task)をストップさせる。

この構造体は、後の説明にも出てきますので注意して読み進めてください。

4.2.2 RT-Linuxモジュールの動き

RTLinuxモジュール(pt_transtask.o)は、Linuxプロセスからの作業依頼に従って、ドライバを使って

データの送受信を行います。

(136〜 190行目 :RT-FIFO,RTLinuxスレッドの生成やドライバの初期化)

RTLinuxモジュールが組み込まれる時、最初に136行から始まるinit_module関数が呼び出されます。

ここでは、RT-FIFOやRTLinuxスレッド,ハンドラ等のリソースを生成しています。

項目 内  容

RT-FIFO(FIFO_COMMAND) 146行目のrtf_create関数>

Linuxプロセスからの指示を受けるためのRT-FIFOです。指

示は、ハンドラmy_handlerに渡されます。

RT-FIFO(FIFO_THRU_CMD) 151行目のrtf_create関数>

ハンドラにて、Linuxプロセスから受け取った情報を、周 期的な送受信を行うRTLinuxスレッド(trans_task)に渡すた めのRT-FIFOです。

RT-FIFO(FIFO_RESULT) 155行目のrtf_create関数>

周期的なデータ送受信を行うRTLinuxスレッド(trans_

task)で取得したデータを、Linuxプロセスに渡すための RT-FIFOです。

ハンドラ(my_handler) 147行目のrtf_create_handler関数>

Linuxプロセスからの指示を受け取るための処理の入り口

です。

RT-FIFO経由で送られた情報は、一旦このハンドラ

が受け取り、然る処理に回されます。

RTLinuxスレッド (trans_task)

189行目のpthread_create関数>

周期的なデータ送受信を行うRTLinuxスレッドです。

Linuxプロセスから送られる指示は、最終的にここに送ら

れ、パルス出力制御を行います。

158〜163行では、受信バッファの確保を行っています。

recv_buff_size変数の値に従い、vmalloc関数を用いて動的にバッファを確保しています。

recv_buff_size変数は、RECV_BUFF_DEF_SIZE(= 80)

に値が初期化されていますが、15行目の

MODULE_PARMマクロにより、 RTLinuxモジュール組み込み時にオプションパラメータを与える

ことで、受信バッファサイズを自由に設定できるようになっています。

例えばRTLinuxモジュール組み込み時、以下のように指定することで、

recv_buff_size変数の値を書

き換えることができます。

# insmod pt_transtask.o recv_buff_size=128

↑recv_buff_sizeの値を128に書き換えます。

このようにして組み込むと、159行目のメモリ確保のサイズを表すrecv_buff_size変数の値は128と なり、128バイトの受信バッファが確保されます。

166〜186行目は、 I/Oモジュールの初期化(166行目のPciGpibExInitBoard関数),IFCの送出(175行目の PciGpibExSetIfc関数),RENの設定(182行目のPciGpibExSetRen関数)を行っています。これは定型的

な処理です。

(123〜131行目:ハンドラの処理)

ハンドラ(my_handler)の役目は、LinuxプロセスからRT-FIFOを経由して送られる指示を、RTLinux スレッド(trans_task)に渡すことにあります。

この処理は、ほとんど定型的なものです。

RT‑FIFO RT‑FIFO

my̲handler

ハンドラ

rtf̲get rtf̲put

Linuxプロセス側 RTLinuxスレッド側

LinuxプロセスからRTLinuxスレッドへのデータの流れ

(49〜112行目:RTLinuxスレッド(trans_task関数)の処理)

RTLinuxスレッド(trans_task関数)は、Agilent34401Aに対するデータの送受信を行います。

58行目と61行目のsend_data関数は、Agilent34401Aに対してリセット(58行目の“*RST”コマンド送

信)とレジスタのクリア(61行目の“*CLS”コマンド送信)を行うコマンドのデータを送信していま す。

この処理により、Agilent34401Aのデータ送受信の準備を行います。

RTLinuxスレッドの処理の中心は、64〜110行目のwhileループです。

ここで、Linuxプロセスから与えられた指示によって、データ送受信の周期実行の開始と停止を 行っています。

処理の決定は、CMD_IDS列挙体の定数値により決定されます。

列挙定数値  内  容 

ID_START

78行目のpthread_make_periodic_np関数により、スレッドの周期実行を開始します。

実行周期の間隔は、smp_period_msメンバ変数により指定されます。

ID_STOP

85行目のpthread_suspend_np関数により、スレッドの周期実行を停止します。

★周期実行の周期について

ここでは、周期実行の周期を500msに設定していますが、この周期はGP-IB機器によって異なってきま す。処理の早いGP-IB機器ならばもっと早い周期でデータ送受信が行え、処理の遅いGP-IB機器ならば もっと遅い周期でしかデータ送受信が行えません。必ず、お持ちのGP-IB機器にあった周期を設定する ようにしてください。

スレッドの周期実行が開始されると、指定された周期ごとに92〜109行目のデータ送受信処理が行われ ます。

92行目のsend_data関数は、“MEASure:VOLTage:DC?"を送信して、Agilent34401Aに対して電圧を測定

するよう指示しています。

96行目のPciGpibExRecvData関数は、計測したデータを受信しています。

受信したデータは、109行目のrtf_put関数にて、RT-FIFO経由でLinuxプロセスに送られます。

4.2.3 Linux プロセスの動き

Linuxプロセス(pt_datadisp_app)は、データ送受信の開始/停止の指示と、受信したデータの受け取

りを行います。

main

RT‑FIFO(FIFO̲RESULT) RT‑FIFO(FIFO̲COMMAND)

受信データ取得

コマンド指令 RTLinux

モジュール

LinuxプロセスとRTLinuxモジュールとのRT-FIFOの関係

(29〜40行目:RT-FIFOのオープン処理)

ここでは、

open関数を使用し、 RTLinuxモジュールとデータのやり取りを行うRT-FIFOをオープン

しています。

(43〜48行目:周期的な送受信の開始)

ここでは、RTLinuxモジュールに対して、周期的な送受信を開始させるため、

CMD_STRUCT構造

体に、周期送受信処理の実行開始を意味するID_START列挙定数と、周期間隔を指定し、write関 数を使ってRT-FIFO経由で指示を送っています。

RTLinuxモジュール側では、この指示をハンドラで受けて処理を行います。

(51〜67行目:受信データの取得)

ここでは、

RTLinuxモジュール内で実行される周期的な送受信処理から、

受け取った受信データを、

select関数とread関数を使って、取得しています。

データの取得は、10回行われます。

(71〜75行目:周期的な送受信処理の停止)

ここでは、RTLinuxモジュールに対して、周期的な送受信を停止させるため、CMD_STRUCT構造体に、

周期送受信処理の実行停止を意味するID_STOP列挙定数を指定し、write関数を使ってRT-FIFO経由で 指示を送っています。

RTLinuxモジュールは、この指示を受け取った後、実行を停止します。