USBデバイス・コントローラ MAX3421E


 PCが実用的なものとして一般に出回ってきた初期の頃、PC本体と周辺デバイスとのインターフェースには、COMポート、プリンタポート、IEE1394、PS/2、D-SUBなどがあり、それぞれ異なった規格で動いていました。従って、それらを動作させるためには、それぞれのインターフェース規格に合わせて、バスを駆動する回路やドライバソフトウェアを用意する必要がありました。USBバスの規格がリリースされたことにより、周辺機器はインターフェースとしてUSBバス規格にのみ対応すれば良いようになり、設計するエンジニアにとっては非常に便利になったように思いますが、個人でUSBインターフェイスを実装しようとする利用者側にとっては、USBバス規格は、手の届かないブラックボックス化した理解しがたいいものになってしまったように思います。近年、パソコン以外の携帯電話、タブレット、ゲーム機、組み込みシステムなどの電子機器にとっても、他デバイスに接続する場合の主流はUSBになりつつあり、USBは必須の構成要素になってきており、USB規格への理解を深める必要性に迫られているように思います。詳しくは、http:///www.usb.org/developpers/docs.html (あるいは、「USB Hardware & Software 日本語版」:1999年初版 発行:インフォクリエイツ 定価30,000円)に記載されています。



    (1)USBホストシールド

    (2)USB通信の説明


    (3)MAX232Eの取り扱い上の注意点


    (4)コマンドの処理の作成手順


    (5)プログラミング処理の基本


    (6)応用プログラミング処理



(1)USBホストシールド

 USBデバイス・コントローラICとは、USBデバイスに必要とされる4本の信号線(VBUS、D+、D-、GND)に接続し、CPUからの制御信号に従ってデータを送受信したり、USBバス上で発生するイベント等をCPUに送る役割を果たすICです。
 アナログ・デバイセズ(MAXIM)、テキサス・インスツルメンツ(TI)、FTDI、Microchipなど、数多くのメーカ−から同様の製品が出ています。MAXIMのUSBデバイス・コントローラIC製品としては、MAX3420、MAX3421があります。MAX3421EはUSBホストとしても、ペリフェラルコントローラとしても動作することができます。MAX3420Eはペリフェラル機能のみを搭載したものです。MAX3421EはMAX3420Eのペリフェラル機能に加えてホスト機能を搭載したものです。
 製品化されたものとして、MAX3421Eを搭載したArduino用のシールド(USBホストシールド)が販売されています。Pro Mini専用や、他にもArduino UNO用のシールドがスイッチサイエンスAmazonから販売されています。MAXIM以外のUSBコントローラを搭載したものはいくつか販売されていたようですが、現在は容易に手に入れることができる製品はありませんでした。ここでは、MAX3421Eを搭載したArduino Pro Mini専用のUSBホストシールドを、ブレッドボードに挿して使用してみました。GitHUBにArduino用のソフトが公開されています。



 USB ホストシールドとR8C/M12Aとの結線図

  SS  ・・・
チップセレクト
  MOSI  ・・・ Master Out Slave In
  MISO  ・・・ Master In Slave Out
  SCK  ・・・ クロック
  VIN  ・・・ 3.3V入力 ホストシールドは3.3V駆動
  GND  ・・・ GND MCUボードのGNDに接続する
  RAW  ・・・ ArduinoProMini用LDO入力ピン
  RST  ・・・ Reset Pin Lowで初期電源オン状態にリセット
  GND  ・・・ GND MCUボードのGNDに接続する
  SS Reset  ・・・ ボード変更ジャンパー用
  MAX Reset  ・・・ ボード変更ジャンパー用
  GPX  ・・・ 未使用
  INT  ・・・ MAX3421E用割り込みピン
  VBUS  ・・・ デフォルトで3.3Vに接続。切り離して5V供給用






HOST-Shield−R8C/M12A 結 線 表
       HOST−SHIELD R8C/M12A
VCC     3.6
GND     GND
SCK(クロック端子)   p3_4(出力)
MOSI(データ入力端子) p3_7(出力)
MISO(データ出力端子) p3_5(入力)
SS(チップセレクト)    p3_3(出力)
RST(リセット)     p4_7(出力)
INT        p4_6(入力)
   FT231X(TXD0)   p1_4    
   FT231X(RXD0)   p1_5    





(2)USB通信の説明

 USB通信では、ホストとデバイスが通信を行うわけですが、ホスト側のみがUSB転送を開始する権限を持っています。デバイス側は常にホストに応答し、自らが転送を自主的に独立して転送を開始することはありません。
 USB通信においては、通信の最小構成単位はパケットと呼ばれます。そのパケットがいくつか集まってトランザクションという通信単位を構成し、そのいくつかのトランザクションからなるフレームが1ms毎にホスト−デバイス間の送受信をおこないます。
 ここではまず、以下にUSB特有の用語、やり取りの手順等について簡単な説明をします。
  • エニュメレーション(Enumeration)

     USBデバイスを接続後、ホストから認識されるまでの一連のデータをやり取りすることをUSBエニュメレーションと呼んでいます。USBエニュメレーションのフローを完了できなければUSBデバイスはホストと連結することはできません。USBデバイスを接続すると、ホストは接続通知を受け取り、接続されたデバイスの確認を行います。具体的には、USBデバイスに対しデバイス・リクエストをおこないます。デバイス・リクエストには2種類あり、一つは、ホストからデバイスに何かを指示する、SET_ADDRESSがその代表です。もう一つは、GET_DESCRIPTORと呼ばれるような、デバイスから、何かの情報を取得するもので、デバイス・ディスクリプタと呼ばれる情報を要求し、それを受け取ることです。デバイスは、返送を全てディフォルトCONTROLエンドポイント0を使って行います。どんなUSBでも、これらの手順からUSB通信がスタートします。ホストがデバイスから受信したデータに満足すると、ホストはこのデバイスを使用することができるようにデバイスにドライバインストールのプログラムを与え、エニュメレーションが完了します。ホストがデバイスのデータに満足しない場合は、そのデバイスを無視します。これらのエニュメレーションの経過を記述したサンプルコードがMAXIMから提供されています。

     ここでは、当面はパソコンではなく、マイコンにUSBの機能を追加することに重点をおいており、パソコンのように数種類のUSB機器を接続することは考えていません。接続する1つのUSB機器だけを考えれば良いので、をUSBエニュメレーションは厳密な意味では必要はありません。


    (3)MAX232Eの取り扱い上の注意点

     1)CPOL(クロック極性)、CPHA(クロックフェイズ)の組み合わせ(CPOL,CPHA)で表すと、MAXIMアプリケーションノート3637では、(0、0)、(1、1)のどちらでも動作可能と記述されていますが、ここでは(0,0)、つまり、正極性、立ち上がりエッジで取り込み(Mode 0)でプログラムしています。

     2)電源投入時には全二重への切り替えができてない状態になっている
       切り替えが必要になります

     3)初期状態では、ペリフェラルモードで動作開始する


     4)MAX3421Eのレジスタは以下のようになっている


       ◎ホストモード、ペリフェラルモード両方で使えるレジスタ<BR>

       R1(RCVFIFO)
       R2(SNDFIFO)
       R4(SUDFIFO)
       R6(RCVBC)
       R7(SNDBC)
       R13(USBIRQ)
       R14(USBIEN)
       R15(USBCTL)
       R16(CPUCTL)
       R17(PINCTL)
       R18(REVISON)
       R20(IOPINS1)
       R21(IOPINS2)
       R22(GPINIEI)
       R23(GPINIEN)
       R24(GPINPOL)
       R27(MODE)






       ◎ホストモードのみで使えるレジスタ

       R25(HIRQ)
       R26(HIEN)
       R28(PERADDR)
       R29(HCTL)
       R30(HXFR)
       R31(HRSL)


       ◎ペリフェラルモードのみで使えるレジスタ

       R0(EP0FIFO)
       R3(EP3INFIFO)
       R5(EP0BC)
       R8(EP3INBC)
       R9(EPSTALLS)
       R10(CLRTOGS)
       R11(EPIRQ)
       R12(EPIEN)
       R19(FNADDR)

     R13〜R31は、MAX3421Eの制御レジスタです。


     5)MAX3421Eのレジスタにアクセスする方法

    SPIコマンドバイトの構成は下図のようになっています
    b7 b6 b5 b4 b3 b2 b1 b0
    Reg4 Reg3 Reg2 Reg1 Reg0 1=WR 0=RD ACKSTAT
    MSB LSB










    (4)最初に行う基本的なコマンド処理

     @SPIモードの変更
      デフォルトで電源投入時にはSPIモードは半二重になっています。そこで、まずMAX3421EのSPIモードを半二重から全二重
     に切り替える必要があります。PINCTLレジスタ(R17)を指定したコマンドバイトをまず送り、次に全二重モードにするデータ
     ビットを含んだ1バイトデータの合計2バイトでデータを書き込みます。全二重モード(FullDuplex)に設定する手順は、


      PINCTLレジスタ(R17)のビット構成は以下になります
      (B7、b6、b5はペリフェラルモードの関係ビットのため除外)

     b7   b6   b5   b4   b3   b2   b1   b0 
                   FDUPSPI INTLEVEL POSINT GPXB GPXA
    MSB               LSB


     コマンドバイトでR17を指定 ・・・ 
    10001 + 010(0x8a)
     FDUPSPIビット(b4)を指定 ・・・  0001 0000(0x10)

          以上の2バイトを連続で送ることになります。



     Aリセット
      MAX3421Eには、3つのリセットソースがありますが、そのうちの1つであるCHIPRES(チップリセット)と呼ばれる
     レジスタビットを使うソフトウエアリセットを試してみます。このリセットはSSピンをLowに駆動するのと同じです。

      R15(USBCTL)レジスタのb5(CHIPRES)をセットする。

      USBCTLレジスタ(R15)のビット構成は以下になります
      (B7、b6はペリフェラルモードの関係ビットのため除外)

     b7   b6   b5   b4   b3   b2   b1   b0 
          CHIPRES PWRDOWN CONNECT SIGRWU  0   0 
    MSB               LSB


     コマンドバイトでR15を指定 ・・・ 
    01111+010(0x7a)
     CHIPRESビット(b5)を指定 ・・・  0010 0000(0x20)
         CPUは、このビットをクリアして、チップのリセットを解除します。


     Bホストモードへの切り替え
      パワーオン時、またはRES#ピンのリセット後は、デフォルトではHOSTビットは0に設定され、ペリフェラルモード
     ですのでホストモードにする必要があります。ペリフェラルモードの時は、MAX3420Eペリフェラル専用コントローラ
     としてしか動作できません。


      R27(MODE)レジスタのb0(HOST)をセットする。

     MODEレジスタ(R27)のビット構成は以下になります

     b7   b6   b5   b4    b3   b2   b1   b0
    DPPULLDN DMPULLDN DELAYISO SEPIRQ SOFKAENAB HUBPRE LOWSPEED HOST
    MSB              LSB


     コマンドバイトでR27を指定 ・・・ 
    11011+010(0xda)
     HOSTビット(b0)を指定 ・・・  00000001(0x01)
         これで、ホストモードで動作します



     Cバスリセット

      R29(HCTL)のb0(BUSRST)をセットする

     レジスタ(R29)のビット構成は以下になります
     b7   b6   b5   b4    b3   b2   b1   b0
    SNDTOG1 SNDTOG0 RCVTOG1 RCVTOG0 SIGRSM SAMPLEBUS FRMRST BUSRST
    MSB              LSB


     コマンドバイトでR29を指定 ・・・ 
    11101+010(0xea)
     BUSRSTビット(b0)を指定 ・・・  00000001(0x01)
         R29(HCTL)のb0(BUSRST)が0になるのを待つ。




     DUSBバスの状態検出



    (5)プログラミング処理の基本

    1)レジスタ定義ヘッダーファイルの説明

     GitHubで公開されているMAXIMから提供されているレジスタ定義ヘッダーファイル MAX3421E.hをそのまま使用しています。
             ・
             ・
     8: #define rEP0FIFO 0<<3
        マニュアルでは5ビット表示で定義されているレジスタ番号0のEP0FIFOレジスタのビットを
        3ビット左シフトして8ビット形式にしたものを、rEP0FIFOとして定義するという意味です。

        以下9行目〜17行目まで同様の意味になります。
     9: #define rEP1OUTFIFO 1<<3
    10: #define rEP2INFIFO 2<<3
             ・
             ・
    16: #define rEP3INBC 8<<3
    17: #define rEPSTALLS 9<<3
             ・
             ・
    20: #define bmACKSTAT 0x40
         レジスタR9(EPSTALLS)のbm(Bit Mask?)構成ビットであるACKSTAT(0x40)を、bmACKSTATとして定義するという意味

     b7   b6   b5   b4    b3   b2   b1   b0
    0 ACKSTAT STLSTAT STLEP3IN STLEP2IN STLEP1OUT STLEP0OUT STLEP0IN
    MSB              LSB
           ・
           ・
    28: #define rCLRTOGS 10<<3
        マニュアルでは5ビット表示で定義されているレジスタ番号10のCLRTOGSレジスタのビットを
        3ビット左シフトして8ビット形式にしたものを、rCLRTOGSとして定義するという意味です。

        以下30行目〜35行目までは、CLRTOGSレジスタの構成ビットをそれぞれ上位から0x80〜
        0x04の順に定義しています。
    30: #define bmEP3DISAB 0x80
    31: #define bmEP2DISAB 0x40
    32: #define bmEP1DISAB 0x20
    33: #define bmCTGEP3IN 0x10
    34: #define bmCTGEP2IN 0x08
    35: #define bmCTGEP1OUT 0x04
             ・
             ・
             ・ 以下省略
             ・
             ・


    2)SPIのMode0に対応した1バイトMOSI、MISO同時使用可能の基本関数

     00:unsigned char SPI_transfer(unsigned char data)
     01:{
     02:  unsigned char i;
     03:  unsigned char ipdat; // ipdat 受信入力データ
     04:  ipdat = 0x00;
     05:  ADDR = 0;      // ADOを入力ポートに設定
     06:// C_SS;        // チップセレクトをLow
     07:  L_CLK();      // Mode 0 アイドル時はLow
     08:  for(i=0;i<8;i++){  // 1ビト毎にクロックと共に送受信する
     09:    ipdat <<=1;
     10:    L_CLK();    // クロックをLにして送受信準備
     11:    if(ADO) ipdat |= 0x01;// ADO端子(MISO)がHならばLSBに1を書き込む
     12:    if(data & 0x80){// MSBから送信
     13:      S_SDA;
     14:    }
     15:    else{
     16:      C_SDA;
     17:    }
     18:    H_CLK();    //クロックをHにして入出力処理
     19:    data<<=1;
     20:  }
     21:// S_SS;// チップセレクトをHigh
     22:  L_CLK();
     23:  return ipdat;// 受信データを戻り値として返す
     24:}





    3)SPI-Register書き込み関数 MOSI(Master Out Slave In)

      コマンド命令を送信後に続いて、SPIマスタはDIRビットで示された方向に1つのデータバイトを転送する。

     01:void wreg(unsigned char reg,unsigned char v) // register, value
     02:{
     03:  unsigned char j;
     04:  unsigned char bv;
     05:  L_CLK();// Clock LOW で準備待機
     06:  C_SS;
     07:  bv = reg | 0x02; // レジスタ + ディレクションビット送信部分
     08:  for (j=0; j<8; j++) //
     09:  {
     10:    if(bv & 0x80){  // MSBから送信
     11:      S_SDA;
     12:    }
     13:    else{
     14:      C_SDA;
     15:    }
     16:    bv <<= 1;    // shift one bit left
     17:    H_CLK();
     18:    L_CLK();
     19:  }

     20:  L_CLK();// Clock LOW で準備待機
     21:  for (j=0; j<8; j++) // レジスタデータ送信部分
     22:  {
     23:    if(v & 0x80){// MSBから送信
     24:      S_SDA;
     25:    }
     26:    else{
     27:      C_SDA;
     28:    }
     29:    v <<= 1; // shift one bit left
     30:    H_CLK();delay();
     31:    L_CLK();
     32:  }
     33:  S_SS;
     34:}






    4) SPI-Register読み込み関数  MISO(Master In Slave Out)

     00:unsigned char rreg(unsigned char reg)
     01:{
     02:  unsigned int i,v,inval;
     03:  inval = 0;
     04:  C_SS;       // チップセレクトをLow
     05:  v = reg;
     06:  L_CLK();     // 待機準備
     07:  for(i=0;i<8;i++){// register 送信部分
     08:    if(v & 0x80){// MSBから送信
     09:     S_SDA;
     10:    }
     11:    else{
     12:     C_SDA;
     13:    }
     14:    v<<=1;
     15:    H_CLK();  // モード0
     16:    L_CLK();
     17:  }

     18:  L_CLK();    // MISO 受信部分
     19:  inval =0;
     20:  for(i=0;i<8;i++){
     21:    inval <<=1;
     22:    if(ADO) inval |= 0x01;// ADO端子(MISO)がHならばLSBに1を書き込む
     23:    H_CLK();// モード0
     24:    L_CLK();
     25:  }
     26:  S_SS;
     27:  return inval;
     28:}






    5)MAX3420Eシステムの立ち上げ(アプリケーションノート3663)

     MAXIMのアプリケーションノート3663のの中で、「USB転送を処理するコードに取りかかる前に、関数をテストするルーチン・・・」の記述があり、その記述をもとにプログラムしてみました。MAX3420Eをリセットし、次に1が1つずつシフトするパターン8バイトをUSBIENレジスタに書き込みます。各バイトに1ビットがセットされ、00000001から始まって、次は00000010、最後は10000000となります。この手順をシングルステップでwreg関数で実行して、書き込んだ値をrreg関数で読み出すことで、MISO(wreg)関数、MOSI(rreg)関数が正常に動作しているかどうかをチェックするものです。読み込み、書き込みのタイミングがうまくいかないのか、200msの時間待ちを挿入することでやっと正常に読み書きができるようになりました。

      void test_SPI(void)
      {
        unsigned char j,wr,rd;
        wreg(rPINCTL , bmFDUPSPI);// MAX3420 SPI-full-duplex
        wreg(rUSBCTL , bmCHIPRES);// MAX3420Eをリセットする
        wreg(rUSBCTL , 0);    // remove th reset チップのリセットを解除する
        wr = 0x01;
        for(j=0 ; j<8 ; j++){
          wait_ms(200); // 時間待ち必要?
          wreg(rUSBIEN,wr);
          wait_ms(200); // 時間待ち必要?
          rd = rreg(rUSBIEN);
          UART0_tx_str("SPI TEST="); UART0_tx_hex(rd,2);UART0_tx_str("\n\r");
          wr <<= 1;
        }
      }

    本来は下記のような出力画面になるはずなのですが、時々出力値が飛んでしまう場合があります



    プロジェクトファイル(アプリケーションノート3663)のダウンロード





    6)その他のコード情報(アプリケーションノート3661)

    ◎AKSTATビット
     AKSTATビットを付与した書き込み関数wregAS()、読み込み関数rregAS()は、すでに作成した読み込み関数rreg()と書き込み関数wreg()とは異なる内容の関数です。

     /********************************************************************/
     /*** Same as wreg( SPI MOSI) 送信部分 but also set the AckStat bit***/
     /********************************************************************/
     void wregAS(unsigned char reg,unsigned char v) // register, value
     {
        unsigned char i;
        unsigned char bv;
        reg = reg | 0x01; // レジスタ + Ackstat bit
        wreg(reg,v);
     }

     /********************************************************************/
     /***   Same as rreg(SPI MISO) but also set the AckStat bit  ****/
     /********************************************************************/
     unsigned char rregAS(unsigned char reg)
     {
        unsigned char v,rval;
        v = reg| 0x01;
        rval=rreg(v);
        return rval;
     }


     上に示したように、SPIコマンドバイトのACK STATUSビットをセットします。SPIマスタは、このビットを使用して、現在のCONTROL転送サービスが終了したことをMAX3420Eに伝え、さらに、ステータス段にACKを送信することによってCONTROL転送を終了します。ACKSTATは、内部レジスタビットとして存在しますが、SPIコマンドバイトにこれを含めることによって、頻繁に使用されるこの動作の実行速度が速くなり、また使用するコードが少なくなるメリットがあります。


    ◎readBytes()関数、writeBytes関数




    7)MAX3420Eの割り込みシステム(アプリケーションノート3661)

     MAX3420Eのシステムの動作は、割り込み要求(IRQ)ビットによって決定されます。このビットを通じてUSBイベントをSPIマスタに通知するようになっています。MAX3420Eには14の割り込み要求ビットがあります。このビットを通して、どの割込みがサービスが要求されているかを判断します。

    1)IRQビット
     MAX3420Eのリセットを解除すると、USBが接続されていなくても、以下の割り込み要求ビットが割り当てられます。


    IRQビットの初期設定
     EPIRQレジスタの構成ビット
     ・IN3BAVIRQ
     ・IN2BAVIRQ
     ・IN0BAVIRQ


     USBIRQレジスタ(R13)のビット構成は以下になります
     b7   b6   b5   b4    b3   b2   b1   b0
    URESDNIRQ VBUSIRQ NOVBUSIRQ SUSPIRQ URESIRQ BUSACTIRQ RWUDNIRQ OSCOKIRQ
    MSB              LSB


     MAX3421E IRQビットは、以下の命令によってレジスタへの1回の書き込みだけでクリアされます

        wreg(rUSBIRQ 、bmURESIRQ);







    (6)応用プログラミング処理

    (1)USBメモリ覚え書き

     USBメモリは、UMS(Usb Mass Storage)として標準仕様が定められています。USBの通信層は、最上層、中間層、物理層の3階層に分類されています。最上位層は、SCSIコマンドを転送する通信層にあたり、コマンド転送、データ転送、ステータス転送を理解する必要があります。中間層は、通信の最小単位であるパケットをUSBバスに投入し、データのやり取りを行います。UMSがやり取りするパケットは9種類ありますが、そのうち、「OUT」「IN」「DATA0」「ACK」の4種類が主要部分です。最下層は電気信号レベルを扱う物理層です。

    @USBメモリのディスクリプタから読み取れること(以下の実験は、PICの章で行ったPIC24FJ64GB002を使った実験で使ったツールを用いています)

     USBメモリは、別名「8-6-50デバイス」とも呼ばれているそうです。その意味は、

     ・デバイス・クラスが8のMass Storage Class
     ・サブクラスが6のSCSI Transparent Command Set
     ・プロトコルが16進数の50のBulk-Only Transportという属性のUSBデバイス

    現在出回っている全てのUSBは8ー6ー50デバイスですので、同じ手順で制御可能とのことです。



      USBメモリのデバイス・ディスクリプタ


      USBメモリのコンフィグ・ディスクリプタ

    コンフィグ・ディスクリプタのクラス、サブクラス、プロトコルの項目が8−6−50になっているのがわかります。
    上図のコンフィグ・ディスクリプタの中で、INのエンドポイント番号1、OUTのエンドポイント番号が2になっていることに注意してください。



    AUSBメモリの転送方法

     USBに使われる転送方法には以下の4種類があります。
     
  • コントロール転送  
  • インタラプト転送  
  • バルク転送  
  • アイソクロナス転送
    転送方法は、用途に応じて使い分けられていますが、アイスクロナス転送はここでは使用しません。今回はバルク転送で接続します。



    エンドポイントのIN/OUTの値を先のコンフィグ・ディスクリプタにあるように、OUT を2、INを1にします。


    BSCSIコマンドを使用してみる(1)

     SCSIコマンドはCommand Descriptor Block(CDB)と呼ばれる形式で送受信されます。合計〜16バイトで一つのセットになっています。最初のバイトではどのような動作命令なのかを指定します。続くバイトで動作の細かなパラメータを指定します。


     SCSIコマンドは以下のような構成になっています

    コード(16進)  名称   バイト 
    00 TEST UNIT READY  6  
     01  REWIND   6  
     03  REQUEST SENSE   6  
     04  FORMAT   6  
     05  READ BLOCK LIMITS   6  
     07  REASSIGN BLOCKS   6  
     07  INITIALIZE ELEMENT STATUS  6  
     08  READ(6)  6  
     0A  WRITE(6)  6  
     0B  SEEK(6)  6  
    ・・・ ・・・ ・・・
    12 INQUIRY  6  
    ・・・ ・・・ ・・・
    25 READ CAPACITY  6  
    ・・・ ・・・ ・・・
    ・・・ ・・・ ・・・
     コード07 ・・・ なぜ2カ所あるのかは不明?



    step1) ホスト側からCBW(Command Block Wrapper)という31バイトデータを、OUT命令で出力します。
        CBWとは、ホスト側がデバイス側に対して命令を伝える仕組みのことです。
        CBWの15バイト目から後方には、SCSIコマンドが書かれています。


      SCSIコマンドのINQUIRY(0x12)コマンドを送っています。 
      CBWで36バイト、ID番号1の返答データを指定しています。



    step2) ホスト側からのCBWに対して、デバイス側はCSW(Command Status Wrapper)という13バイトのデータを送り返します。
        CSWとは、コマンドを正常に実施できたか、エラーは無かったか等の情報をホスト側へ伝えるしくみです。



        USBメモリからの返答データ 36バイト






       SCSIコマンドに対する13バイトのCSWレスポンスの解析
       CBWに対応する同じID番号が表示されているのがわかる
       最後の1バイトに転送結果 ステータス 00(成功)が入っている
        

        step1)のホスト側の送信に、step2)のデバイス側が応答することによって初めてバルク転送が成立することになります。



    CSCSIコマンドを使用してみる(2)

     接続してあるUSBメモリに対して、SCSIコマンドのREAD CAPACITY(0x23)コマンドを使って、USBメモリのサイズを表示させてみます。




      SCSIIコマンドREAD CAPACITYを送信した内容です。



      USBからの返信内容です。


     最終セクタ番号とセクターサイズを掛け合わせたものがUSBメモリの容量になります。

     7,747,927.55 KByte =7.74GByte と計算できます。

     接続してあるのは 8GByte のUSBメモリですので、ほぼ正しく表示されていると思います。


    参考文献:InterFace 2014年12月号 特集「目指せ小型でハイパー!USB探偵団」・USBメモリ用簡単USBドライバ



    (2)USBバスの状態検出

     (4)最初に行う基本的なコマンド処理の節DUSBバスの状態検出でもう既に述べていることですが、 関係しているレジスタはHCTL(R29)とHSRL(R31)です。
    レジスタ定義ヘッダーファイルMAX3421E.hのR29とR31の記述部分は、以下のようになっています。
         ・
         ・
         ・
      #define rHCTL 29<<3
      // ---------bits------------
      #define bmBUSRST 0x01
      #define bmFRMRST 0x02
      #define bmSAMPLEBUS 0x04
      #define bmSIGRSM 0x08
      #define bmRCVTOG0 0x10
      #define bmRCVTOG1 0x20
      #define bmSNDTOG0 0x40
      #define bmSNDTOG1 0x80
         ・
         ・
         ・
      #define rHRSL 31<<3
      // ---------bits------------
      #define bmRCVTOGRD 0x10
      #define bmSNDTOGRD 0x20
      #define bmKSTATUS 0x40
      #define bmJSTATUS 0x80



    R29(HCTL)のb2(SAMPLEBUS)に1をセットし、0にクリアされるのを待つ。

    R31(HRSL)の下記のビットチェックをおこなう。

    JSTATUSビット(b7)を読み取る ・・・ 0かどうかをチェック
    KSTATUSビット(b6)を読み取る ・・・ 0かどうかをチェック

      JSTATUS、KSTATUSの両方が0なら、デバイスは接続されていない。





    ・・・・・・・・・・ 参 考 資 料 ・・・・・・・・・・

        (MXIM社がAnalog Devices社に吸収統合されて以来、一部のリンクが正しく辿れなくなっています)

         MAX3420E の USB エニュメレーションコード(およびその他)
         アプリケーションノート 3661 MAX3420Eの割り込みシステム
         アプリケーションノート 3637 あらゆるシステムにUSBを追加
         アプリケーションノート 3598 MAX3420Eプログラミングガイド
         アプリケーションノート 3785 MAX3421Eプログラミングガイド
         アプリケーションノート 3663 MAX3420Eシステムの立上げ
         アプリケーションノート 3597 MAX3421Eに関するFAQ (よくある質問)
         アプリケーションノート 3803 役に立つUSB用語集
         アプリケーションノート 3891 Isolating USB(USBの絶縁)(英語版)
         アプリケーションノート 3891 USBの絶縁(日本語訳)
         アプリケーションノート The Analog Devices USB Laboratory
         アプリケーションノート 3937 MAXIM USB LABORATORYのセットアップ
         アプリケーションノート 4000 MAXIM3421Eの改版1と2のホストOUT転送
         チュートリアル 5884 TURN ANY VIDEO GAME CONTROLLER INTO A USB MOUSE
         チュートリアル 1882 USB On-the-Goの基礎


    プロジェクトファイルのダウンロード


    メニューに戻る