[KEKB Bunch Feedback Group]

Internix社製40ビットデジタルI/OボードPVME-501/02用EPICS Device Supportの製作(Japanese)


by とびやま まこと(Makoto Tobiyama)/KEKB ビームモニターグループ

警告
以下の記述に関しては、意図する、しないに関わらず多くの誤り、誤解が含まれていると思われますので、決して信用してはいけません。これを信じて起きた損害に関しては、当方は一切責任を持ちません。


If you need contact with the author, please E-mail makoto.tobiyama@kek.jp.
目次

1.はじめに

PVME-501/02は、インターニックス株式会社殿が開発したVMEバス対応の40ビット入力、40ビット出力のデジタルI/Oボードです。入力、出力は高速(?)フォトカップラで絶縁してあります。

これから紹介するデバイスサポートは、このボードをただのI/OボードとしてEPICSで使うためにtobiyamaが書いたものです。割り込み等の機能には対応していません。


2.VMEバスレジスタ

PVME-501/02を操作する上で必要な各レジスタについて紹介します。詳しくはPVME-501/02のユーザーズ・マニュアルをご覧下さい。ベースアドレス(BASE_IO)は省略しますが、あるアドレス(例えば0x01)が書いてある場合、BASE_IO+0x01だと思って見て下さい。特に断らない限り、unsigned charアクセスをしていると思って下さい。

3.EPICS環境

本デバイスサポートは、EPICS R312で開発した後、R313でも動作を確認したものです。R313の環境をもとに説明しています。EPICSそのものに対する説明、入門出家入道については専門家に帰依するなり、コントロールグループのページをご参照されるなりなさってください。また、IOCは68k40及びPPC750で動作確認をおこなっています。
せっかちな人のために、これから紹介するデバイスサポートのsource fileを示します。

4.コードの説明

基本的なデバイスサポートの構造については、TD-4Vのデバイスサポートの項目で十分に?説明してありますので、ここでは目新しい物のみを説明します。

5.1 インクルードファイル

-インクルードファイルでは、mbbiDirect、mbboDirectのheaderが必要です。
#include        <mbbiDirectRecord.h>
#include        <mbboDirectRecord.h>

4.2 VMEアドレスの割り当て構造体

アドレスマップにそって、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とります。

4.3 関数プロトタイプの宣言

このデバイスサポートで使用する関数のプロトタイプ宣言をしておきます。

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();

を宣言しています。

4.4 データベース構造体の宣言

このデバイスサポートでは、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};

4.5 カード構造体の宣言

struct ioCard {
        volatile struct DPvme501     *card; /* address of this card */
        FAST_LOCK                    lock; /* semaphore */
      };
と、通常の構造体です。これを使ったカード用変数は
static struct ioCard cards[CONST_NUM_LINKS];
です。

4.6 スタートアップで呼ぶ設定読み込みファイル

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の前に呼びます。

5.7 初期化ファイル

カード存在の確認、各レジスタの初期化を行います。
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);
}
特殊な所はありません。

4.8 mbbiDirect、mbboDirect

このボードの様に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);
}

5.EPICSデータベース

このデバイスサポートで使うデータベースをまとめると、以下の様になります。
RecordSignalNameFunctionRemarks
mbbiDirect0portabport A B input
mbbiDirect1portcdport C D input
mbbiDirect2portjport J input8 bit
mbboDirect0portefport E F output
mbboDirect1portghport G H output
mbboDirect2portkport K output8 bit
longin0lportabport AB longin
longin1lportcdport CD longin
longin2lportjport J longin8 bit
longout0lportefport EF longout
longout1lportghport GH longout
longout2lportkport K longout8 bit

capfastで書いたデータベースを下に示します。

6.スタートアップファイル

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でパラメータを渡すのを忘れないようにして下さい。

7.MEDMによる制御

テストのためmedmで制御をしてみました。
medm image
なお、longin/outでもmbbiDirect/mbboDirectでも同じポートをアクセスできますが、このデータベース構造ではお互いに設定は反映しませんので、注意が必要です。

8.おわりに

汎用40ビットI/OボードPVME501のデバイスサポート及びEPICSデータベース等の説明を行いました。関東情報サービスの吉田氏には、mbbiDirect及びmbboDirectのcapfastシンボルを用意して頂くなど、お世話になりました。
Makoto Tobiyama
7/Sep/98

Return to FB Home Page...