WF dev.sup for Joerger vdacm device

Getting Started with EPICS
Lecture Series
Writing Device Support
Eric Norum
November 16, 2004
Argonne National Laboratory
Office of Science
U.S. Department of Energy
A U.S. Department of Energy
Office of Science Laboratory
Operated by The University of Chicago
Writing Device Support – 概観
• EPICSデバイス・サポート開発に必要な概念の概要
• 「石器時代」の方法を示す例を提示する。
• Asynパッケージはデバイス・サポート開発を簡単にするフレームワーク
を提供する。
- ここで示した概念はそこでも有効である。
Pioneering
Science and
Technology
Office of Science
U.S. Department
of Energy
Writing Device Support – アウトライン
•
•
•
•
•
•
•
•
デバイス・サポートとは?
.dbd ファイルの内容
ドライバー DSET(Device Support Entry Table)
デバイスのアドレス
サポート関数
割り込みの利用
非同期入出力
コールバック(呼び返し)関数
Pioneering
Science and
Technology
Office of Science
U.S. Department
of Energy
EPICS Software Architecture
Client Tool
CA Client
CA Server
DB Common
Record Support
Device Support
Driver Support
IO
Plant
Pioneering
Science and
Technology
Optional
Office of Science
U.S. Department
of Energy
デバイス・サポートとは?
• EPICS レコードとハードウエアの界面(インタフェース)である
• レコードサポートが呼び出す一組の関数群
•
•
- レコード型によって要求される関数の組が決められる。
- これらの関数はすべてのレコード内のフィールドに自由に読み書きを
実行出来る。
レコードが同期あるいは非同期で動作するかを決定付ける。
レコードの入出力を実行する。
- 割り込みの取り扱いの仕組みを提供する。
Pioneering
Science and
Technology
Office of Science
U.S. Department
of Energy
なぜデバイス・サポートを使うのか。
• デバイス・サポートを導入する変わりに、それぞれのハードウエアに異な
•
ったレコード型を導入することも可能であった。それぞれのレコードを導
入することで、利用可能なすべての機能を利用するフィールドを追加す
ることも出来た。
デバイス・サポートの分離による利点:
- ユーザはデバイス毎に新しいレコード型の使い方を学ぶ必要がなく
なる。
- モジュラー化を増強する。
- 入出力ハードウエアの変更による影響を最小化できる。
- デバイス・サポートはレコードサポートより簡単である。
- ハードウエアと直接入出力を行うコードをEPICS レコードから分
離できる。
• 特別用途のレコードは必要があれば導入できる。
- "本当に、本当に、本当に"必要ならと言うことだ。
- 既存のレコードでほとんどの応用に対応出来る。
Pioneering
Science and
Technology
Office of Science
U.S. Department
of Energy
レコードはどのようにしてデバイス・サポートを見つけ
るか。
.dbd ファイルの‘device’ 文を通じて
Pioneering
Science and
Technology
Office of Science
U.S. Department
of Energy
.dbd ファイルの内容
• データベースは.dbdファイル中の次の記述からデバイスサポートを見
•
•
つける。
device(recType,addrType,dsetName,”dtypeName”)
addrType は次のうちの一つである。
AB_IO
BITBUS_IO
CAMAC_IO GPIB_IO
INST_IO
RF_IO
VME_IO
VXI_IO
dsetName はCプログラム中の Device Support Entry Table (DSET)の名前
である。
• コンベンションとしてこの名前はレコード型とハードウエアタイプを指し示して
いる。:
device(ai, GPIB_IO, devAidg535, "dg535")
device(bi, VME_IO, devBiXy240, "XYCOM-240")
Pioneering
Science and
Technology
Office of Science
U.S. Department
of Energy
DSET
• デバイスサポートを構成する関数へのポインタから成るCの構造体であ
•
•
•
る。
内容はレコード型に依存している。
それぞれのデバイスサポートはそれが持つ関数へのポインタをもつ
DSETを定義する。
DSET 構造体の定義の一例を示す。 :
struct dset {
long number;
long (*report)(int level);
long (*initialize)(int pass);
long (*initRecord)(struct … *precord);
long (*getIoIntInfo)(…);
… read/write and other routines as required
};
• number はすべてのDSETに共通で、構造体中のポインタの数をしめす
。(通常は5または6である。)
• 必須でない関数が未実装であればNULLが与えられる。
• DSET 構造体と 関数は通常staticと宣言される。
Pioneering
Science and
Technology
Office of Science
U.S. Department
of Energy
The DSET – 初期化ルーチン
long initialize(int pass);
• デバイスサポートを初期化する。
• 初期化ルーチンは必須ではない。
• 起動時に一度だけ必要な処理に使われる。:
•
- バックグラウンドタスクの起動
- 共有テーブルの生成
このルーチンはiocInitに2度呼ばれる。:
- pass=0 – レコードの初期化前
- 通常ハードウエアにはアクセスしない。まだハードウエアアドレス
などはこの段階で未定であるからである。
- pass=1 – すべてのレコードの初期化の後
- 起動処理の最終段階として呼ばれる。すべてのデバイスアドレス
は既知となっている。
Pioneering
Science and
Technology
Office of Science
U.S. Department
of Energy
The DSET – initRecord
long initRecord(struct … *precord);
• DTYPEが一致するすべてのレコード毎にiocInit()内から呼び出される。
• 必須のルーチンでは無いが、提供されるのが普通である。
• ルーチンはしばしば、
- INPあるいはOUTフィールドの適合をチェックする。
- アドレスが指示するハードウエアが存在することを確認する。
- レコードにデバイス固有の記憶領域を割り当てる。
- すべてのレコードはvoid *dpvt ポインタをこの為似用意してい
る。(device private)
- デバイスレジスタの初期化
- 物理値(Engineering Unit)との変換に必要なレコード特有のフィール
ドをセットする。
Pioneering
Science and
Technology
Office of Science
U.S. Department
of Energy
The DSET – initRecord – Device Addresses
• .dbd ファイル中のデバイス・サポート定義
device(recType,addrType,dset,"name")
• addrType はアドレスリンクに使われるタイプを指定する。たといえば:
device(bo,VME_IO,devBoXy240,"Xycom XY240")
は pbo->out
フィールドを:
- pbo->out.type = VME_IO
- に設定し、デバイスサポートが pbo->out.value.vmeio を使うことをしていす
る。out.value.vmeioは次の構造体である。
struct vmeio {
short card;
short signal;
char *parm;
};
• すべてのaddrTypeはIOC Application Developer’s Guideに記述さ
れている。
Pioneering
Science and
Technology
Office of Science
U.S. Department
of Energy
The DSET – report
long report(int level);
• dbior shell commandによって呼び出される。
• デバイスの現在の状態、入出力統計等を印刷する。
• 出力量はlevel引数で制御される。
- level=0 – 接続されたハードゥエアのリストを出力する。1行につき
一つのデバイス。
- level>0 – 詳細な情報あるいはlevel=0とは別の種類の情報を出
力する。
Pioneering
Science and
Technology
Office of Science
U.S. Department
of Energy
The DSET – read/write
long read(struct … *precord);
long write(struct … *precord);
• レコードがプロセスされる際に呼び出される。
• 入出力動作を実行(あるいは起動)する:
- 同期入力
- ハードゥエアからの値を precord->rvalにコピー
- 0 を返す(読み出し成功の場合)
- 同期出力
- precord->rvalの値をハードウエアに出力する。
- 0 を返す(書き込み成功の場合)
Pioneering
Science and
Technology
Office of Science
U.S. Department
of Energy
A simple example (vxWorks or RTEMS)
#include <recGbl.h>
#include <devSup.h>
#include <devLib.h>
#include <biRecord.h>
#include <epicsExport.h>
static long initRecord(struct biRecord *prec){
char *pbyte, dummy;
if ((prec->inp.type != VME_IO) ||
(prec->inp.value.vmeio.signal < 0) || (prec->inp.value.vmeio.signal > 7)) {
recGblRecordError(S_dev_badInpType, (void *)prec, "devBiFirst: Bad INP");
return -1;
}
if (devRegisterAddress("devBiFirst", atVMEA16, prec->inp.value.vmeio.card, 0x1,
&pbyte) != 0) {
recGblRecordError(S_dev_badCard, (void *)prec, "devBiFirst: Bad VME
address");
return -1;
}
if (devReadProbe(1, pbyte, &dummy) < 0) {
recGblRecordError(S_dev_badCard, (void *)prec, "devBiFirst: Nothing there!");
return -1;
}
prec->dpvt = pbyte;
prec->mask = 1 << prec->inp.value.vmeio.signal;
return 0;
}Pioneering
Office of Science
Science and
Technology
U.S. Department
of Energy
A simple example (vxWorks or RTEMS)
static long read(struct biRecord *prec)
{
volatile char *pbyte = (volatile char *)prec->dpvt;
prec->rval = *pbyte;
return 0;
}
static struct {
long number;
long (*report)(int);
long (*initialize)(int);
long (*initRecord)(struct biRecord *);
long (*getIoIntInfo)();
long (*read)(struct biRecord *);
} devBiFirst = {
5, NULL, NULL, initRecord, NULL, read
};
epicsExportAddress(dset,devBiFirst);
Pioneering
Science and
Technology
Office of Science
U.S. Department
of Energy
A simple example – device support .dbd file
これらのサンプルのデバイス・サポートに対応する .dbd ファイルのデバイ
ス定義文は、次のような物になる。:
device(bi, VME_IO, devBiFirst, “simpleInput”)
Pioneering
Science and
Technology
Office of Science
U.S. Department
of Energy
A simple example – application .db file
このデバイスサポートを利用するアプリケーションの.dbファイルは次のよう
なものになる。
record(bi, "$(P):statusBit")
{
field(DESC, "Simple example binary input")
field(DTYP, "simpleInput")
field(INP, "#C$(C) S$(S)")
}
Pioneering
Science and
Technology
Office of Science
U.S. Department
of Energy
A simple example – application startup script
例のデバイス・サポートを使うIOCアプリケーションの起動コマンド(st.cmd)
には以下のようなデータベース定義コマンドが現れる。
dbLoadRecords("db/example.db","P=test,C=0x1E0,S=0")
これは次のデータベースに展開される。
record(bi, "test:statusBit")
{
field(DESC, "Simple example binary input")
field(DTYP, "simpleInput")
field(INP, "#C0x1E0 S0")
}
Pioneering
Science and
Technology
Office of Science
U.S. Department
of Energy
便利なファシリティ
• ANSI C 関数 (OSベンダが提供しない関数についてのEPICS headers
)
•
•
- epicsStdio.h – printf, sscanf, epicsSnprintf
- epicsString.h – strcpy, memcpy, epicsStrDup
- epicsStdlib.h – getenv, abs, epicsScanDouble
OS-非依存ハードウエアアクセス (devLib.h)
- Bus address  Local address conversion
- Interrupt control
- Bus probing
EPICS 関数
- epicsEvent.h – 同期セマファの処理
- epicsMutex.h – 相互排他(mutual-exclusion) セマファ
- epicsThread.h – マルチスレッドサポート
- recGbl.h – レコードのエラーおよびアラームの通知
Pioneering
Science and
Technology
Office of Science
U.S. Department
of Energy
デバイスの割り込み
• vxWorks/RTEMS の割り込みハンドラーはC 言語で記述される。
• VME割り込みは二つのパラメータをもつ
割り込みレベル (1-7, しかし level 7を使ってはいけない) – ボード
上のジャンパやDIPスイッチで切り替えるのが普通。
- 割り込みベクトル (0-255, <64 reserved on MC680x0) –ボード上
のレジスタに設定するのが普通
OS初期化には二つの関数呼び出しが必要。
1. 割り込みハンドラをベクターに接続
-
•
devConnectInterruptVME(unsigned vectorNumber,
void (*pFunction)(void *),void *parameter);
2. VMEから CPUへの割り込みを許可する
devEnableInterruptLevelVME (unsigned level);
Pioneering
Science and
Technology
Office of Science
U.S. Department
of Energy
I/O 割り込みによるレコード処理
• ハードウエア割り込みが生じたとき、レコードが処理される。
• 一般にはデバイス・サポートとハードウエアに依存する。
•
•
•
•
- チャンネル毎の割り込みかカード後との割り込みか?
#include <dbScan.h> :追加的な宣言のために必要。
局所変数を初期化するために各割り込む源毎にscanIoInit() 関数を呼
び出す。
scanIoInit(&ioscanpvt);
DSET must provide a getIoIntInfo routine to specify the
interrupt source associated with a record – a single interrupt
source can be associated with more than one record
Interrupt handler calls scanIoRequest with the ‘ioscanpvt’
value for that source – this is one of the very few routines
which may be called from an interrupt handler
Pioneering
Science and
Technology
Office of Science
U.S. Department
of Energy
The DSET – getIoIntInfo
long getIoIntInfo(int cmd, struct … *precord,
IOSCANPVT *ppvt);
• Set *ppvt to the value of the IOSCANPVT variable for the
interrupt source to be associated with this record
• Must have already called scanIoInit to initialize the
IOSCANPVT variable
• Return 0 to indicate success or non-zero to indicate failure – in
which case the record SCAN field will be set to Passive
• Routine is called with
- (cmd=0) when record is set to SCAN=I/O Intr
- (cmd=1) when record SCAN field is set to any other value
Pioneering
Science and
Technology
Office of Science
U.S. Department
of Energy
The DSET – specialLinconv
long specialLinconv(struct … *precord, int after);
• Analog input (ai) and output (ao) record DSETs include this
•
sixth routine
Called just before (after=0) and just after (after=1) the value
of the LINR, EGUL or EGUF fields changes
• “Before” usually does nothing
• “After” recalculates ESLO from EGUL/EGUF and the hardware
•
range
If record LINR field is Linear ai record processing will
compute val as
val = ((rval + roff) * aslo + aoff) * eslo + eoff
Ao record processing is similar, but in reverse
Pioneering
Science and
Technology
Office of Science
U.S. Department
of Energy
組み込みのEPICS IO アドレス形式
•以下のIO typeとそのアドレス形式がEPICSには用
意されている
•デバイスサポートは.dbdファイルの記述によって以下
のIOタイプのいずれかに関連づけられている
•device(waveform, VME_IO, devWfLT364,
"LT364")
IO type
GPIB
BITBUS
VME
CAMAC
VXI
INST
Pioneering
Science and
Technology
@
link
link
card
branch
flag
station
node
port
signal
crate slot
frame slot
signal
addr
la
func
signal
parameter
paramter
parameter
parameter
parameter
parameter
Office of Science
U.S. Department
of Energy
VME_IO
• アドレスの例:
•
•
- field(OUT,"#C0 S0 @L")
アドレスを保存する構造体
- /* structure of a VME io channel */
- struct vmeio {
short card;
short signal;
char *parm;
- };
レコード構造体のINP, OUTなどのフィールドはこの構造体になる。
Pioneering
Science and
Technology
Office of Science
U.S. Department
of Energy
INST_IO:その他のアドレス指定 方式
/* from $EPICS/base/include */
#include <link.h>
•
•
•
組み込みのIOタイプにあわないアドレスの方式にはINST_IOが使われる。
パラメータ部分をデバイスサポートが解析する。
- field(INP,"@$(HOST)$(DOMAIN) public TCP-MIB::tcpCurrEstab.0
Gauge32: 11")
リンク構造体
- /* structure of an instrument io link */
- struct instio {
char *string;
/* the cat of location. signal.parameter */
- };
Pioneering
Science and
Technology
Office of Science
U.S. Department
of Energy
OSI ライブラリー
•
EPICSのサポートするOS間の違いを吸収し、EPICS のソースコードを非依存と
するためにOSIライブラリー層が定義された。
• libCom/osiにそれらのライブラリーが定義されている。
• os依存のコードはlibCom/osi/osに収められている。
• osi/
- epics*.h
• *
.cpp - A few generic c++ implementations
- os/
- Linux/
- Darwin/
- RTEMS/
- WIN32/
- cygwin32/
- default/
- posix/
- solaris/
Office of Science
Pioneering
- vxWorks/
U.S. Department
Science and
Technology
of Energy
OSIライブラリーのAPI
•
•
•
•
•
•
•
•
•
•
•
•
•
epicsEvent
epicsFindSymbol
epicsInterrupt
epicsMath
epicsMessageQueue
epicsMutex
epicsStdlib
epicsStdio
epicsStdioRedirect
epicsThread
epicsTime
osiSock.h
osiProcess
Pioneering
Science and
Technology
•
•
Application Developer Guideを
参照の事。
VME バスアクセスのOSI化(
vxWorks/RTEMS/Linux)はまだ完
了していない(?)
Office of Science
U.S. Department
of Energy
Asynchronous I/O
• Device support must not wait for slow I/O
• Hardware read/write operations which take “a long time” to
•
complete must use asynchronous record processing
- TI/O  100 s
– definitely “a long time”
- TI/O  10 s
– definitely “not a long time”
- 10 s < TI/O < 100 s – ???
If device does not provide a completion interrupt a “worker”
thread can be created to perform the I/O
- this technique is used for Ethernet-attached devices
Pioneering
Science and
Technology
Office of Science
U.S. Department
of Energy
Asynchronous I/O – read/write operation
• Check value of precord->pact and if zero:
•
- Set precord->pact to 1
- Start the I/O operation
- write hardware or send message to worker thread
- Return 0
When operation completes run the following code from a
thread (i.e. NOT from an interrupt handler)
struct rset *prset = (struct rset *)precord->rset;
dbScanLock(precord);
(*prset->process)(precord);
dbScanUnlock(precord);
• The record’s process routine will call the device
support read/write routine – with precord->pact=1
- Complete the I/O, set rval, etc.
Pioneering
Science and
Technology
Office of Science
U.S. Department
of Energy
Asynchronous I/O – callbacks
• An interrupt handler must not call a record’s process routine
directly
Use the callback system (callback.h) to do this
•
• Declare a callback variable
CALLBACK myCallback;
• Issue the following from the interrupt handler
callbackRequestProcessCallback(&myCallBack,
priorityLow, precord);
• This queues a request to a callback handler thread which will
•
perform the lock/process/unlock operations shown on the
previous page
There are three callback handler threads
- With priorities Low, Medium and High
Pioneering
Science and
Technology
Office of Science
U.S. Department
of Energy
Asynchronous I/O – ASYN
• This should be your first consideration for new device support
• It provides a powerful, flexible framework for writing device
•
support for
- Message-based asynchronous devices
- Register-based synchronous devices
Will be completely described in a subsequent lecture
Pioneering
Science and
Technology
Office of Science
U.S. Department
of Energy