[KEKB Bunch Feedback Group]

株式会社デジテックス研究所製 超高速バンチ電流モニタEPICS Device Support(Japanese)


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

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


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

1.はじめに

バンチ電流モニターは509MHzで動作する8ビットのメモリーボードです。メモリー自体は20Mbもっていますが、高速更新・アクセスを実現するためアドレス空間を制限しています。 本デバイスサポートはバンチ電流モニターデータ更新と同時にリフレクティブメモリーへのアクセスもするようになっており、KEKB専用です。

2.VMEバスレジスタ

バンチ電流モニターボードのアドレスマップは以下の通りです。

3.EPICS環境

本デバイスサポートは、EPICS R313改訂版で開発したものです。EPICSそのものに対する説明、入門出家入道遁世については専門家に帰依するなり、コントロールグループのページをご参照なさるなり勝手になさってください。動作はPPC750のみで確認しています。

4.コードの概要

コードは以下の通りです。通常使用しない部分に関しては完全なテストは行っていません。

Advanet1522のアドレス

作者の違いにより、Advanet1522 shared memory関連のアドレス指定は特殊です。

#define R_MID   (CARD1522 + 0x03)  /* Node ID */
#define R_MINF1 (CARD1522 + 0x07)  /* Memory Information 1 */
#define R_MINF2 (CARD1522 + 0x0B)  /* Memory Information 2 */
#define R_SR    (CARD1522 + 0x0F)  /* Status */
#define R_CMD   (CARD1522 + 0x13)  /* Command */
#define R_HCNT  (CARD1522 + 0x17)  /* Hop Count Register */
#define R_IIVEC (CARD1522 + 0x1B)  /* Internal Interrupt Vector */
#define R_IILEV (CARD1522 + 0x1F)  /* Internal Interrupt Level  */
#define R_EIVEC (CARD1522 + 0x23)  /* External Interrupt Vector */
#define R_EILEV (CARD1522 + 0x27)  /* External Interrupt Level  */
#define R_TITID (CARD1522 + 0x2B)  /* Transfer Interrupt Command ID  */
#define R_TIINF (CARD1522 + 0x2F)  /* Transfer Interrupt Information */
#define R_RIDTD (CARD1522 + 0x33)  /* Receive  Interrupt Command ID  */
#define R_RIINF (CARD1522 + 0x37)  /* Receive  Interrupt Infromation */
#define R_MEM1  ((void*)(CARD1522 + 0x200))
              /* Start addr. of network shared memory */
#define R_MEM2  ((void*)(CARD1522 + 0x2200))

初期化部

バンチ電流モニターと同時にshared memory ADVANET1522の初期化もします。
if (sysBusToLocalAdrs(VME_AM_EXT_SUP_DATA,(char *)Base_IO,(char **)&p) == ERROR)
	{
		logMsg("VmebcmL: cannot find extended address space\n");
		return(ERROR);
	}
        /* これはバンチ電流モニター用アドレス割り振り */

         cards[cardNum].card = p;  /* Remember address of the board */

	 cards[cardNum].card->cntl2 = 0x40;
        /* データ転送方式をD32-compressedにするおまじない */
	 
	 cards[cardNum].card->cntl1 = 0x01;
	 /* とりあえずバンチ電流モニターをstop状態にする
	    初期化中に割り込みが入ると困るから */
	
	 scanIoInit(&(cards[cardNum].ioscanpvt));
	 /* 割り込みベクタ初期化 */
	 FASTLOCKINIT(&(cards[cardNum].lock));
	 FASTUNLOCK(&(cards[cardNum].lock)); /* Init the board lock */

    
  /* ここからAdvanet 1522初期化ルーチン */
  BASE1522=0x30000000; /* 完全に決めうち */
  
  if (sysBusToLocalAdrs(VME_AM_EXT_SUP_DATA, (char *)(int)BASE1522,
                        (char **)&CARD1522) == ERROR)
    {
      logMsg("devDvmesw: cannot find extended address space\n");
    }
  
  logMsg("R_MID=0x%x R_MEM1= 0x%x R_MEM2= 0x%x\n",R_MID,R_MEM1,R_MEM2);
  *R_TITID=0xFF; /* reciever ID  3= Linac */
  *R_MINF1=0x80; /* transfer enable */

configuration function

ボード数、A32アドレス、割り込みレベル、割り込みベクターの初期値を指定します。

int devVmebcmConfigS(ncards,a32base,intlevel,intvecbase)
int ncards;
long a32base;
int intlevel;
int intvecbase;
{
  vmebcm_num_links = ncards;
  Base_IO = a32base;
  INT_LEVEL = intlevel;
  INT_VEC_BASE = intvecbase;
  logMsg("devVmebcm NumLink= %d BaseIO= %x IntLevel = %d IntVecBase =0x%x\n",vmebcm_num_links,Base_IO,INT_LEVEL,INT_VEC_BASE);

  init_all(0);
}

BOの動作

割り込み処理ルーチン

単に割り込みをかけたボードに対してscanリクエストを出すだけ。
void bcm_isr(pwf)
struct waveformRecord	*pwf;
{
  unsigned char mode;
  short cardN;

  cardN = pwf->inp.value.vmeio.card;
  scanIoRequest(cards[cardN].ioscanpvt);
  return;
}

waveform初期化ルーチン

割り込みの初期化及びボードの初期化を行います。ここを通って初めてボードは動作可となります。
static long init_wf_record(pwf)
struct waveformRecord	*pwf;
{
  short cardNum;
  
  cardNum = pwf->inp.value.vmeio.card;

  if (intConnect(INUM_TO_IVEC(INT_VEC_BASE + cardNum),
		 (VOIDFUNCPTR)bcm_isr, 
		 (int)pwf) != OK)
    logMsg("devbcm: Interrupt connect failed for card %d\n",pwf->inp.value.vmeio.card);
  logMsg("intConnect 0x%X\n",pwf);
  cards[cardNum].card->cntl1 = 0x01;
  sysIntEnable(INT_LEVEL+cardNum);
  logMsg("bcm int set for int 0x%x\n",INT_LEVEL+cardNum);
  cards[cardNum].card->cntl1 = 0x01;
  cards[cardNum].card->cntl1 = 0x09;
  cards[cardNum].card->cntl1 = 0xff0c;
  return(0);
}

shared memory用データ合成ファンクション

8ビットデータ4つを合成して1つの32ビットデータを作るfunctionです。shared memoryへのアクセス回数をできるだけ減らすための工夫です。

static unsigned long bc_comb(unsigned char bc_o[], int i)
{
  unsigned long a = 0;
  a = ((unsigned long)(bc_o[i*4])<<24) | ((unsigned long)(bc_o[i*4+1])<<16) | ((unsigned long)(bc_o[i*4+2])<<8) | (unsigned long)(bc_o[i*4+3]);
  return a;
}

waveform読みとり

はじめに(念のため)ボードを読みとり状態に再設定します(余り意味はないが...)
  cards[cardN].card->cntl2 = 0x40;
  cards[cardN].card->cntl1 = 0x01;
  cards[cardN].card->cntl1 = 0x09;
charの配列bc_oにまずデータを入れます。メモリーの構造は大きくboardとcardに分かれており、隣同士もインターリーブ出力なので面倒です。あるアドレスをD32で読んだとき、
4  2  3  1
という形でデータが並んでいます。また、隣のアドレス(1 card先)は32個先のデータになります。1ボード先は4先のデータ(つまり今のデータの隣組)となります。これを正しく読むため、
                for (j=0; j<8; j++)
		 {

		  for (i=0;i<160; i++)
		    {
		      a1=cards[cardN].card->board[j][i+MEM_OFFSET];
		      bc_o[j*4+i*32]=    (unsigned char)(a1 & 0x000000ff);
		      bc_o[j*4+i*32+1] = (unsigned char)((a1 & 0x00ff0000)>>16);
		      bc_o[j*4+i*32+2] = (unsigned char)((a1 & 0x0000ff00)>>8);
		      bc_o[j*4+i*32+3] = (unsigned char)((a1 >>24));

		    } 
		  }
LERのときは(card IDが0と決めうちしてある)waveformデータ用にbc_oを換算し、SMemLにバンチ電流データを書き込み、shared memoryの*R_TIINFに0xf0を(LERよ)と書き、*R_CMDを1にします。
		if (cardN==0) /* for LER */
		  {
		    for (i=0; i<1280; i++)
		      {
			for (j=0; j<4; j++)
			  {
			    f_thing[i*4+j]=cal_fac_bcm_L*bc_o[i*4+j];
			  }
			ref_dat[i]=bc_comb(bc_o,i);
		      }			 
		    for (iad=0;iad<320;iad++){
		      write_smemek(SMemL,ref_dat,iad*4,nwd);
		    }
		    *R_TIINF = 0xf0;
		    *R_CMD=1; /* inform interrupt */
		  }
HERの時は換算計数がHER用になり、SMemHに書き、*R_TIINFが0x00となります。作業が終わったら、waveformの長さを書いておきます。
	pwf->nord=5120;
このあと、ボードをリセットして次のトリガーに備えます。
  cards[cardN].card->cntl1 = 0x01;
  cards[cardN].card->cntl1 = 0x09;
  cards[cardN].card->cntl1 = 0xff0c;

dbdファイル

dbdファイルの中で次のように定義します。
device(bo,VME_IO,devBoVmebcmS,"VMEBCMS")
device(mbbiDirect,VME_IO,devMbbiVmebcmS,"VMEBCMS")
device(waveform,VME_IO,devWfVmebcmS,"VMEBCMS")
初期化ファイルはdevVmeFIRCnfigで、ベースアドレスが0x20400000で2枚使うとすると、
devVmebcmConfigS(2,0x20400000,0x05,0xf1)

の様に指定します。

5.EPICSデータベースサンプル

このデバイスサポートで使うデータベースをまとめると、以下の様になります。
DTYPRecordSignalNameFunctionRemarks
VMEBCMSwaveform0($USER):BUNCHBunch current data(5120)このままでは表示等できないのでデータベースで分割する必要あり
Soft ChannelsubarrayN/A($USER):FILL1Bunch current data(0-2559)速すぎるのでやはり使えない
Soft ChannelsubarrayN/A($USER):FILL2Bunch current data(2560-5119)速すぎるのでやはり使えない
Soft ChannelwaveformN/A($USER):HALF1Bunch current data(0-2559)5秒更新
Soft ChannelwaveformN/A($USER):HALF2Bunch current data(2560-5119)5秒更新
Soft ChannelwaveformN/A($USER):BCM1Bunch current data(0-2559)60秒更新(記録用)
Soft ChannelwaveformN/A($USER):BCM1Bunch current data(2560-5119)60秒更新(記録用)
VMEBCMSBO0($USER):SYNCボードスタートアクセスで起動
VMEBCMSBO1($USER):STOPボードストップアクセスで起動

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

現在ののスタートアップファイル(の関係部分)は次のようになります。
dbLoadDatabase("fbppcApp/Db/FBL_BCM.db")
dbLoadDatabase("fbppcApp/Db/FBH_BCM.db")

devVmebcmConfigS(2,0x20400000,0x05,0xf1)

iocInit

7.おわりに

バンチ電流モニターボード用のEPICSデバイスサポートおよびデータベースについて紹介しました。この中のAdvanet 1522に関連する部分は菊谷氏によってかかれたものをこのデバイスサポートに移植したものです。
LERのバンチ電流モニター表示例
Makoto Tobiyama
7/Mar/2001

Return to FB Home Page...