VME 2幅 ダブルハイト
VMEアクセスがあったとき緑色に点灯。
緑:トリガー許可状態
赤:メモリー書き込み中(メモリーへのアクセス及びトリガー不可)
橙:A/D終了(メモリーの最後まで書き込んだ状態)
点灯時はADC温度(ファン停止)あるいは電源電圧異常。よく(?)あるのは、 VMEバスへの突っ込み不足で電圧異常が起きているとき点灯する。
緑:FPGA正常(ブートOK)
赤:FPGA異常(ブート未了、あるいはブート失敗)
各信号入力時に点灯
NIMレベル。インピーダンス50Ω。立ち下がりでADスタート。20ns程度の幅があることが望ましい。
NIMレベルトリガー出力。
リング周回周波数、NIMレベル、立ち下がり動作。20ns程度の幅があることが望ましい。 動作中は常に(正確に)供給されていること。
Rev出力
サンプルクロック入力。インピーダンス50Ω。内蔵EP196により、最大10ns、ステップ10psのdelay可能。 -10dBm〜5dBmの正弦波を想定。内部でラインレシーバーによりタイミング取得している。
インピーダンス50Ω。内蔵THS4303により14dB(5倍)に増幅し、MAX108 ADCに入力する。
アドレス | Write/Read | データ | |||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ||||
0x*****(***00)00 | (R/W) | BOARD RESET | |||||||||||||||||||||||||||||||||
0x*****(***00)04 | (R/W) | TRIG_ENB | |||||||||||||||||||||||||||||||||
0x*****(***00)08 | (R/W) | MEM_TRIG | |||||||||||||||||||||||||||||||||
0x*****(***00)0C | (R/W) | MEM_SIZE | |||||||||||||||||||||||||||||||||
0x*****(***00)10 | (R/W) | IRQ_ENB | |||||||||||||||||||||||||||||||||
0x*****(***00)14 | (R/W) | ADCLK_DLY | |||||||||||||||||||||||||||||||||
0x*****(***00)18 | (R/W) | ADC_RST | |||||||||||||||||||||||||||||||||
0x*****(***00)1C | (R/W) | ADRDPT_RST | |||||||||||||||||||||||||||||||||
0x*****(***00)20 | (R/W) | MEM_CL | |||||||||||||||||||||||||||||||||
0x*****(***00)24 | (R/W) | FPGA_OUT | |||||||||||||||||||||||||||||||||
0x*****(***00)28 | |||||||||||||||||||||||||||||||||||
0x*****(***00)2C | |||||||||||||||||||||||||||||||||||
0x*****(***00)30 | (R) | BOARD_STS | |||||||||||||||||||||||||||||||||
0x*****(***00)34 | (R) | AD_STS | |||||||||||||||||||||||||||||||||
0x*****(***00)38 | (R) | REC_MODE | |||||||||||||||||||||||||||||||||
0x*****(***00)3C | (R) | HARMONIC | |||||||||||||||||||||||||||||||||
0x*****(***00)40 | (R) | IRQ_NO | |||||||||||||||||||||||||||||||||
0x*****(***00)44 | (R) | IRQ_ID | |||||||||||||||||||||||||||||||||
0x*****(***00)48 | (R) | FPGA_IN | |||||||||||||||||||||||||||||||||
0x*****(***00)4C | |||||||||||||||||||||||||||||||||||
0x*****(***00)50 | (R) | DEBUG0 | |||||||||||||||||||||||||||||||||
0x*****(***00)54 | (R) | DEBUG1 | |||||||||||||||||||||||||||||||||
0x*****(***00)58 | |||||||||||||||||||||||||||||||||||
0x*****(***00)FC | |||||||||||||||||||||||||||||||||||
0x*****(***01)00 | (R) | Data 0 | Data 1 | Data 2 | Data 3 | ||||||||||||||||||||||||||||||
0x*****(***01)04 | (R) | Data 4 | Data 5 | Data 6 | Data 7 | ||||||||||||||||||||||||||||||
(R) | Data n | Data n+1 | Data n+2 | Data n+3 | |||||||||||||||||||||||||||||||
0x*****(***01)FC | (R) | Data 252 | Data 253 | Data 254 | Data 255 |
入力電圧 | ディジタル出力 | |||||||
---|---|---|---|---|---|---|---|---|
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
100mV | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
0V | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
-100mV | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
電源オン状態にリセット、FPGAはFlashよりコードを再ロード
1でtrigger許可。0にすると強制停止。ADスタート後、自動0クリア
メモリーモード時のトリガー位置。BCMモード時は-100%に固定です。 0の時-100%、1の時0%、2の時100%です。ほとんどの場合、 0の-100%の設定になると思います。
メモリーモード時の記憶容量で、ハーモニック数×この記録周回数と なります。
0で4096(h=5120のとき20MB)、1で8192(h=5120の時40MB)、2で16384(h=5120の時80MB) です。
割り込み許可です。LSBがADデータ取得終了時の割り込み許可で1でenableです。2bit目は デバッグ用の5秒タイムアウト割り込みで、デバッグ以外使うことはありません。
ADC用のclockをEP195を使いdelayするもので、10ビットあります。1ビットが10psにあたります。 最大10ns程度までdelayさせることは可能ですが、大きなdelayではEP195の温度特性により 大きな誤差が生じますので、精々2ns程度までの設定にした方が良いです。
MAX108 ADCのインターリーブド出力をFPGAからのADCLK/4に同期させるコマンドで、もしも Ach-Bchが入れ替わっていたとき試してみると役に立つかもしれません(1回で同期出来る 保証は無いので、だめなら数回試してみる必要があります)。
VMEからのADリードポインタを0クリアします。メモリー読み出し時前に1回発効する 必要があります。
1でADデータメモリのクリアを行います。データは常に上書きされていますので、 デバッグ以外でこのコマンドを発効する必要はありません。
予備レジスタ
ボードステータスで
10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|
ADCオーバーフロー(1でNG) | ADC_FAN(1でOK) | RF OK | Rev OK | FPGA DONE(1でOK) | DDR2 OK | FPGAパワーOK | ADC温度OK | -5VA OK | +5VA OK | +3.3VD OK |
AD処理ステータスです。
4 | 3 | 2 | 1 | 0 |
トリガー検出 | ADC overflow | データ強制終了 | ADC OK |
0でBCMモード、1でメモリーモード
設定ハーモニック数読み出し。0で230(DR)、1で312(PF)、2で640(AR)、3で5120(KEKB)。
割り込みレベル(1〜7)。ボード上の設定読みだし
割り込みvector。ボード上の設定読みだし
EPICSそのものに対する入門出家入道については専門家に帰依するなり、 コントロールグループのページを参照するなどの自活努力をお願いします。
device(bo,VME_IO,devBo18k10KM,"V18K10KM") device(bi,VME_IO,devBi18k10KM,"V18K10KM") device(mbbiDirect,VME_IO,devMbbi18k10KM,"V18K10KM") device(waveform,VME_IO,devWf18k10KM,"V18K10KM") device(longout,VME_IO,devLo18k10KM,"V18K10KM") device(longin,VME_IO,devLi18k10KM,"V18K10KM") device(stringout,VME_IO,devSo18k10KM,"V18K10KM") device(stringin,VME_IO,devSi18k10KM,"V18K10KM")です。
DMA転送の詳細は、18k11の説明に 書きましたので、ここでは変更部分のみ示します。18K11の場合は、MBLTでしたが、18K10はBLTなので、 以下の様になります。
#include </space/wind221/target/config/mv5500/sysDma.h> #include </space/wind221/target/config/mv5500/universe.h> #include <vxLib.h>
static unsigned long *gplTmpData;
if ( sysVmeDmaInit() != OK ) { logMsg("sysVmeDmaInit() Error!!\n",0,0,0,0,0,0); return(ERROR); }
gplTmpDataB = memalign( 256, 64*4 );
設定の関数はsysVmeDmaCnfgSetで、以下の様な形になっています。
STATUS sysVmeDmaCnfgSet( UINT32 xfertype, UINT32 addSpace, UINT32 dataType, UINT32 userType ) RETURN : OK (正常) or ERROR (エラー) xfertype: 転送種別 DCTL_VDW_8 | DCTL_VCT_SINGLE(データ8ビット シングルサイクルモード) DCTL_VDW_16 | DCTL_VCT_SINGLE(データ16ビット、シングルサイクルモード) DCTL_VDW_32 | DCTL_VCT_SINGLE(データ32ビット、シングルサイクルモード) DCTL_VDW_64 | DCTL_VCT_SINGLE(データ64ビット、シングルサイクルモード) DCTL_VDW_32 | DCTL_VCT_BLK(データ32ビット、ブロック転送モード) DCTL_VDW_64 | DCTL_VCT_BLK(データ64ビット、ブロック転送モード) addrSpace: VMEアドレスモード DCTL_VAS_A16 : short (A16)アドレス DCTL_VAS_A24 : 標準 (A24)アドレス DCTL_VAS_A32 : 拡張 (A32)アドレス dataType: データ種別 DCTL_PGM_DATA : データ DCTL_PGM_PRGM : プログラム userType : アクセス種別 DCTL_SUPER_USER : 非特権アクセス DCTL_SUPER_SUP : 特権アクセスこれらの組み合わせを指定することで、対応するAMコードも変わります。 ボード側でサポートされていない組み合わせだと、AMコードが出ても ボード側が応答しない(DTACKが出ない)のでエラーとなります。なお、 シングルサイクルモードは、VMEで規定されているブロック転送では ありませんので、AMコードとしては通常アクセスと同じです。転送自体 はCPUを通さないので、通常のアクセスより高速です。今回の 転送は、BLT(A32 supervisory 32-bit block transfer) なので、AMコードは0x0Fとなります。
if (sysVmeDmaCnfgSet(DCTL_VDW_32 | DCTL_VCT_BLK, DCTL_VAS_A32, DCTL_PGM_DATA, DCTL_SUPER_SUP) != OK){ logMsg("devVme18k10KM error DMA setting\n",0,0,0,0,0,0);}
STATUS sysVmeDmaV2LCopy( UCHAR *localVMEAddr, UCHAR *localAddr, UINT32 nbytes ) RETURN : OK(正常) ERROR (ドライバ未初期化 or 引数不正) DGCS_LERR (PCIbus エラー) DGCS_VERR (VMEバスエラー) DGCS_P_Error (プロトコルエラー) *localVMEAddr : VMEバスアドレス(8byteアライメントアドレス) *localAddr : ローカルメモリアドレス(8byteアライメントアドレス) nbyte : コピーするデータサイズ(byte) 0x1-0xffffff(16Mb -1)はじめに、VMEからのADリードポインタを0クリアします。読み出し自体は メモリーマッピングが素直なので、そのまま取ってきたデータを waveformに展開すればOKです。
cards[cardN].card->adrdpt_rst = 0x1; sysUnivVERRClr(); if(sysVmeDmaStatusGet(&pSta) != OK ) { logMsg("sysVmeDmaStatusGet() Error!!\n", 0, 0, 0, 0, 0,0); } if(sysVmeDmaCnfgGet(&p1,&p2,&p3,&p4) != OK ) { logMsg("sysVmeDmaCnfgGet() Error!!\n", 0, 0, 0, 0, 0,0); } for (is=0;is<81920;is++){ iDmaStartRc = sysVmeDmaV2LCopy( &cards[cardN].card->ad_data[0], gplTmpDataB+0, 64*4 ); if(iDmaStartRc != 0) { logMsg("-->sysVmeDmaV2LCopy() error!! Rc[%d] card[%d]\n", iDmaStartRc, cardN, 0, 0 ,0, 0 ); } for ( ii = 0; ii < 64 ; ii++ ) {us_thing[is*256+ii*4+0] = (unsigned char)( (gplTmpDataB[ii] >>24)&0xff); us_thing[is*256+ii*4+1] = (unsigned char)( (gplTmpDataB[ii] >>16)& 0xff); us_thing[is*256+ii*4+2] = (unsigned char)((gplTmpDataB[ii] >>8) &0xff); us_thing[is*256+ii*4+3] = (unsigned char)((gplTmpDataB[ii]) & 0xff);} }
fb5500_DBD += devVme18k10KM.dbd fb5500_SRCS += devVme18k10KM.cmakeは以下の様にsrcディレクトリで
gmakeとします。
初期化ファイルはdev18k11Configで、ベースアドレスが0x08000000で、 IRQ=4、IRQ Vectorが0xF0で1枚使うとすると、
dev18k10KMConfig(1,0x08000000,0x4,0xf0)
の様に指定します。
実際の使用条件では、データを自動的にdiskにsaveして、あとからアクセスすることがほとんどと 思います。このため
static int saveflag[10];を定義し、boレコードを使ってこのフラグを制御します。具体的には、boのsignal 5を追加して
case 5 : /* soft : record data y/n */ saveflag[cardN] = 0x1 &(pbo->val); break;としておきます。waveformレコード内では、saveflagをみて条件分岐させます。
struct timespec time_val;外部からSOで与えたファイルheader (MLHとかMHVとか)に 現時間を日付_月_年_時間_分_秒の形にした物をくっつけ、 拡張子としてADCを付けた名前を作り、global変数のfile_nameに格納します。
strcpy(file_name[cardN],NULL); strcat(file_name[cardN],head[cardN]); clock_gettime(CLOCK_REALTIME, &time_val); strftime(ttt,buflen,"%d_%b_%Y_%H_%M_%S",localtime(&time_val)); strcat(file_name[cardN],ttt); strcpy(eee,".ADC"); strcat(file_name[cardN],eee); if (debug_flag >5) logMsg("file_name =%s\n",file_name[cardN],0,0,0,0,0);なお、SIレコードでこのファイル名が読み出せるようにしておきます。
static long init_si_record(pstringin) struct stringinRecord *pstringin; { return 0; } static long read_si(pstringin) struct stringinRecord *pstringin; { long status = 0; short cardN; char tempchar[255]; cardN = pstringin->inp.value.vmeio.card; if (checkLink(cardN) == ERROR) { logMsg("Error- No 18k10KM for card %d\n",cardN,0,0,0,0,0); return(ERROR); } switch(pstringin->inp.value.vmeio.signal){ case 0 : strcpy(pstringin->val,file_name[cardN]); break; } return(status); }デバイスサポート内だけで、このSIレコードをプロセスさせるのは面倒(というか、 よく分からない)ので、waveformがprocessされたとき、FLNKでSIレコードを プロセスするようにデータベースでしておきます。もしも、sequencerなどで モニターしておけば、SIレコードが更新したタイミングを捕まえて actionすることができます。
手順は以下の様になります。
#define NUM_20M (5120*4096) #define NUM_40M (5120*8192) #define NUM_80M (5120*16384) ... if (memory_size == 1) { m1 = 81920 * 2; m2 = NUM_40M; } else if (memory_size == 2) { m1 = 81920 * 4; m2 = NUM_80M; } else { m1 = 81920; m2 = NUM_20M; } ...... pwf->nord = m2; if (saveflag[cardN]) { if (hostAdd( "wrs", "172.19.57.***" ) != OK) { logMsg("hostAdd Error!!\n",0,0,0,0,0,0); return(-1); } taskDelay( sysClkRateGet() /10); if( nfsMount( "wrs", "/raid0/data/_NAS_NFS_Exports_/BOR","/bor/" ) != OK) { logMsg("nfsMount Error!!\n",0,0,0,0,0,0); return(-1); }cd( "/bor/current/");if( ( pwFile = fopen( file_name[cardN], "w" )) == NULL ) {logMsg("File Open[Write mode] Error!!\n",0,0,0,0,0,0);return(-1); } if( ( wsize = fwrite(&us_thing[0], 1, m2, pwFile )) != m2) {logMsg("Unmatch File Write Length!!\n",0,0,0,0,0,0); } fclose(pwFile);nfsUnmount("/bor/"); hostDelete( "wrs", "172.19.57.***"); }
# Example vxWorks startup file #Following must be added for many board support packages </cont/bootp/ioc/kekb_mv5500.cmd putenv "EPICS_CA_MAX_ARRAY_BYTES=167772160" # put your startup script below </users/tobiyama/epics_M6/iocBoot/iocfbppc/st.test2.cmd kekBootLog printTime(60)のように、自分の所のブートファイルを読みに行くように設定します。 なお、EPICS_CA_MAX_ARRAY_BYTESはクライアント側も設定しておかないと 長いwaveformを読む事が出来ません。
dbLoadRecords("db/FB_BCMKM.db","USER=FBB, CHAN=C0")
dev18k10KMConfig(1,0x08000000,0x5,0x90)
dbpf "FBB:MEM4:IRQENB","1" dbpf "FBB:MEM4:TRG_ENB","1" dbpf "FBB:MEM4:FILEHEAD","MLH"
こう見てみると、VMEのデータ転送がやはり一番遅くボトルネックになって いることが分かります。NASに書き込むより遅いなんてショックです。 もちろん、昔のBORに比べると、遙かに早くはなっているのですが。