アドレス | 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)00000 | (R/W) | **** | CH3:ADデータ | **** | CH1:ADデータ | ||||||||||||||||||||||||||||
**** | Ch3 | **** | CH1 | ||||||||||||||||||||||||||||||
0x**(**00)0FFFC | **** | CH3:ここまで(32kワード時) | **** | CH1:32k | |||||||||||||||||||||||||||||
**** | Ch3 | **** | CH1 | ||||||||||||||||||||||||||||||
0x**(**00)FFFFC | **** | CH3:ここまで(256kワード時) | **** | CH1:256k | |||||||||||||||||||||||||||||
0x**(**01)00000 | (R/W) | **** | CH4:ADデータ | **** | CH2:ADデータ | ||||||||||||||||||||||||||||
**** | CH4 | **** | CH2 | ||||||||||||||||||||||||||||||
0x**(**01)0FFFC | **** | CH4:ここまで(32kワード時) | **** | CH2:32k | |||||||||||||||||||||||||||||
**** | CH4 | **** | CH2 | ||||||||||||||||||||||||||||||
0x**(**01)FFFFC | **** | CH4:ここまで(256kワード時) | **** | CH2:256k | |||||||||||||||||||||||||||||
0x**(**10)00000 | R/W | * | AD_START | ||||||||||||||||||||||||||||||
0x**(**10)00004 | R/W | * | AD_MEMORY | ||||||||||||||||||||||||||||||
0x**(**10)00008 | R/W | * | TRG_POS | ||||||||||||||||||||||||||||||
0x**(**10)0000C | R/W | * | IRQ_ENB | ||||||||||||||||||||||||||||||
0x**(**10)00010 | R/W | * | Reserved | ||||||||||||||||||||||||||||||
0x**(**10)00014 | R | * | AD_STATUS | ||||||||||||||||||||||||||||||
0x**(**10)00018 | R | * | IRQ_NO | ||||||||||||||||||||||||||||||
0x**(**10)0001C | R | * | IRQ_ID | ||||||||||||||||||||||||||||||
0x**(**11)***** | R | * | トリガポインタレジスタ(R) | ||||||||||||||||||||||||||||||
0x**(**11)FFFFF | N/A | *(NOT USED) |
63-48 | 47-32 | 31-16 | 15-0 |
---|---|---|---|
CH4:A/Dデータ | CH2:A/Dデータ | CH3:A/Dデータ | CH1:A/Dデータ |
ADCのデータフォーマットは、
入力電圧 | ディジタル出力 | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
(MSB) | (LSB) | |||||||||||||||
2V | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
1V | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0V | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 |
---|---|
5秒タイムアウト(有効=1) | IRQ有効(有効=1) |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|
CH4オーバーフロー | CH3オーバーフロー | CH2オーバーフロー | CH1オーバーフロー | AD CLOCK OK | AD BUSY | AD ERROR | AD正常終了 |
0xaff00000(0x08000000)〜0xceffffff(0x27ffffff) *cpuアドレス(VMEアドレス)の設定となっています。
EPICSそのものに対する入門出家入道については専門家に帰依するなり、
コントロールグループのページを参照するなどの自活努力が必要です。
現時点で、KEKBではMV5500用のデバイスサポートはabco3(呪われたSun OS)で
しか開発出来ません。abco3の一般的設定は大変素敵なので、開発には相当の覚悟
と絶えざる忍耐が必要です。
コードを以下に示します。
#include </space/wind221/target/config/mv5500/sysDma.h> #include </space/wind221/target/config/mv5500/universe.h> #include <vxLib.h>
static unsigned long *gplTmpData; /* 256K Word * 4ch(256*1024*2*4/4) */
if ( sysVmeDmaInit() != OK ) { logMsg("sysVmeDmaInit() Error!!\n",0,0,0,0,0,0); return(ERROR); }
gplTmpData = memalign( 256, 524288*4 ); /* 256K Word x 4ch */
設定の関数は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を通さないので、通常のおばかアクセスより大変高速です。今回の 転送は、VME64xで新たに規定されたMBLT(A32 supervisory 64-bit block transfer) なので、AMコードは0x0Cとなります。
if (sysVmeDmaCnfgSet(DCTL_VDW_64 | DCTL_VCT_BLK, DCTL_VAS_A32, DCTL_PGM_DATA, DCTL_SUPER_SUP) != OK){ logMsg("devVme18k11 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)64bit時のメモリーマッピングは32bit時と異なりますので、以下の様に データを取ってきて、その後にwaveformに展開します。
sysUnivVERRClr(); if(sysVmeDmaStatusGet(&pSta) != OK ) { logMsg("sysVmeDmaStatusGet() Error!!\n", 0, 0, 0, 0, 0); } if(sysVmeDmaCnfgGet(&p1,&p2,&p3,&p4) != OK ) { logMsg("sysVmeDmaCnfgGet() Error!!\n", 0, 0, 0, 0, 0); } iDmaStartRc = sysVmeDmaV2LCopy( &cards[cardN].card->call[0], gplTmpData+0, mems * 8 ); if(iDmaStartRc != 0) { logMsg("-->sysVmeDmaV2LCopy() error!! Rc[%d] card[%d] ch1ch3\n", iDmaStartRc, cardN, 0, 0 ,0, 0 ); } for ( ii = 0; ii < mems ; ii++ ) {もしも、64bit MBLTでなく、D32、singleでデータを取ってくる場合は 転送モードをD32 singleにしてus_thing[ii+ 0] = (unsigned short)( gplTmpData[ii*2+1] & 0x3fff ); us_thing[ii + 262144] = (unsigned short)( ( gplTmpData[ii*2+1] >> 16 ) & 0x3fff ); us_thing[ii + 524288] = (unsigned short)( gplTmpData[ii*2] & 0x3fff ); us_thing[ii + 786432] = (unsigned short)( ( gplTmpData[ii*2] >> 16 ) & 0x3fff );}
if (sysVmeDmaCnfgSet(DCTL_VDW_32 | DCTL_VCT_SINGLE, DCTL_VAS_A32, DCTL_PGM_DATA, DCTL_SUPER_SUP) != OK){ logMsg("devVme18k11 error DMA setting\n",0,0,0,0,0,0);}2カ所のメモリーを転送し
iDmaStartRc = sysVmeDmaV2LCopy( &cards[cardN].card->call[0], gplTmpData+0, mems * 4 ); iDmaStartRc = sysVmeDmaV2LCopy( &cards[cardN].card->call[262144], gplTmpData+262144, mems * 4 );データをwaveformに変換します。
for ( ii = 0; ii < mems; ii++ ) {us_thing[ii + 0] = (unsigned short)( gplTmpData[ii + 0] & 0x3fff ); us_thing[ii + 262144] = (unsigned short)( ( gplTmpData[ii + 0] >> 16 ) & 0x3fff ); us_thing[ii + 524288] = (unsigned short)( gplTmpData[ii + 262144] & 0x3fff ); us_thing[ii + 786432] = (unsigned short)( ( gplTmpData[ii + 262144] >> 16 ) & 0x3fff );}
device(bo,VME_IO,devBo18k11,"V18k11") device(mbbiDirect,VME_IO,devMbbi18k11,"V18k11") device(waveform,VME_IO,devWf18k11,"V18k11") device(longout,VME_IO,devLo18k11,"V18k11") device(longin,VME_IO,devLi18k11,"V18k11")
fb5500_DBD += devVme18k11.dbd fb5500_SRCS += devVme18k11.cmakeは以下の様にsrcディレクトリで
gmake vxWorks-ppc604_longとします。なお、何かの呪いでdbdの方は変更しようが追加しようが makeだけでは何もしてくれないようなので、 先にgmake cleanとかした方が良いと思います。 いっぱいwarningが出て鬱陶しいですけど。 初期化ファイルはdev18k11Configで、ベースアドレスが0x24000000で、 IRQ=4、IRQ Vectorが0xF0で9枚使うとすると、
dev18k11Config(9,0x24000000,0x4,0xf0)
の様に指定します。なお、このボードは1枚で2Mバイトもの領域を占有しますので、
他のボードと干渉しないよう特段の注意が必要です。特にTD-4Vのdefaultアドレスは近いし、同じVMEバス上で使う可能性が高いので注意が必要です。
2枚目のボードはVMEアドレスを0x20400000(A22を1にする)、IRQ Vectorを0xF1にと
順次incrementしていきます。IRQは4のまま変更する必要はありません。
subArrayをやめ、EPICSシーケンサでwaveformに分割する場合
のようになります。
注意
VxWorksのメモリー空間は大変呪われていて、まるで昔のべーしっく
のごとく、標準で全てグローバル変数となっています。なので、シーケンサでも
同じ名前の物を二つ動かすことはできません。もしも2つ動かしたければ、
同じ内容で、state名などが異なる、2つのシーケンサをコンパイルして
実行することになります。データベース名は外から渡すことができますが、
内部の変数などは重複していてはダメです(static宣言すれば良いという
説はあるが、ステート名はそうはいかない)。ま、VxWorksの問題という
より、シーケンサの設計がお馬鹿ということかも知れません。
# 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=1048576" # 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_DRMON.db","USER=FB51, CHAN=C0") dbLoadRecords("db/FB_DRMON.db","USER=FB52, CHAN=C1") dev18k11Config(2,0x24000000,0x4,0xf0) dbpf "FB51:ADC4:MEMSIZE","0" dbpf "FB51:ADC4:TRGPOS","4" dbpf "FB51:ADC4:IRQENB","3" dbpf "FB51:ADC4:START","1" dbpf "FB52:ADC4:MEMSIZE","0" dbpf "FB52:ADC4:TRGPOS","4" dbpf "FB52:ADC4:IRQENB","3" dbpf "FB52:ADC4:START","1"測定した入力パワーに対する応答、標準偏差は以下の様になりました。
入力パワーをAM変調(1kHzで45%程度)したときのデータは以下の様でした。
対数表示でもsinはsinっぽく見えるようです。心眼で見ると上下非対称になっている のが分かります(本当か?)。
VMEサイクル間隔は2μ秒程度で、非常に低速です。(低速の CPUをのせているPPC750より遅い)。原因については諸説あり ますが、いずれにしても改善は難しそうです。
Tsundora UniverseIIのDMA機能を使うと、Singleアクセスモード でもCPUを介さないので、かなり高速になります。
アクセスサイクルは、500ns位まで改善しています。
64ビットMBLTアクセスは、VME64xで新たに規定されたモードで、 最初にアドレスおよびAMコードを出し、その後は、ボード側は アドレスラインおよびデータラインを使ってデータを出力し、 DTACKをだし、CPU側はDSでデータ取得完了を通知、すると次の アドレスのデータをボードが出す、というサイクルをASが 下りている間中(最大256サイクルまで)続けるというものです。
この図はMBLTの最初のサイクルを見たもので、CPU側はバスに AMコード0x0Cと最初のアドレスを出力、ボードがDTACKを出すと ブロック転送サイクルがスタート、ボードが自動的に データをアドレスバスとデータバスに出力→DTACK→CPUが データ取得→DS0,1をドライブ→ボードは次のデータを用意、 準備が出来たらDTACKをドライブ、というサイクルを繰り返して います。
statusモードでみてみると始まりは
となり(このVMEアナライザでは、MBLTであるという認識は あるようですが、アドレスラインのステート解析がうまくいかない ようです)1サイクル500ns程度の時間で処理出来ているようです。
ブロック転送なので、規定通り256サイクルで一旦止めてアドレスを 出し直しています。
全部の処理時間については、ボード1枚あたり、32k turnsデータ処理 としてVMEバスアナライザのデータからは以下の様に
呪われたsubArrayをやめて(compactSubarrayをインプリメントしてもらう とか、あるいは長いarrayをそのまま処理することにする)みると
subArrayの代わりに、シーケンサーの中でチャンネル毎への waveform分割を行い(EPICSレコードへも記録する)、平均 標準偏差、ビーム位置(およびその分散)を計算させたところ