目次
PVME-501/02は、インターニックス株式会社殿が開発したVMEバス対応の40ビット入力、40ビット出力のデジタルI/Oボードです。入力、出力は高速(?)フォトカップラで絶縁してあります。
これから紹介するデバイスサポートは、このボードをただのI/OボードとしてEPICSで使うためにtobiyamaが書いたものです。割り込み等の機能には対応していません。
PVME-501/02を操作する上で必要な各レジスタについて紹介します。詳しくはPVME-501/02のユーザーズ・マニュアルをご覧下さい。ベースアドレス(BASE_IO)は省略しますが、あるアドレス(例えば0x01)が書いてある場合、BASE_IO+0x01だと思って見て下さい。特に断らない限り、unsigned charアクセスをしていると思って下さい。
- bim_cntrl_reg0(0x01)
ユーザータイマー割り込みの設定。使用しないので省略。0x00に設定。
- bim_cntrl_reg1(0x03)
パターンマッチ割り込み1の設定。使用しないので省略。0x00に設定。
- bim_cntrl_reg1(0x05)
パターンマッチ割り込み2の設定。使用しないので省略。0x00に設定。
- bim_cntrl_reg1(0x07)
外部トリガ割り込みの設定。使用しないので省略。0x00に設定。
- bim_vector_reg0(0x09)
割り込みベクター設定。使用しない。
- bim_vector_reg1(0x0B)
割り込みベクター設定。使用しない。
- bim_vector_reg2(0x0D)
割り込みベクター設定。使用しない。
- bim_vector_reg3(0x0F)
割り込みベクター設定。使用しない。
- timer_counter_0(0x11)
クロックタイマーにカウント値を設定するレジスタ。省略。
- timer_counter_1(0x13)
パターンマッチ用タイマーにカウント値を設定するレジスタ。省略。
- timer_counter_2(0x15)
ユーザータイマーにカウント値を設定するレジスタ。省略。
- timer_contrl_word(0x17)
timer_counter 0、1、2の初期設定を行うレジスタ。省略。
- timer_gate_0(0x19)
カウンター#0の出力設定レジスタ。0x00で出力禁止なので、0x00を設定。
- timer_gate_0(0x1B)
カウンター#1の出力設定レジスタ。0x00で出力禁止なので、0x00を設定。
- timer_gate_0(0x1D)
カウンター#2の出力設定レジスタ。0x00で出力禁止なので、0x00を設定。
- io_port_directionA(0x1F)
port A,B,C,D,Jの方向を設定する。方向は使用するメザニンボードによって決まっているので、正しく設定すること。
Bit | I/O | 機能
|
---|
| |
|
| |
|
| |
|
D4 | O | J(1が出力、0が入力)
|
D3 | O | D(1が出力、0が入力)
|
D2 | O | C(1が出力、0が入力)
|
D1 | O | B(1が出力、0が入力)
|
D0 | O | A(1が出力、0が入力)
|
MDL-02カードはA,B,C,D,Jは入力なので、0x00を設定。
- io_port_directionB(0x21)
port E,F,G,H,Kの方向を設定する。方向は使用するメザニンボードによって決まっているので、正しく設定すること。
Bit | I/O | 機能
|
---|
| |
|
| |
|
| |
|
D4 | O | K(1が出力、0が入力)
|
D3 | O | H(1が出力、0が入力)
|
D2 | O | G(1が出力、0が入力)
|
D1 | O | F(1が出力、0が入力)
|
D0 | O | E(1が出力、0が入力)
|
MDL-02カードはE,F,G,H,Kは出力なので、0x1Fを設定。
- compare pattern condition(0x23)
パターンマッチの比較条件を設定。使用しないので0x00を設定。
- pattern c set reg(0x25)
port c とのパターンマッチさせるデータを設定するレジスタ。使用しない。
- pattern d set reg(0x27)
port d とのパターンマッチさせるデータを設定するレジスタ。使用しない。
- pattern match out(0x29)
パターンマッチのイコール信号の出力を設定するレジスタ。使用しないので0x00を設定。
- port_enable_A(0x2B)
Bit | I/O | function
|
---|
| |
|
| |
|
| |
|
D4 | I | J(1でenable、0でdisable)
|
D3 | I | D
|
D2 | I | C
|
D1 | I | B
|
D0 | I | A
|
0x1fを設定。(全てenable)
- port_enable_B(0x2D)
Bit | I/O | function
|
---|
| |
|
| |
|
| |
|
D4 | I | K(1でenable、0でdisable)
|
D3 | I | H
|
D2 | I | G
|
D1 | I | F
|
D0 | I | E
|
0x1fを設定。(全てenable)
- port J Data reg(0x3D)
Bit | I/O | function
|
---|
D7 | I/O |
|
D6 | I/O |
|
D5 | I/O |
|
D4 | I/O |
|
D3 | I/O |
|
D2 | I/O |
|
D1 | I/O |
|
D0 | I/O |
|
port Jデータをread/writeするレジスタです。
- port K Data reg(0x3F)
Bit | I/O | function
|
---|
D7 | I/O |
|
D6 | I/O |
|
D5 | I/O |
|
D4 | I/O |
|
D3 | I/O |
|
D2 | I/O |
|
D1 | I/O |
|
D0 | I/O |
|
port Kデータをread/writeするレジスタです。
- port A Data reg(0x40)
Bit | I/O | function
|
---|
D7 | I/O |
|
D6 | I/O |
|
D5 | I/O |
|
D4 | I/O |
|
D3 | I/O |
|
D2 | I/O |
|
D1 | I/O |
|
D0 | I/O |
|
port Aデータをread/writeするレジスタです。
- port B Data reg(0x41)
Bit | I/O | function
|
---|
D7 | I/O |
|
D6 | I/O |
|
D5 | I/O |
|
D4 | I/O |
|
D3 | I/O |
|
D2 | I/O |
|
D1 | I/O |
|
D0 | I/O |
|
port Bデータをread/writeするレジスタです。
- port C Data reg(0x42)
Bit | I/O | function
|
---|
D7 | I/O |
|
D6 | I/O |
|
D5 | I/O |
|
D4 | I/O |
|
D3 | I/O |
|
D2 | I/O |
|
D1 | I/O |
|
D0 | I/O |
|
port Cデータをread/writeするレジスタです。
- port D Data reg(0x43)
Bit | I/O | function
|
---|
D7 | I/O |
|
D6 | I/O |
|
D5 | I/O |
|
D4 | I/O |
|
D3 | I/O |
|
D2 | I/O |
|
D1 | I/O |
|
D0 | I/O |
|
port Dデータをread/writeするレジスタです。
- port E Data reg(0x44)
Bit | I/O | function
|
---|
D7 | I/O |
|
D6 | I/O |
|
D5 | I/O |
|
D4 | I/O |
|
D3 | I/O |
|
D2 | I/O |
|
D1 | I/O |
|
D0 | I/O |
|
port Eデータをread/writeするレジスタです。
- port F Data reg(0x45)
Bit | I/O | function
|
---|
D7 | I/O |
|
D6 | I/O |
|
D5 | I/O |
|
D4 | I/O |
|
D3 | I/O |
|
D2 | I/O |
|
D1 | I/O |
|
D0 | I/O |
|
port Fデータをread/writeするレジスタです。
- port G Data reg(0x46)
Bit | I/O | function
|
---|
D7 | I/O |
|
D6 | I/O |
|
D5 | I/O |
|
D4 | I/O |
|
D3 | I/O |
|
D2 | I/O |
|
D1 | I/O |
|
D0 | I/O |
|
port Gデータをread/writeするレジスタです。
- port H Data reg(0x47)
Bit | I/O | function
|
---|
D7 | I/O |
|
D6 | I/O |
|
D5 | I/O |
|
D4 | I/O |
|
D3 | I/O |
|
D2 | I/O |
|
D1 | I/O |
|
D0 | I/O |
|
port Hデータをread/writeするレジスタです。
本デバイスサポートは、EPICS R312で開発した後、R313でも動作を確認したものです。R313の環境をもとに説明しています。EPICSそのものに対する説明、入門出家入道については専門家に帰依するなり、コントロールグループのページをご参照されるなりなさってください。また、IOCは68k40及びPPC750で動作確認をおこなっています。
せっかちな人のために、これから紹介するデバイスサポートのsource fileを示します。
基本的なデバイスサポートの構造については、TD-4Vのデバイスサポートの項目で十分に?説明してありますので、ここでは目新しい物のみを説明します。
-インクルードファイルでは、mbbiDirect、mbboDirectのheaderが必要です。
#include <mbbiDirectRecord.h>
#include <mbboDirectRecord.h>
アドレスマップにそって、DPvme501構造体を定義します。
struct DPvme501 {
char dummy00;
char bim_cntlreg0;
char dummy0;
char bim_cntlreg1;
char dummy1;
char bim_cntlreg2;
char dummy2;
char bim_cntlreg3;
char dummy3;
char bim_vecreg0;
char dummy4;
char bim_vecreg1;
char dummy5;
char bim_vecreg2;
char dummy6;
char bim_vecreg3;
char dummy7;
char timer_counter0;
char dummy8;
char timer_counter1;
char dummy9;
char timer_counter2;
char dummy10;
char timer_cntlreg;
char dummy11;
char timer_gate0;
char dummy12;
char timer_gate1;
char dummy13;
char timer_gate2;
char dummy14;
char io_reg_a;
char dummy15;
char io_reg_b;
char dummy16;
char comp_pat_cond;
char dummy17;
char pattern_c_reg;
char dummy18;
char pattern_d_reg;
char dummy19;
char pattern_match_out;
char dummy20;
char port_a_enable;
char dummy21;
char port_b_enable;
char dum[14];
unsigned short port_j;
unsigned short port_k;
unsigned short port_ab;
unsigned short port_cd;
unsigned short port_ef;
unsigned short port_gh;
unsigned short dums[92];
};
カード毎の占有アドレススペースは0xffとります。
このデバイスサポートで使用する関数のプロトタイプ宣言をしておきます。
static long init();
static long init_li_record();
static long init_lo_record();
static long init_mi_record();
static long init_mo_record();
static long read_longin();
static long write_longout();
static long read_mbbiDirect();
static long write_mbboDirect();
static int checkLink();
を宣言しています。
このデバイスサポートでは、longin,longout,mbbiDirect,mbboDirectのデータベースを使います。
mbbiDirect、mbboDirectレコードの定義は次の通りです。
/* For devMbbiPvme501 */
struct{
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_mi_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_mbbiDirect;
}devMbbiPvme501={
5,
NULL,
NULL,
init_mi_record,
NULL,
read_mbbiDirect};
/* For devMbboPvme501 */
struct{
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_mo_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_mbboDirect;
}devMbboPvme501={
5,
NULL,
NULL,
init_mo_record,
NULL,
write_mbboDirect};
struct ioCard {
volatile struct DPvme501 *card; /* address of this card */
FAST_LOCK lock; /* semaphore */
};
と、通常の構造体です。これを使ったカード用変数は
static struct ioCard cards[CONST_NUM_LINKS];
です。
int devPvme501Config(ncards,a24base)
int ncards;
long a24base;
{
pvme501_num_links = ncards;
Base_IO = a24base;
printf("Pvme501 NumLink= %d BaseIO= %x\n",pvme501_num_links,Base_IO);
init(0);
}
何枚PVME-501を使うか、Base_IOアドレスを設定するファイルです。スタートアップファイルの中で、
devPvme501Config(1,0x4B0000)
iocInit
の様に、iocInitの前に呼びます。
カード存在の確認、各レジスタの初期化を行います。
static long init(after)
int after;
{
int cardNum, chanNum;
unsigned char probeVal;
volatile struct DPvme501 *p;
if (init_flag != 0 )
return(OK);
init_flag = 1;
if (sysBusToLocalAdrs(VME_AM_STD_SUP_DATA,(char *)Base_IO,(char **)&p) == ERROR)
{
printf("VmeP501: cannot find A24 address space\n");
return(ERROR);
}
#ifdef DEBUG_ON
if ( CDEBUG)printf("PVME501 (init) Called. pass = %d\n", after);
#endif
for (cardNum=0; cardNum< pvme501_num_links; cardNum++)
{
probeVal = UTREG;
if (vxMemProbe((char*) &(p->bim_cntlreg0), WRITE, 1, &probeVal)< OK)
{
if (debug_flag >0 )
printf("No PVME501 with cardNum= %d\n probe= %x\n",cardNum,p);
cards[cardNum].card = NULL;
}
else
{
probeVal = BM1REG;
if ((vxMemProbe((char*) &(p->bim_cntlreg1), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d bit pattern reg 1 init\n",cardNum);
......中略......
probeVal = PORTEN2;
if ((vxMemProbe((char*) &(p->port_b_enable), WRITE, 1, &probeVal) == OK) && (debug_flag >10))
printf("PVME501 card %d port EFGHK enable init\n",cardNum);
if (debug_flag >0)
printf("Found PVME501 with cardNum= %d\n address= %x\n",cardNum,p);
cards[cardNum].card = p; /* Remember address of the board */
FASTLOCKINIT(&(cards[cardNum].lock));
FASTUNLOCK(&(cards[cardNum].lock)); /* Init the board lock */
}
p++;
}
return(OK);
}
特殊な所はありません。
このボードの様にI/Oがたくさんある場合、これを全てboとかbiのsignalで分けていったのでは大変です(出来ないわけではない)。そこで、mbboDirect(multi-bit binary output direct)とかmbbiDirect(multi-bit binary input Direct)といったレコードが用意してあります。デバイスサポートとしてはとってもカンタンになります。outputならpatternがpmbbo->rvalに自動的に入っていますので、これを渡すだけです。但し、instructionにpmbbo->rbvの管理をするのはデバイスサポートの責任であると書いてあるので、ちゃんとした方がいいでしょう。
static long write_mbboDirect(pmbbo)
struct mbboDirectRecord *pmbbo;
{
short cardN;
cardN = pmbbo->out.value.vmeio.card;
if (debug_flag >5)
printf("write_mbboDirect called with card %d\n",cardN);
if (checkLink(cardN) == ERROR)
return(ERROR);
FASTLOCK(&(cards[cardN].lock));
if (debug_flag >5)
printf("card locked...\n");
switch(pmbbo->out.value.vmeio.signal){
case 0: /* Port EF */
cards[cardN].card->port_ef = pmbbo->rval;
pmbbo->rbv=cards[cardN].card->port_ef;
break;
case 1: /* Port GH */
cards[cardN].card->port_gh = pmbbo->rval;
pmbbo->rbv=cards[cardN].card->port_gh;
break;
case 2: /* Port k */
cards[cardN].card->port_k = ((pmbbo->rval) & (0xff));
pmbbo->rbv=((cards[cardN].card->port_gh) & (0xff));
break;
default:
FASTUNLOCK(&(cards[cardN].lock));
return(-1);
}
if (debug_flag >5)
printf("write complete \n");
FASTUNLOCK(&(cards[cardN].lock));
if (debug_flag >0)
printf("unlock card ...\n");
return(CONVERT);
}
また、mbbiDirectの場合は、pmbbi->rvalに値を入れるだけです。
static long read_mbbiDirect(pmbbi)
struct mbbiDirectRecord *pmbbi;
{
short cardN;
cardN = pmbbi->inp.value.vmeio.card;
if (debug_flag >5)
printf("read_mbbiDirect called with card %d\n",cardN);
if (checkLink(cardN) == ERROR)
return(ERROR);
switch(pmbbi->inp.value.vmeio.signal){
case 0: /* port AB */
pmbbi->rval = cards[cardN].card->port_ab;
break;
case 1: /* port CD */
pmbbi->rval = cards[cardN].card->port_cd;
break;
case 2: /* port J */
pmbbi->rval = ((cards[cardN].card->port_j) & (0xff));
break;
default:
return(-1);
}
if (debug_flag >5)
printf("read complete \n");
return(CONVERT);
}
このデバイスサポートで使うデータベースをまとめると、以下の様になります。
Record | Signal | Name | Function | Remarks
|
---|
mbbiDirect | 0 | portab | port A B input |
|
mbbiDirect | 1 | portcd | port C D input |
|
mbbiDirect | 2 | portj | port J input | 8 bit
|
mbboDirect | 0 | portef | port E F output |
|
mbboDirect | 1 | portgh | port G H output |
|
mbboDirect | 2 | portk | port K output | 8 bit
|
longin | 0 | lportab | port AB longin |
|
longin | 1 | lportcd | port CD longin |
|
longin | 2 | lportj | port J longin | 8 bit
|
longout | 0 | lportef | port EF longout |
|
longout | 1 | lportgh | port GH longout |
|
longout | 2 | lportk | port K longout | 8 bit
|
capfastで書いたデータベースを下に示します。
Makefile.Vxを変更し、それぞれ
SRCS.C += ../devPVME501.c
と
LIBOBJS += devPVME501.o
を付け加え、gmakeでコンパイルします。capfastのschファイルもsch2dbでdbファイルにコンバートします。また、新しく加わったデータベースを"なんとかinclude.dbd"の定義に加えておきます。
device(longin,VME_IO,devLiPvme501,"PVME501")
device(longout,VME_IO,devLoPvme501,"PVME501")
device(mbbiDirect,VME_IO,devMbbiPvme501,"PVME501")
device(mbboDirect,VME_IO,devMbboPvme501,"PVME501")
スタートアップファイルは、iocBootの下のiocなんとかの所に作ります。
# Example vxWorks startup file
#Following must be added for many board support packages
cd "/users/tobiyama/epics_r313/iocBoot/iocfeedback"
#ld < bin/enableA24_frc64.o
ld < bin/kekRouteSet_frc40.o
#ld < bin/kekRouteSet_frc64.o
ld < bin/iocCore
ld < bin/seq
ld < bin/feedbackLib
dbLoadDatabase("dbd/feedbackApp.dbd")
dbLoadDatabase("feedbackApp/Db/fb_ar_pvme.db","user=tobiyama")
#dbLoadRecords("feedbackApp/Db/dbExample.db","user=tobiyama")
devPvme501Config(1,0x4B0000)
iocInit
#seq &snctest
iocInitの前にdevPvme501Configでパラメータを渡すのを忘れないようにして下さい。
テストのためmedmで制御をしてみました。

なお、longin/outでもmbbiDirect/mbboDirectでも同じポートをアクセスできますが、このデータベース構造ではお互いに設定は反映しませんので、注意が必要です。
汎用40ビットI/OボードPVME501のデバイスサポート及びEPICSデータベース等の説明を行いました。関東情報サービスの吉田氏には、mbbiDirect及びmbboDirectのcapfastシンボルを用意して頂くなど、お世話になりました。
Makoto Tobiyama
7/Sep/98
Return to FB Home Page...