ミミックUSB FX2

  公開日 2007/06/08(Fri)
最終更新日 2007/07/16(Mon)

【警告】
 本頁では回路図・プログラム等も公開していますが、各人の環境での動作を保証する ものではありません。 自分なりに応用し、トラブっても自力で解決してください。
何が起きても私は責任を取れません。あくまでも 自己責任で お願いします。
 また、この注意は、同様の注意を明示していない他のページでの保証、及びサポート 義務の発生 を意味するものでもありません。

 念を押しておくと、このページの内容は オプティマイズさんの カメレオンUSB や 使いこなしている人(CPLDの回路や FWをサンプルを参考に自分用を作れるレベル)、 FPGAを使ったことがある人 を対象にしています。

■はじめに
 オプティマイズさんMINI FX2 キット(LP版) と CQ出版 Design Wave Magazine (以下 DWM と表記)2005年1月号の付録基板〜XILINXの FPGA、Spartan-3 XC3S50搭載〜 を 組み合わせて、電源・クロック供給とコンフィグを MINI FX2基板から行えるように しました。

■名称について
 まずUSBアナライザを作りましたが、これはあくまでアプリ (応用)のひとつであり、FPGAと EZ-USB FX2に任意の回路・FW を書き込んでいろんな 事に使えるように考えています(後が続くかは保証の限りではありません)。
ほとんどの人には説明不要だと思いますが、これはオプティマイズさんの カメレオンUSB をそのまま踏襲しただけです。オリジナルの カメレオンUSB が EZ-USB + CPLD の 組み合わせなのに対し、こちらは EZ-USB FX2 + FPGA になります。

これまで 不定期ログ のページで仮に「カメレオンUSB FX2(嘘)」 と呼んでいましたが、 オプティマイズさんが、本家カメレオンUSB FX2 を開発された時に迷惑をかけると いけないので、アプリ公開を機に 「ミミックUSB FX2」と 呼ぶことにしました。

    「カメレオンUSB」のように、回路と FWの変更でいろいろなアプリに変身できる
    意味と、「カメレオンUSB」自体を真似ている・偽者 の意味を込めています。
ミミックUSB FX2
ミミックUSB FX2 外観
MINI FX2 + ユニバーサル基板 +
DWM 付録基板2005JAN(裏側)

■ミミックUSB FX2 の概要
【追記】XC95XL144 は 5V入力トレラント(5V信号を直接入力 しても大丈夫)ですが、XC3S50/XC3S250E はそうではありません。  入力できるのは 3.3V信号まで(一部のピンは 2.5V信号まで)なので注意


ハード編

 ミミックUSB FX2 の製作方法と、ソフト編に登場するソースファイルの
ダウンロードについては USBアナライザを作るにまとめました。

【追記】  DWM 2007年7月号付録基板(2007JUL)での配線方法(仮・暫定レベル)、プログラムを追加しました。


ソフト編

■ホストアプリ
 EZ-USBとの I/Fは 21xx系 FX2系共通項でまとめた mmcusb.c と、 ミミックUSB FX2 だけで必要になるパートをまとめた mmcusbfx2.c に分けて います(+ヘッダファイル mmcusb.h )。 オプティマイズさんの cusb.c をベースに改造させて頂きました。

    特長
  1. mmcusb.c は EZ-USB 21xx系 と FX2系両方に対応
    mmcusb.hをインクルードする前に
     21xx系で使う場合 マクロ EZUSB_21xx を、
     FX2で使う場合、マクロ EZUSB_FX2 を宣言します。
    #define を使うか Cコンパイラの -Dオプションを使います。

    宣言せずにコンパイルすると、トラップが発動して usb_open()関数が必ずエラー終了 するので注意。 また、mmcusb.h が参照する ezusbsys.h のパスもオリジナルとは異なるので 各自自分の環境に合わせて修正が必要です。

  2. 半自動的に 21xx系EZ-USB と EZ-USB FX2 を見分けて接続デバイスを選択可能
    この機能は 1台の PCに複数の EZ-USBを接続しているときに有効です。
    簡易的には cusb_init() / mmcusbfx2_init()関数でデバイス番号を -1にすればいいです。
    どのようにしているかはソースを読んでください。ソースを読めば更に 進んだ機器選択が可能になるヒントになると思います。
    mmcusb.c の中にある ezusb_check()関数 が肝です。
    尚、自動選択のために 使用する FWのディスクリプタ VID/PID を適切に 設定しておく必要があります(FW修正)。
mmcusb.c が提供する関数
 オリジナルの cusb.c に元からあった関数は、ほぼ同じ使いかたなので省略します ソースを見てください (【追記】 返り値の仕様を変更 しているものもあり)。以下、mmcusb.c で追加した関数のみ説明します。

int usb_pipe_info( HANDLE *h, s32 sw, s32 pipeno, s32 *dirno,
  s32 *type, s32 *pktsz )

機能 パイプ情報を取得
引数
h  オープンした EZ-USBのデバイスハンドル
sw  0:初回実行または 毎回ちゃんと OSから情報を取得する場合
 0以外:前回取得済であれば再利用する。
pipeno  調査するパイプ番号(0-n)
dirno  返り値情報 IN/OUT方向とエンドポイント
 bit7 (0x80)が立っていれば IN でなければ OUT
 bit3-0(0x0F) EndPoint番号(0-15)
type  返り値情報 エンドポイントの種類
 0:CTRL 1:ISO 2:BULK 3:INTERRUPT
pktsz  最大パケットサイズ(byte)
 USB1.1接続なら最大でも 64
 USB2.0ハイスピード接続バルク転送なら最大 512
返り値 ステータス
 0:取得成功  0以外:エラー
備考  オープンした FX2が本当に USB2.0ハイスピード接続されているか
 の確認用に用意しました(パケットサイズでチェック)。
 そのほか、必要ない情報の引数(ポインタ)は NULLにできます。


int usb_getvidpid( HANDLE *h, int *vid, int *pid )
機能 VID/PID情報を取得
引数
h  オープンした EZ-USBのデバイスハンドル
vid  返り値情報 ベンダーID(0000-FFFF)
pid  返り値情報 プロダクトID(0000-FFFF)
返り値 ステータス
 0:取得成功  0以外:エラー
備考  必要ない情報の引数(ポインタ)は NULLを
 指定できます。


int ezusb_check( char *fwname, char *fwver, EZUSBLIST *ezp )
機能 EZ-USBデバイスの接続状況を調べる
引数
fwname  探したい FWの名称(ストリングディスクリプタ)
 特に決まっていない場合、NULLを指定してもよい。
fwver  探したい FWの名称(ストリングディスクリプタ)
 特に決まっていない場合、NULLを指定してもよいが、
 fwname を NULLにしていればこちらも自動的に無視される
ezp  EZ-USBの探索結果を格納する構造体へのポインタ
 見つかった EZ-USBは FWの合致や VID/PID別に分類されます。
 詳しくはソースを見てください。

返り値 ステータス
 0:取得成功(結果は ezp)  0以外:エラー ezpは不定
備考  EZ-USBのオープン前に適切な相手を見つける為の情報を得る関数です
 ezusb-0 〜 ezusb-7 までの8台分しか調べませんが実用上は十分だと
 思います。

int ezusb_finddev( EZUSBLIST *ezp, int *pril )
機能 EZ-USB接続状況を、指定した優先順位に従って走査し、
 オープンすべき EZ-USBのデバイス番号を返す
引数
ezp  ezusb_check()で取得したデバイスリスト構造体のポインタ
pril  選別優先順位リスト
 NULL を使うと mmcusb.c 内にある 21xx系 / FX2系のデフォルト優先順位
 dev_pri[] を使用する。
返り値 デバイス番号
 0〜7:取得成功で、そのデバイス番号の EZ-USBが選別結果
 <0(負の値):選別エラー
備考  デフォルト優先順位は 1)FWNAME/FWVER が一致するもの
 2)21xx系/FX2系 の FWが未ダウンロードのもの  3)21xx系/FX2系 の FW
 ダウンロード済のもの 〜 の順で探します。
 同じ条件が複数ある場合、番号の若い方を優先するのでルールを変えたい
 場合は自分で関数を作ってください。

int ezusb_autoselect( s8 *fwname, s8 *fwver )
機能 使用する EZ-USBデバイスを自動選択する
引数
fwname  探したい FWの名称(ストリングディスクリプタ)
 特に決まっていない場合、NULLを指定してもよい。
fwver  探したい FWの名称(ストリングディスクリプタ)
 特に決まっていない場合、NULLを指定してもよいが、
 fwname を NULLにしていればこちらも自動的に無視される
返り値 ステータス or デバイス番号
 <0(負の値):エラー
 下位16bit : 選別したデバイス番号
 上位16bit : 一番若い空きデバイス番号
備考  ソースを見れば分かるように ezusb_check() と ezusb_finddev() を
 組み合わせただけです。デフォルト優先順位を使用します。

 返り値は mmcusbfx2_init()に与える前に 上位下位分離してください。
 上位の値は ndevno の候補値です。


mmcusbfx2.c が提供する関数(ふたつ)
 mmcusbfx2.c には ミミックUSB FX2 専用の関数(コンフィグ+FWダウンロードを まとめて処理)が収録されています。  必ず、FX2用にコンパイルした mmcusb.c と一緒にして使います。

int mmcusbfx2_init( int devno, int ndevno, HANDLE *h, BYTE *fw, char *fwname,
  char *fwver, BYTE *bit, int bitsize )

機能 ミミックUSB FX2 の FPGAコンフィグと 本命FWダウンロードを
 まとめて行う
引数
devno  EZ-USBのデバイス番号(0-7)を指定します。
 -1を指定すると自動選択します。
ndevno  devno より若い番号が空いている場合、FWダウンロードによりデバイス
 番号が移動してしまうことがあります。前もって移動先の番号が分かって
 いる場合に、この引数で指定します。不明なら -1を指定しておきます。
 失敗してももう一度プログラムを実行すれば今度は成功するかもしれません。
h  オープンする EZ-USB FX2のデバイスハンドルを記録するものです。
fw  FPGAコンフィグ後の 本命FW の格納配列を渡します。
 FWサイズは mmcusb.h にて 1000h(4096バイト)に限定しているので、
 必要ならば修正してください。
fwname  本命FW のストリングディスクリプタ[1] の文字列です。
 通常、FWの名称を割り当てておきます。合致していなかったら FPGAコンフィグ
 からやり直します。
fwver  本命FW のストリングディスクリプタ[2] の文字列です。
 通常、FWのバージョンを意味します。合致していなかったら FPGAコンフィグ
 からやり直します。
bit  FPGAのコンフィグデータです。ISE WebPACKで作成した bitファイル
 そっくりそのまま Cの1バイト配列に格納したものを渡せばいいです。
 iMPACTで XSVFファイルに変換する必要はありません。
 StartUpは JTAGにしておいたほうがベターですが、しなくても動きます。
bitsize  FPGAのコンフィグデータサイズをビット単位の数値で渡します。
 bitファイル のファイルサイズを8倍すれば OKです。
返り値 ステータス
 0:成功  0以外:エラー
備考  新設した ndevno, bit, bitsize 以外は カメレオンUSBの cusb_init() と同様です。
 また、プログラム終了の際は usb_close() を使います。
 FPGAコンフィグに FX2jtag.DLL を使用し、XILINX Spartan-3専用です。

int mmcusbfx2_devno( void )
機能 オープンしたデバイス番号の確認
引数 なし
返り値 0-7:mmcusbfx2_init()で最終的にオープンした EZ-USB デバイス番号(0-7)
 -1:未オープン または オープンに失敗
備考  本関数は FWダウンロードでデバイス番号が移動した場合に備えたものです。
 mmcusbfx2_init() 成功した直後に呼んでください。



FX2用FW (の修正)

●FW修正点 : FW.c について
 オプティマイズさんが開発された FX2FW(F2FW - V100) はそのままでは  ミミックUSB FX2 では使うことができません。 何故なら、FX2FW は CypressのサンプルFWをベースに作られていますが、 Cypressがわざわざ、21xx系EZ-USBのサンプルコードから新しく追加して下さった (←ここ Cypressへの嫌味)不都合が残っているからです。
この不都合は EZ-USB FX2を単独で使用する場合は表面化しないのですが、  ミミックUSB FX2 として使う場合には必ず問題になります。
Cypressサンプルをベースに独自の FWを開発する場合(オプティマイズさんの FX2FWを 使う場合を含む)は、必ず修正が必要です。

不都合の内容
ミミックUSB FX2 として使う場合に表面化する不都合(不都合でなく 不具合 と言いたいが)とは、
    FW未ダウンロード状態の EZ-USB FX2へ一番最初にダウンロードした FWは動くが、 そこから更に別の FWをダウンロードしてもうまく動かない
ことです。もちろん、後者の FWも、初めてダウンロードする場合は正常に動くものです。
確認方法は
こちらへ

この不都合の原因は、FX2での CypressサンプルFWでは 21xx系のそれと違って、初回の FWダウンロード→CPU リセットの回でしか ReNumerationTM  しないためです。
21xx系/FX2 両方とも FW.c 内の EZUSB_Discon()関数呼び出し がこれを担当 していますが、FX2用では該関数呼び出しが 21xx系には無かった if文で囲われています。
この if文 "if (!(USBCS & bmRENUM))" をコメントアウトして FWをビルド(コンパイル)して やると、2回目以降の FWダウンロードでもちゃんと ReNumeration するので、正常に 動くようになります。

●FW修正点 : dscr.a51 について
 サンプルFWを構成するもうひとつのソースファイル dscr.a51 はアセンブリ 言語用のものです。このファイルで、VID/PID(ベンダID/プロダクトID)やストリング ディスクリプタなどのディスクリプタ(USB機器の仕様情報)を記述しています。
FW.c と違って、致命的なものではないのですが、利便性を上げるために以下4点を修正します。

具体的な修正点が知りたい人は USBアナライザのページで TUSBanaのソースを DLして  Cypressオリジナルと比較してみてください。
  1. VID/PIDの変更
    (Cypress自身が間違えてるので勘弁して欲しい所ですが、)FX2用サンプルFWでは  VID/PIDが 0547/1002 になっています。 これは本来 21xx用サンプルFW向けに用意された ものの筈です(詳細はこちら)。 04B4/1002 に変更しておきます。 → DeviceDscrブロック

  2. ストリングディスクリプタの Index
    カメレオンUSBでは(ミミックUSB FX2も)FWの種類を FWNAME(FW名)文字列と FWVER (FWバージョン)文字列で識別します。 それはいいのですが、Windowsのデバイスマネージャから見ると、FWVERの方が表示 されてしまい、面白くありません。
    そこで dscr.a51 の該当箇所を修正して FWNAME の方が表示されるようにしています。
    これも DeviceDscrブロックになります。

  3. 消費電流の変更
    ミミックUSB FX2では、MINI FX2 だけでなく FPGAへの電源供給も行うので デバイスの要求電流を 最大の 500mAに上げておきます(数値は 1/2の 250)。 これは HighSpeedConfigDscrブロックにあります。

  4. EVENマクロ
     FX2では DeviceDscr、DeviceQualDscr, HighSpeedConfigDscr、FullSpeedConfigDscr、StringDscr の 5つのラベルが全て必ず偶数アドレスに 配置されていなければなりません (理由はこちら )。 これを知らずに dscr.a51 を編集して、エンドポイントの数を奇数にするとハマります (実際、自分がハマった)。 各ラベルの前に、アドレスを調整する命令を入れておきます。


JTAG DLLの仕様

 ミミックUSB FX2のために作った FX2用 JTAG DLL FX2jtag.DLL の仕様です。
繰り返しますが、オリジナルは ザイリンクスでいこう(ページ作者 さとうさん)提唱の JTAG I/F用DLLです。
以下関数仕様を説明します。青字で記述した部分はこちらで 勝手に拡張した部分です。
さとうさん認可の 正式仕様ではない ので注意してください。

DWORD jtag_version( void )
機能 ドライバのバージョン取得
引数 なし
返り値  上位16ビット:メジャーバージョン BCD4桁
 下位16ビット:リリースコード BCD4桁
備考  FX2jtag.DLL では勝手に 1.15 を名乗っています。

int jtag_init( DWORD port_address, DWORD baudrate, char *probe_name )
機能 JTAG I/F 初期化
引数
port_address  ポート番号(FX2jtag.DLL ではEZ-USBの
 デバイス番号。 0,1,2,... 尚、-1 なら自動で探す
baudrate  0:ドライバ依存
 0以外:TCKの通信速度の最大値を指定、単位は Hz(ヘルツ)
 ドライバはこれ以下の値に調整する。
  FX2jtag.DLL では速度固定なので、指定の有無に
 関係なく 2MHz 。
probe_name  プローブ(JTAG I/F)名称を格納するポインタ
返り値 ステータス
 0:OK  0以外:エラー
備考  probe_name にドライバー名を設定する。
 実際の TCK通信速度は後述の jtag_config()で 調べられる。
 jtag_config()で後から変更することもできる(仕組みだけ用意)。

int jtag_power( void )
機能 ターゲット電源チェック
引数 なし
返り値 ステータス
 1:ON  0:OFF または異常
備考  FX2jtag.DLL では常に 1を返す(電源端子を見ていない)
 さとうさんの「JTAGドライバDLL仕様」のページでは返り値が逆に
 なっていますが、実際は(ソースを見ると)こっちの様です。

int jtag_xfer( const BYTE *ibuf, BYTE *obuf, DWORD drsize, int tms_s, int tms_e )
機能 JTAG送受信
引数
ibuf  NULLのとき、TDIへの送信データは任意、
 NULL以外の時、TDIから送信するデータのポインタ
 送信データはデフォルトで MSBファーストで送信される。
obuf  NULLのとき、TDOからの受信処理不要
 NULL以外の時、TDOから受信したデータを格納するポインタ
drsize  総送信ビット数
 但し、obuf が NULLの場合、すぐには通信せず一旦バッファに貯める。

 実際に JTAG通信を行うには 本引数を 0で呼び出す(フラッシュ)。
 また、内部バッファが溢れた時、obufが NULL以外で呼ばれた場合も自動的に
 フラッシュされ、通信内容の順序関係は保証される。
 後述の jtag_wait()により、通信の合間のウエイト実施も保証される。
tms_s  最終ビット以外の TMS信号レベル 0=LOW、1=HIGH
tms_e  最終ビット送信時の TMS信号レベル 0=LOW、1=HIGH
返り値 ステータス
 0:OK  0以外:エラー
備考  jtag_config()で通信ビット順序を LSBファーストに変更可能
 (PlayXSVF 対応のため)

int jtag_txrx( const BYTE *ibuf, BYTE *obuf, DWORD drsize, int tms_s, int tms_e )
機能 JTAG送受信 旧方式
引数 jtag_xfer()と同じ。但し
 ibuf は jtag_config()に関係なく送信データは MSBファースト、
 obuf は jtag_config()に関係なく受信データは LSBファーストで
 格納される。 バッファリングして、 drsizeを 0で呼び出すと
 フラッシュするのは有効
返り値 ステータス
 0:OK  0以外:エラー
備考  互換性のために残していますが、私(シバ某)は使ってないので
 全然テストしていません。

void jtag_end( void )
機能 JTAG DLLの使用終了
引数 なし
返り値 なし
備考  通信データがバッファに残存していた場合、まずフラッシュしてから
 終了します。


    ここまでの関数はオリジナル版に存在するものです。
    以下のふたつの関数は、私(シバ某)が勝手に追加したもので、 青字でなくても全て新規仕様です。


void jtag_wait( int utime )
機能 指定時間待つ
引数 待つ時間値。単位は μs MAX256
返り値 なし
備考  通信データのバッファリング機能のために、ウェイト時間管理も DLLが受け持ちます。
 尚、本関数は TCKパルスを発生させません
 XILINX FPGA の Startupシーケンスで、TCKパルスが必要な場合は、
 別途 jtag_xfer()関数を使う必要があります。


int jtag_config( int mode, DWORD var )
機能 JTAG-DLL動作設定 情報取得もろもろ(コンフィグ≠FPGAのコンフィグ)
引数
mode 書き込み動作の場合、CFG_WRITE + CFG_xxxx、
 読み込み動作なら CFG_READ + CFG_xxxx を指定。 xxxxは下の表参照
var  書き込み動作では書き込み用 data
 読み込み動作時は結果を格納するために ポインタ変数のアドレスを
 キャストして渡す

返り値 ステータス
 0:OK(未対応につき無視、を含む)  0以外:エラー
備考  modeで使う定数は JTAGDLL.h で定義しています。
 modeによる個別動作は下の表を見てください。

引数動作
CFG_STAT 統計情報
WRITE 記録値を 0クリア
READ 以下の値が格納された DWORD配列へのポインタを返す
 [0] bitlen JTAGで通信した総ビット数
 [1] wait I/F側でウェイトさせた 回数
 [2] called jtag_xfer/jtag_txrx を呼んだ回数 但し フラッシュ動作の回数は除く
 [3] flush フラッシュ回数。 called と絡めると合体率が分かる
 [4] txrx jtag_xfer/jtag_txrx を送受信ありで呼んだ回数
 [5] tms  jtag_xfer/jtag_txrx を TMS(JTAG-TAP)を制御する目的で呼んだ回数
 [6] pktsz 送信パケットサイズ(USB利用 I/F のみ有効 違うなら 0)
 [7] pktnum 送信したパケット数(USB利用 I/F のみ有効)
 [8] pktnet 送信パケットの内、有効データのbyte数(同上)

 [備考] USBのパケットのデータ効率(充填率)を
  pktnet / (pktsz * pktnum) x 100(%) で求めることができる
CFG_SPEEDI JTAG通信スピード設定 INDEX版
READ I/F側が用意している (I/Fで使用可能な)TCK周波数値の配列
 (型は DWORD [])へのポインタを渡す。 テーブルは、最高周波数から最低周波数へ
 列挙していき、最終は 0で終わる 単位は [Hz]

WRITE var を Indexとする物に変更 (0 から始まる)
 (DWORD)-1 や範囲外を渡すと I/F(DLL)のデフォルト値にする
 デフォルト値にする目的以外では、先に READでテーブルを得てから使うべき
CFG_SPEEDV JTAG通信スピード設定 数値版
READ 現在の TCK周波数の設定値 [Hz]を返す
WRITE I/Fが設定できるTCK周波数の中から、var[Hz]を超えない速度に設定
 var=0 か 指定値にできない場合(I/Fの最低速度よりも遅い場合)などは
 デフォルト値に戻す。
 従って、実行後は念のため READで設定を確認するのが望ましい。
CFG_MESSW メッセージスイッチ(デバッグ用)
READ なにもしない
WRITE
 0(デフォルト):なにもしない
 0以外:数値に応じてI/Fが 動作毎にコンソールに情報を表示する
 どういう風に実装するかは I/F側の自由。
CFG_MSBLSB jtag_xfer() での通信ビット順序変更
READ なにもしない
WRITE
 0以外(デフォルト):MSBファースト
 0:LSBファースト に変更
CFG_IFNAME I/F名称取得
WRITE なにもしない
READ varを使って文字列 ptを返す
 文字列内容は jtag_init() の probe_name と同じか それに類するもの

 通信速度(TCK周波数)については要求に従って変更できるように体裁を 用意しただけで、FX2jtag.DLL では 常に 2MHz固定です。
但し、この数値はTCK波形の一番短い部分(LOW幅が0.25μs)から求めたもので、 実効通信速度は最速(送信専用時の場合)で 1.55MHzです。
このように、TCKの波形がデューティ比50%でない場合は、短いほうの時間幅 から求めた値の周波数テーブルを作成するのがいいでしょう。

以前作った カメレオンUSB版は 6MHz/12MHz切り替え可能なので、時間があれば この仕様にて作り直す予定です。

バッファリングする理由
jtag_xfer() / jtag_txrx() で 送信のみの通信をバッファリングするのは、FX2jtag.DLL が  USBを経由する I/Fなので 1ms単位 もしくは 125μs時間間隔の「(マイクロ)フレーム」に実行 時間が縛られるためです。 バッファリングによって、EZ-USBに送る JTAG通信パケットをまとめて一気に送ることで 処理時間を短縮させることができます。そのために指定時間のウェイトも jtag_wait()を 用意し、コマンドとして EZ-USB側に送って待たせます(256μsを超える場合、分割して 呼ぶか、まずフラッシュさせておいて、PC側で待つ)。
バッファリングは特にコマンドが小ビット数の通信に分割される CPLD相手の場合効果が 大きいです(FPGA〜ミミックUSB FX2〜 では効果が小さい)。
プリンタポート等、リアルタイムにJTAG通信が実行できるI/Fを使うのなら、 バッファリングしても時間短縮の効果は出ません。

【注意】 プログラム終了前に呼ぶ jtag_end() でフラッシュも実行されるが、 関数から帰ってきても FX2側はたぶんまだ JTAG通信処理をしています。  ミミックUSB FX2 では、すぐに別の FWに書き換えようとして JTAG通信完了前に 中断させてしまう恐れがあるので、ダミーで jtag_xfer()を受信付で呼び出して、 フラッシュと JTAG通信が確実に完了するのを待つようにしています。

〜〜〜〜〜〜
    なにか、こう、 htmlにまとめたものを改めて眺めてみると…、 「ミミックUSB FX2」として使う場合は、追加・拡張した仕様が殆ど性能の向上に寄与していない!!
    最初、カメレオンUSB用に拡張版で作ったのですが、このときは XC95108相手に、 かなりの改善効果がありました。
    それをベースに、さらに仕様を整理しながら FX2用に作り直したらこうなってしまいました。
    いまさら、さとうさんのオリジナル仕様に合わせて書き直すのも面倒なだけなので 勘弁してください。
〜〜〜〜〜〜

【追記】
 2007/06/08(Fri)公開版の FX2jtag.DLL は jtag_xfer()などの受信方向の通信が正常に 動作していませんでした(USBアナライザでは動作に影響なかった)。
修正版を こちらのページからダウンロードできます。

尚、仕様を変えた訳ではないので jtag_version() の返り値は 1.15(0001/0015) のままです。
代わりに jtag_init() の probe_name の先頭に ”2007/JUL” の文字列を追加しました。
FX2jtag.DLL のタイムスタンプは 旧:2007-06-05 新:2007-07-06 です。


■参考資料(本文に登場しなかったもの)
「トランジスタ技術 1995年2月号 」 CQ出版
  "バウンダリ・スキャン・テスト方式とロジック設計" 小川 和彦 p.295-
USBターゲット機器開発のすべて」  CQ出版
 他 CQ出版の雑誌いろいろからつまみ食い
「XAPP058.pdf eisp_pc.zip(PlayXSVF)」 XILINX



以上。