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
© Copyright 2025 ExpyDoc