2012年05月23日

MPSSEめも

いままで作ってきた コードは、Synchronous BitBang(以下 SYNCBB) Mode を使っている。FT2232H でも FT232H でも SYNCBB は持っているので、コードはそのまま使えるのだ。

遅いという問題はあるが、実用上さほど問題になることはないと思っている 。FT2232H とか使ったら それなりに高速になる。ただ、UM232H とか安価な モジュールも出てきたし MPSSE を使ってみたいような気もしている。MPSSE は、JTAG ケーブルで良く使われているが、実際どういう機能なのか知りたくも思っていた。まずは、どのように使うものなのか調べていこう。

初期化:

    SYNCBB も MPSSE も FT_SetBitMode() を使ってモード設定する。だから、FT_SetBitMode() するまでの手順は、どちらも共通なのだ。

    FT_SetBitMode() で MPSSE モードにした後は、送受信するデータの意味が SYNCBB とは違う。

  • AN108: Command Processor for MPSSE and MCU Host Bus Emulation Modes

    このドキュメントがその詳細。初期化に必要そうなコマンドをちょっと抜粋しておこう。

  • GPIO の設定と読み出し (初期値の設定)
    MPSSI で使う TCK/TDI/TDO/TMS を含めて ADBUS/ACBUS (BDBUS/BCBUS) の設定と読みだしが出来る。


    Set Data bits LowByte 0x80 Value Direction
    Set Data bits HighByte 0x82 Value Direction
    Read Data bits LowByte 0x81
    Read Data bits HighByte 0x83

    LowByte は、ADBUS の Bit番号に対応し、HighByte は ACBUS の Bit番号に対応する。
    また、ADBUS の bit0 - bit3 は、 デバイスにかかわらず TCK/TDI/TDO/TMS が割り当てられる。Direction は 各bit の値が、1 で出力 0 で入力。

      ここで注意点がある。RS232C のモードだと TXD/RXD/RTS/CTS に割り当てられている。bit2 TDO はデバイスからの出力 だが、RS232C でも RTS でホストからの出力でぶつかるのだ。

      なので、一般的には シリアルに割り当てないように EEPROM の設定が必要になる。

  • クロックレートの設定
    FT_SetBaudRate とは別に クロックレートの設定をしなければならない。

    Clock 30MHz 0x8A
    Clock 6MHz 0x8B (default)
    Set TCK/SK divisor 0x86 ValueL ValueH

    0x8A/0x8B は、FT2232D にはない モードで ベースクロック値を変更する。0x86 の Value はこのクロックに対して分周する値(-1)。bit clock を 1 MHz に設定したければ、5 を設定する。30 MHz にした場合は、29。

    この説明は、正確ではないがだいたいこんなもの。

    GPIOの設定 の周期が、この設定で変わるのかどうかは不明。

  • ループバックの設定
    デバッグの初期にしか必要ないと思えるのだが、TDI と TDO を内部でつなげるモード。

    Loopback Enable 0x84
    Loopback Disable 0x85

    ひょっとしたら 初期化で Disable にしないといけないかも。

  • 2232D にない機能
    2232D にない機能は、無視してよいかと思ったのだが、気になるものがあるので、追記


    Enable 3 Phase Data Clocking 0x8C
    Disable 3 Phase Data Clocking 0x8D

    他にもあるが、とりあえず。

データの入出力

    データの出力方法に様々なパターンがあるのだが、JTAG で使いそうなものだけピックアップ。

    Clock Data Bytes Out on +ve clock edge LSB First (no read)
    0x18 LengthL LengthH byte1 .... ByteN
    Clock Data Bytes In on -ve clock edge LBS FIrst (no write)
    0x2C LengthL LengthH
    Clock Data Bytes In and Out (Out +ve / In -ve)
    0x3C LengthL LengthH byte1 .... ByteN

    Clock Data Bits Out on +ve clock edge LSB First (no read)
    0x1A Length byte1
    Clock Data Bits In on -ve clock edge LBS FIrst (no write)
    0x2E Length
    Clock Data Bits In and Out (Out +ve / In -ve)
    0x3E Length byte1

    -ve clock edge とは TCKの 立下り(↓)だと思えるが、説明はないようだ。8bit 単位でない操作は、bit mode を使う。それぞれの mode は、Out/In を行うかどうかで 3 通りがある。 byte mode に設定できる Lehgth は 1 〜 65535。bit mode は、1 〜 7 。

    基本はこの 6 種類で済むはずだが ... ルールがあるのでそれについて

    bit0 : -ve CLK on write
    bit1 : 0 byte mode / 1 bit mode
    bit2 : -ve CLK on read
    bit3 : 0 MSB First / 1 LSB first
    bit4 : DO write TDI
    bit5 : DO read TDO
    bit6 : DO write TMS
    bit7 : 0

    ピックアップした 6 つは、

    0 x x x 1 1 x 0

    のパターンが基本。ただし no read の場合は、bit2 は 0/1 どちらでも良いのかも知れない。 あと 出力は TMS 入力は TDO というパターンがある。TDI/TMS とも write に設定するとどうなるのか? ... 説明は見つけられていない。

rtavr_tools とのマッピング

    rtavr_tools での CABLE ドライバのインターフェイスは、次のように決めている。

    open
    close
    delay bitclock ベースの遅延
    put_tdi_bits TDI ストリームの出力 , Read あり/なし
    put_tms_tdi_bits TDI+TMS ストリームの出力 , Read あり/なし
    setup_port TCK/TDI/TMS の値を設定。
    setup_gpio INIT/PROG/M1/M2 と名付けた GPIO の状態設定
    get_gpio      INIT/PROG/M1/M2 と名付けた GPIO の状態取得
    set_bitclock bitclock の設定

  • put_tdi_bits

    上に書いてないが、最後のビットだけ TMS を H にするオプションがあり、JTAG では良く使われる。

    コマンドの組立てを考えると...

    MPSSE_PUT_BYTES (MPSSE_PUT_GET_BYTES read あり)
    :
    MPSSE_PUT_BITS (MPSSE_PUT_GET_BITS read あり)
    (TMS_HIGH オプションの場合 の追加)
    MPSSE_SET_LOW
    MPSSE_PUT_BITS (MPSSE_PUT_GET_BITS read あり)
    MPSSE_SET_LOW

    こんな感じになる。ただし、bit 数によっては、MPSSE_PUT_BYTES / MPSSE_PUT_BITS のどちらかがない場合がある。read なしの場合は、単に一気に 送れば良いのであまり問題でないのだが ...

    read ありでは、read データを解析しないといけない。MPSSE_GET_PUT_BYTES / MPSSE_GET_PUT_BITS がどういう組み合わせになっていようが、綺麗なビットマップになる。TMS_HIGH オプションがあると 1 bit 分のデータがそれにくっつく。... これぐらいだったら、BitBang 用として作ったものをベースに改造すればいけそうだ。

  • put_tms_tdi_bits

    これは、JTAG の ステートを変更する 時に使っている。操作するビット数はあまり多くない(最大 10bit)が、jtag の API がステート + TDI ストリーム という構造なので、put_tdi_bits と同じような頻度で使われることになる。

    もともとの仕様は、read あり になっているのだが ... どう実装するのが良いのだろう?

    (bit 数分のくり返し)
    MPSSE_SET_LOW (TMS が 変化する場合のみ)
    MPSSE_PUT_GET_BITS (1bit 分)
    MPSSE_SET_LOW (TMS を最後の状態に戻す)


    read の結果には MPSSE_SET_LOW は関係せず、1 バイト 1bit と決まるから、解析は難しくない。

    これで一応仕様を満たすことにするが ... 実は read ありは使っていない。read が入らなければ、write が連続で出ることになり、レイテンシは無視できる。BitBang だと write した分は、かならず read が入る。たぶんこの理由で、MPSSE の方が速くなりそう。

      ところで、JTAG の ステート変更では、TMS のみを TCK で出力するパターンを使う。そうであれば、TMS を変化させる コマンドを使った方が効率が良い。

      ただ、API まで変えるつもりはないので、TDI が全部 0 のとき TMS を変化させるコードにする .. とか最適化のひとつと考えておく。

  • delay
    クロックを発行しつつ delay する というコード。MPSSE_GET_BITS を必要クロック分発行すれば良さそう。ただし、実装する必要はなくオプション。

    実装されていなければ、put_tdi_bits で代替する。

  • setup_port / setup_gpio / get_gpio

    BitBang 用のコードをベースにすることで、簡単につくれる。

    ちなみに、INIT/PROG/M1/M2 は、Xilinx の信号線をベースに決めている。どのように操作するかは、

    (cbl->setup_gpio)(cbl, CABLE_GPIO_PROG, -1);
    (cbl->setup_gpio)(cbl, CABLE_GPIO_M2, 1);
    (cbl->setup_gpio)(cbl, CABLE_GPIO_M1, 0);
    (cbl->setup_gpio)(cbl, CABLE_GPIO_PROG, 0);
    (cbl->setup_gpio)(cbl, CABLE_GPIO_PROG, -1);
    (cbl->setup_port)(cbl, 1, 0, 0); // TMS = 1, TDI = 0, TCK = 0;

    こんな風に固定にしている。-1 は HI-Z (入力) 、あと config ファイルでの割り当てがなければなにもしない。それに加えて論理を逆にする config の設定がある。

(おまけ)I2C の考察

    I2C のコードはますます作る気はないが、メモ。

    MPSSE_SET_LOW/MPSSE_SET_HIGH は、アトミックに 方向を切り替えられる。だから L または HI-Z (入力) という操作は簡単にできる。読み込みの MPSSE_GET_LOW/MPSSE_GET_HIGH も期待通り同期してくれるだろうから、似非 I2C マスターのコードは簡単そうだ。

    似非 と書いたのは、ちゃんと作ると SCL を H にしたい場合は H になったことを確認しないといけないから。読み込みの結果によってループするようなコードにすると、USB は極端に遅くなる。だから、応答性能 の保証がないデバイス相手だと、ちょっと面倒なことになりそう。

    対策としては、遅くなるのを覚悟で、H になったことを確認する (1)。このパターンだと すごく遅くなるだけでなく、AVR USI を使うときに AVR も止まるという弊害がある。

    もうひとつは、delay をちゃんと計算する(2) 。AVR USI 相手 だと、割り込みが起きる フレームの最初のところだけ遅くして、あとは 普通にするとか。たぶん このやりかたが適切だろう。
posted by すz at 21:45| Comment(0) | TrackBack(0) | artemis
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
この記事へのトラックバックURL
http://blog.sakura.ne.jp/tb/56030282
※ブログオーナーが承認したトラックバックのみ表示されます。

この記事へのトラックバック