ネットワーク・デバイスのための EPICS デバイス・サポート

EPICS 横断化グループ   小田切 淳一





  1. 概要
  2. 全体構成
  3. サポートされるデバイス
  4. リンク・フィールドの書式
  5. デバッグのための機能
  6. デバイス・サポート開発者のために





1 概要


    近年の加速器制御システムでは、イーサネット経由で制御を行うデバイスが多用される傾向にあります。このようなデバイスは、メッセージ・ベースのトランザクションにより EPICSIOC と通信を行うことになります。このような通信は「遅い」I/O であり、 EPICS のデバイス/ドライバ・サポートは非同期で動作する必要があります。非同期式のデバイス/ドライバ・サポートは、同期式のものに比べて作りが複雑になるため、個々のデバイスのデバイス/ドライバ・サポートを別々に作成すると、その作業は膨大な量になります。また、開発後の維持の負担も大きなものになります。デバイスと送受信するメッセージの内容はデバイスに依存しますが、メッセージを送受信する仕組み自体は基本的にはデバイスに依存しないため、複雑にな低レベルのコードはデバイス間で共有し、開発の効率を上げることができます。また、共有される一つのモジュールに改善の努力を集中することで、多くのデバイスが、その恩恵を受けることができます。
    現在、ネットワーク・デバイスのための
デバイス・サポートをデバイス依存層とデバイス非依存層に分けてモジュール化する作業が、 KEK EPICS 横断化グループ、 J-PARC  制御グループ、理研の重イオン・リニアック制御グループ、および(株)三菱コントロール・ソフトウェアにより行われています。間もなく、 5 機種のデバイス( 3 機種の PLC2 機種の組込みコントローラ)がサポートされる予定です。








2 全体構成


    一つのデバイスと通信するために、以下に示す三つのモジュールを必要とします。一例として、横河社製 FA-M3 PLC の場合、かつ、モジュールをインクリメンタルに IOC 上にロードする場合のスタートアップ・スクリプトを示すと、

cd "/where/the/modules/are/"

ld < d rvNetMpf.o
ld < devNetDev.o
ld < devYewPlc.o


のようになります。
VxWorksLinking Loader がモジュール間の外部参照を解決するために、 モジュールをロードする順序は大切ですのでご注意下さい(ホスト計算機上で静的にリンクする場合には問題になりません)。はじめの二つがデバイスに依存しないモジュールで、最後がデバイス( FA-M3 )固有のモジュールです。以下、各モジュールについて、その機能を簡単に説明します。

drvNetMpf.o
    "Mpf" Message Passing Facility の略です。上位のモジュールから渡されたメッセージを通信相手に送り、もしレスポンスがあれば、それを受け取り、上位層に返す役割を担います。そのためのソケットの生成、送信タスク/受信タスクの生成、メッセージのバッファリング等を行います。このモジュールは、メッセージの内容には一切関知しません。

devNetDev.o
    このモジュールは、EPICS非同期 I/O の仕組みを隠蔽し、上位層のモジュールに簡単な関数の形で提供します。また、複数のデバイスに共通して利用される機能をライブラリとして用意する場合には、このモジュールの中に置きます。このモジュールもメッセージの内容には一切関知しません。

devYewPlc.o
    このモジュールは、横河社製 FA-M3 PLC に固有なプロトコル(コマンド/レスポンス体系)を実装するモジュール です。 FA-M3 の場合に限らず、各デバイスをサポートするモジュールは、一般に、以下の三つの 関数を実装する必要があります。
    デバイスに固有なモジュールの機能の詳細については、次節で説明します。









3 サポートされるデバイス

    現在、FA-M3 を含めた六つのデバイスをサポートするため、以下のデバイス毎のモジュール (機種/開発者/状況)の開発が進められています。
    これらのモジュールは、任意の組合せで利用することができます。例えば、

cd "/where/the/modules/are/"

ld < drvNetMpf.o
ld < devNetDev.o
ld < devYewPlc.o
ld < devOmrPlc.o
ld < devMelPlc.o


とすれば、この
IOC は、3機種の PLC と通信することができます。デバイスに依存しない最初の二つのモジュールは、他の三つのデバイス毎のモジュールに共有されて利用されます。デバイス毎のモジュール相互の間ではシンボルの参照・被参照関係が存在しないため、ロードする順序に制約はありません。





3-1  横河 PLC 用デバイス・サポート ( devYewPlc.o )

    横河社製
FA-M3 PLC をサポートするモジュールです。 FA-M3 の「パソコンリンクコマンド説明書」に記載されているプロトコルの他、未公開のプロトコルも併用しています。いずれもバイナリ・モードの場合のみのサポートです。 アスキー・モードでは使えませんのでご注意下さい。

(ネットワーク・プロトコル)
(リンク・フィールドの書式)
(デバイス・タイプ)
(標準的な機能)

(特殊な機能)
(データベース定義ファイルの書式)
device(ai,INST_IO,devAiYewPlc,"Yew Plc")
device(ao,INST_IO,devAoYewPlc,"Yew Plc")
device(bi,INST_IO,devBiYewPlc,"Yew Plc")
device(bo,INST_IO,devBoYewPlc,"Yew Plc")
device(longin,INST_IO,devLiYewPlc,"Yew Plc")
device(longout,INST_IO,devLoYewPlc,"Yew Plc")
device(mbbiDirect,INST_IO,devMbbiDirectYewPlc,"Yew Plc")
device(mbboDirect,INST_IO,devMbboDirectYewPlc,"Yew Plc")
device(waveform,INST_IO,devWfYewPlc,"Yew Plc")
device(arrayout,INST_IO,devAroYewPlc,"Yew Plc")

device(ai,INST_IO,devAiYewPlcEvent,"Yew Plc Event ")
device(ao,INST_IO,devAoYewPlcEvent,"Yew Plc Event")
device(bi,INST_IO,devBiYewPlcEvent,"Yew Plc Event")
device(bo,INST_IO,devBoYewPlcEvent,"Yew Plc Event")
device(longin,INST_IO,devLiYewPlcEvent,"Yew Plc Event")
device(longout,INST_IO,devLoYewPlcEvent,"Yew Plc Event")
device(mbbiDirect,INST_IO,devMbbiDirectYewPlcEvent,"Yew Plc Event")
device(mbboDirect,INST_IO,devMbboDirectYewPlcEvent,"Yew Plc Event")
device(waveform,INST_IO,devWfYewPlcEvent,"Yew Plc Event")
device(arrayout,INST_IO,devAroYewPlcEvent,"Yew Plc Event")


driver(drvNetMpf)




3-2 『J-PARC 仕様』 横河 PLC 用デバイス・サポートdevJkYewPlc.o )


    同じく、横河社製
FA-M3 PLC をサポートするモジュールですが、「J-PARC ルール」(間接書き込みと PLC ID の検査機能)を実装している点が devYewPlc.o と異なります。横河 PLC の標準デバイス・サポート( devYewPlc.o ) と同時に IOC にロードして使用することができます。

(ネットワーク・プロトコル)
(リンク・フィールドの書式)
(デバイス・タイプ)
(標準的な機能) (特殊な機能)
hostPlcAdd( "hostname", "192.168.210.1", 4, 0 )
"hostname":      PLC のホスト名
"192.168.210.1": PLC IP アドレス
4:                     PLC ID
0:                     オプション :登録しようとする ( IP-ID ) のセットと衝突する登録が既に存在する場合、 0:  エラーを返して拒否、 1:  既にある登録を上書き

この例では、hostname IP の紐付も同時に行っていますが、すでに VxWorkshostAdd( ) 関数でこれが行われている場合には、第一引数を 0 として下さい( "hostname" null とする)。
(データベース定義ファイルの書式)
device(ai,INST_IO,devJkAiYewPlc,"JK Yew Plc")
device(ao,INST_IO,devJkAoYewPlc,"JK Yew Plc")
device(bi,INST_IO,devJkBiYewPlc,"JK Yew Plc")
device(bo,INST_IO,devJkBoYewPlc,"JK Yew Plc")
device(longin,INST_IO,devJkLiYewPlc,"JK Yew Plc")
device(longout,INST_IO,devJkLoYewPlc,"JK Yew Plc")
device(mbbiDirect,INST_IO,devJkMbbiDirectYewPlc,"JK Yew Plc")
device(mbboDirect,INST_IO,devJkMbboDirectYewPlc,"JK Yew Plc")
device(waveform,INST_IO,devJkWfYewPlc,"JK Yew Plc")
device(arrayout,INST_IO,devJkAroYewPlc,"JK Yew Plc")
device(ai,INST_IO,devJkAiYewPlcEvent,"JK Yew Plc Event")
device(ao,INST_IO,devJkAoYewPlcEvent,"JK Yew Plc Event")
device(bi,INST_IO,devJkBiYewPlcEvent,"JK Yew Plc Event")
device(bo,INST_IO,devJkBoYewPlcEvent,"JK Yew Plc Event")
device(longin,INST_IO,devJkLiYewPlcEvent,"JK Yew Plc Event")
device(longout,INST_IO,devJkLoYewPlcEvent,"JK Yew Plc Event")
device(mbbiDirect,INST_IO,devJkMbbiDirectYewPlcEvent,"JK Yew Plc Event")
device(mbboDirect,INST_IO,devJkMbboDirectYewPlcEvent,"JK Yew Plc Event")
device(waveform,INST_IO,devJkWfYewPlcEvent,"JK Yew Plc Event")
device(arrayout,INST_IO,devJkAroYewPlcEvent,"JK Yew Plc Event")
driver(drvNetMpf)




3-3 オムロン PLC 用デバイス・サポート ( devOmrPlc.o ) [ 開発中 ]

    オムロン社製 PLC をサポートするモジュールです。 FINS プロトコルを使用しています。 アスキー・モードでは使えませんのでご注意下さい。

(ネットワーク・プロトコル)
(リンク・フィールドの書式)
(デバイス・タイプ)
(標準的な機能) (FINS ノードアドレスの登録 )
finsNodeAdd( "hostname", "192.168.210.1", 4, 0 )
"hostname":      PLC のホスト名
"192.168.210.1"
: PLC IP
4:                     PLC FINS ノード・アドレス
0:                    
オプション:登録しようとする ( IP-ID ) のセットと衝突する登録が既に存在する場合、0:  エラーを返して拒否 、1:  既にある登録を上書き 

この例では、
hostnameIP の紐付も同時に行っていますが、すでに VxWorkshostAdd( ) 関数でこれが行われている場合には、第一引数を 0 として下さい( "hostname"null とする)。
(データベース定義ファイルの書式)
device(ai,INST_IO,devAiOmrPlc,"Omr Plc")
device(ao,INST_IO,devAoOmrPlc,"Omr Plc")
device(bi,INST_IO,devBiOmrPlc,"Omr Plc")
device(bo,INST_IO,devBoOmrPlc,"Omr Plc")
device(longin,INST_IO,devLiOmrPlc,"Omr Plc")
device(longout,INST_IO,devLoOmrPlc,"Omr Plc")
device(mbbiDirect,INST_IO,devMbbiDirectOmrPlc,"Omr Plc")
device(mbboDirect,INST_IO,devMbboDirectOmrPlc,"Omr Plc")
device(waveform,INST_IO,devWfOmrPlc,"Omr Plc")

device(arrayout,INST_IO,devAroOmrPlc,"Omr Plc")

driver(drvNetMpf)




3-4 三 菱 PLC 用デバイス・サポート ( devMelPlc.o )

    三菱電機社製
MELSEC-Q シリーズをサポートするモジュールです。 MC ( Melsec Communication ) プロトコル、QnA 互換 3E フレーム(バイナリ・モード)を使用しています。 アスキー・モードでは使えませんのでご注意下さい。

(ネットワーク・プロトコル)
(リンク・フィールドの書式)
(デバイス・タイプ)
(標準的な機能)
(データベース定義ファイルの書式)
device(ai,INST_IO,devAiMelPlc,"Mel Plc")
device(ao,INST_IO,devAoMelPlc,"Mel Plc")
device(bi,INST_IO,devBiMelPlc,"Mel Plc")
device(bo,INST_IO,devBoMelPlc,"Mel Plc")
device(longin,INST_IO,devLiMelPlc,"Mel Plc")
device(longout,INST_IO,devLoMelPlc,"Mel Plc")
device(mbbiDirect,INST_IO,devMbbiDirectMelPlc,"Mel Plc")
device(mbboDirect,INST_IO,devMbboDirectMelPlc,"Mel Plc")
device(waveform,INST_IO,devWfMelPlc,"Mel Plc")
device(arrayout,INST_IO,devAroMelPlc,"Mel Plc")
driver(drvNetMpf)




3-5 EMB-LAN100 用デバイス・サポート ( devEmbLan.o ) [ 開発中 ]

    KEK で開発された組込みコントローラ(イーサネット・コントローラ・ボード)、 EMB-LAN100 をサポートするモジュールです。 コマンド/レスポンスの送受信に加えて、アテンション通知メッセージの受信をサポートします。
.
(ネットワーク・プロトコル)

(リンク・フィールドの書式)
(デバイス・タイプ)
(標準的な機能)
(特殊な機能)
(データベース定義ファイルの書式)
device(ai,INST_IO,devAiEmbLan,"Emb Lan")
device(ao,INST_IO,devAoEmbLan,"Emb Lan")
device(longin,INST_IO,devLiEmbLan,"Emb Lan")
device(longout,INST_IO,devLoEmbLan,"Emb Lan")
device(mbbiDirect,INST_IO,devMbbiDirectEmbLan,"Emb Lan")
device(mbboDirect,INST_IO,devMbboDirectEmbLan,"Emb Lan")
device(waveform,INST_IO,devWfEmbLan,"Emb Lan")
device(arrayout,INST_IO,devAroEmbLan,"Emb Lan")

device(attention,INST_IO,devAtEmbLanEvent,"Emb Lan Event")
driver(drvNetMpf)




3-6 N-DIM 用デバイス・サポート ( devNDim.o ) [ 開発中 ]

    理化学研究所で開発された組込みコントローラ(ネットワーク・デジタル I/O モジュール)、N-DIM をサポートするモジュールです。現在、開発中のモジュールの中で、唯一、アスキーでメッセージの送受信を行います。
(ネットワーク・プロトコル)
(リンク・フィールドの書式)
(デバイス・タイプ)
(標準的な機能)
(特殊な機能)
(データベース定義ファイルの書式)
device(ai,INST_IO,devAiNDim,"NDim ")
device(MbbiDirect,INST_IO,devMbbiDirectNDim,"NDim")
device(MbboDirect,INST_IO,devMbboDirectNDim,"NDim")
device(stringin,INST_IO,devSiNDim,"NDim")
device(stringout,INST_IO,devSoNdim,"NDim")

device(beamProfile,INST_IO,devBeamProfileNDim,"NDim Event")
driver(drvNetMpf)






4 リンク・フィールドの書式

    基本的にリンク・フィールドの書式は、デバイス毎に定義します。


4-1 PLC の場合


    PLC
の場合、 PLC 内のデバイスの種類、名称等に差異はあるものの、似たようなアドレス指定方式が使われています。そこで、以下のような「統一ルール」を採用することにしました。
    "@hostname(port_num):unit#type :address"
朱書きの部分は必須であり、他は省略可能です(省略した場合にはデフォルトの値が使われます)。

配列データの場合も、データ数はレコードの NELM フィールドから取得されるため、単一データの場合と同じです。
hostname 以外で用いられる数値は、0x で始まれば 16 進数、そうでなければ 10 進数と解釈されます。
field(INP,"@jhfacplc01#D1001")
field(INP,"@jhfacplc01#D:1001")
field(INP,"@jhfacplc01(0x3001)#D: 1001")
field(INP,"@jhfacplc01(0x3001):2#D: 1001")
field(INP, "@jhfacplc02(9600):01#0x82:0001")
field(INP,"@melsec01#D:1000")
field(INP,"@melsec01(5000)#0x9d :1000")



4-2 PLC 以外の場合


"@hostname(port_num)#address "

とします。
  • hostname "ホスト名"もしくは "192.168.210.1" の形で指定します。
  • address には、読み書きするレジスタのアドレスを指定します(0x で始まれば 16 進数、そうでなければ 10 進数と解釈されます)。
  • (port_num) を省略すると デバイスがデフォルトで使用する値に設定されます。
  • waveform, arrayout, attention レコードの場合は先頭アドレスを指定します(読み書きするレジスタの数はレコードの NELM フィールドから取得されるため、リンク・フィールドに指定する必要はありません)。
  •  アテンション通知を受け取る attention レコードの場合、port_num には、EMB-LAN100 側のコマンド・サーバではなく、IOC 側でメッセージを受信するサーバ・タスクが使用するポート番号を指定します。
"@hostname(port_num)#address"

とします。
  • hostname "ホスト名"もしくは "192.168.210.1" の形で指定します。
  • address には、読み書きする AI, DI / DO のアドレスを指定します(0x で始まれば 16 進数、そうでなければ 10 進数と解釈されます)。特殊命令の場合、address は、コマンド・テーブルへのインデックスとして解釈されます。
  • (port_num) を省略するとデバイスがデフォルトで使用する値に設定されます。
  • MbbiDirect / MbboDirect レコードの場合は先頭アドレスを指定します(読み書きするチャネルの数はレコードの NOBT フィールドから取得されるため、リンク・フィールドに指定する必要はありません)。
  • プロファイル・モニタからの UDP パケットを受信する beamProfile レコードの場合、port_num には、N-DIM 側のコマンド・サーバではなく、 IOC 側でメッセージを受信するサーバ・タスクが使用するポート番号を指定します。





デバッグのための機能

   
実行時のデバッグに使用する以下のコマンドについて説明します。
これらのコマンドは、 VxWorks のターミナル上で、シェル・プロンプト( -> )にタイプして使用します。




5-1 peerShowAll


    Msessage Passing Facility (MPF) は、通信相手となるデバイス(より正確にはデバイス上のサーバ)に対応して、一つの peer 構造体を生成し、相手との通信に使用される情報を格納します。 peerShowAll コマンドは、IOC 上に生成された全ての peer 構造体ID と、そのメモリ上のアドレスをプリントします。


-> peerShowAll

Peer: 0 (0x01d758d8)
value = 0 = 0x0


これは、通信相手が一つの場合の実行結果です。
ID  0 peer 構造体が、メモリ・アドレス 0x01d758d8 に割り当てられてられています。






5-2 peerShow

    peerShow コマンドは、引数に指定されたに生成された ID を持つ peer 構造体の 内容をプリントします。


-> peerShow 0
  ------------------------------
  id:                       0
  protocol:             UDP
  socket_fd:           14
  addrss_family:     0x0002
  intenet_addr:       192.168.210.131
  port_number:       0x3001
  in_transaction:     0
  num_requests:     0
  reqQ_mutex_sem_id: 0x01d3e420
  req_queued_sem_id: 0x01d3e3f8
  next_cycle_sem_id: 0x01d3e3d0
  watchdog_id:        0x01d3e3a8
  send_task_id:       0x01d756c0
  recv_task_id:       0x01d72d98
  send_msg_len:     0
  recv_msg_len:     -12
  send_buf:            0x01d7591c
  recv_buff_addr:    0x01d7691c
value = 0 = 0x0




5-3 showMsg

    showMsg コマンドは、引数に指定されたに生成された ID を持つ通信相手( peer )との間で送受信されるメッセージを表示するために使用します


-> showMsg 0
value = 0 = 0x0
=> 71 01 00 0E 26 09 00 0A 00 02 00 01 00 04 00 00 0B BC
<= F1 00 00 08 26 09 00 04 00 00 00 0E

先頭の記号  =>"
は、 IOC からデバイスに送られたコマンドが続くことを示し、 "<=" デバイスから IOC に返されたレスポンスが続くことを示します。showMsg コマンドの、第二引数に 1 を指定することで、アスキー文字列としてメッセージを表示させることもできます。
    stopMsg
コマンドにより、このメッセージを停止させることができます。引数には、 showMsg コマンドに与えた ID を指定します。

-> stopMsg 0




5-4 イベント通知型の場合のコマンド

    イベント通知型の場合についても、上で述べたコマンドに対応するものとして、 が用意されています。使い方は、上に述べた対応するコマンドに準じています。







6デバイス・サポート開発者のために


   
ここでは、デバイス・サポートを新規に作成する開発者のために有用と思われる情報を提供します。全体の概要を示すことが目的であり、完全な詳細情報を提供するものではありません。関数や引数の型、インクルード・ファイル、マクロ定義などの詳細については、既存のデバイス/ドライバ・サポートのソース・コードを参照して下さい。




6-1 重要なデータ構造体


    デバイス/ドライバ・サポートの中で使用されるデータ構造体として、以下の三つがあります。





6-2 タスク構成と動作の概要


    「2 全体構成」で述べた以下の三つの関数が、いつ、どのようなタスクのコンテキストから実行されるかに焦点を合わせて、全体の動作を概観します。

6-2-1 初期化( iocInit )段階での処理
6-2-2 レコードのプロセスに伴う処理 (コマンド/レスポンス型の場合)

    Initiation:
    Completion:

6-2-3 レコードのプロセスに伴う処理 (イベント通知型の場合)



6-3 ライブラリ関数と便利なマクロ


    新たなデバイス・サポートの実装に役立つと思われる関数とマクロを列挙します。引数や戻り値の型などの詳細については、以下のファイルを参照して下さい。
     以下に、まずデバイス・サポートの主要な機能の実装に使用する関数を列挙します。これらを核として、レコード型に特殊な処理などを含めたラッパー関数を用意することで、 DSET ( Device Support Entry Table ) メンバ関数を容易に作成することができます。
    以下五つは、汎用性があると思われるサポート関数です。
    以下の三つの関数については、多少、背景説明が必要です。まず、基本的にドライバによるコマンド/レスポンスの送受信は、レコードのプロセスに伴うトランザクションです。しかし、デバイスの初期化時の処理などでは、デバイスへのパラメータ設定などのために、レコードのプロセスからは独立してコマンド/レスポンスの送受信が行えると便利な場合があります。このような目的で使用される内部的なトランザクションを行う関数を示します。
    以下の二つはマクロです。
    以下の六つのマクロは、初期化された PEER 構造体TRANSACTION 構造体から、パラメータを取得するために使用します。いずれも TRANSACTION 構造体へのポインタを引数として渡します
以上です。