Maxim USB Laboratory
要約
Maxim USB LaboratoryはARM7™プロセッサと実例ソフトを使用するMAX3421E/MAX3420Eをベースとしたシステムです。このアプリケーションノートは、システムとそれを実行するソフトウェアについて説明します。USBホストとペリフェラルの両方とも同じARM®のCコードで実装されています。この方法はリファレンスデバイスをUSBケーブルの他端に接続する利点を備え、すべて同じCコードでUSBペリフェラルと埋め込みホストの開発と学習が可能になります。
このアプリケーションノートはアプリケーションノート3937 「Maxim USB Laboratoryのセットアップ」と対になっています。マキシムデモコードを含むKeil™プロジェクトはダウンロード可能です。
はじめに
Maxim USB Laboratoryは2つの回路ボードとCプログラムを組み合わせたものです。このシステムを使うと次のことが可能となります:
- MAX3420E USBペリフェラルコントローラに接続されたARM7マイクロコントローラ(µC)をベースとしたUSBデバイス機能の学習、動作、試験、および変更。
- MAX3421Eホストコントローラに接続された同じARM7 µCを使用するUSBホスト機能の学習、動作、試験、および変更。図1はUSBメモリスティックからホストによってデータが検索される様子が示されています。
- ホストをペリフェラルにUSBケーブルで接続して、ホストとペリフェラルを同時に動作させます。USBホストまたはUSBペリフェラルのコードのいずれかを開発するとき、USBの他端にリファレンスデザインを備えることは非常に役に立ちます。こうすることで、両方とも同じCコードで実装されているホストとペリフェラル、つまりUSBケーブルの両側を、制御可能とすることができ、カスタム化することができます。
図1. MAX3421ホスト/ARMが、USBペリフェラルデバイスからエニュメレーションデータを検索し、ターミナル用のエミュレーションプログラムを実行しているPCに、接続されたシリアルポートを通してその結果を通知しています。
その他の文書
MAX3420EとMAX3421Eのプログラミングガイド、データシート、およびアプリケーションノートはマキシムのウェブサイトでご利用頂けます:
MAX3420E
MAX3421E
アプリケーションノート3937 「Maxim USB Laboratoryのセットアップ」
ハードウェア
アプリケーションのCコードは2つのボードセットで動作します:
- マキシムのMAX3421Eの評価(EV)キット、1ボード
- Keil MCB2130、2番目のボード
図2. Keil MCB2130ボードにプラグインしたマキシムのEVキット。
図2はボードの組立てを示しています。青いボードがKeil MCB2130でARM7チップとしてPhilips®のLPC2138を搭載しています。このµCは、2つのマキシムUSBコントローラチップに接続する2つのSPI™ハードウェアユニットを備えています。
垂直のボードがMAX3421EのEVKIT-1です。MAX3420EペリフェラルコントローラはARMのSPIポートの1つに接続され、図2の「3420 P」 (PはペリフェラルのP)と表示されたUSBの「B」コネクタ(J5)に結線されています。MAX3421Eのホスト/ペリフェラルコントローラはもう1つのARM SPIポートに接続されて、「3421P」 (J2)および「3421H」 (J1)コネクタ(HはホストのHです)に結線されています。このアプリケーションで記述されたコードはMAX3421Eをホストとしているため、EVキットボード上の中間のUSBコネクタ(J2)は使われません。
ホストのソフトウェアは、ターミナルエミュレーションプログラムを実行するPCにUSBの記述情報を送信するために2つのシリアルポートの1つ(MCB2130ボード上のP1)を使います。Tera Term Proなどのターミナルプログラムは、画面をクリアしてカーソルを原点に復帰させるためにプログラムによって送信される特別な「escape code」シーケンスを認識するターミナル(VT100)をエミュレートすることができます。ターミナルプログラムのシリアルポートの設定値はフロー制御なしの38400、N、8、1です。
図2のベージュ色のボックスとリボンケーブルはKeil ULINK JTAGローダーデバッガーです。このユニットはKeil µVision®3開発環境によってサポートされています。MCB2130ボードにはKeilツールセットの完全機能バージョンであるµVision3の評価バージョンが同梱されています。この評価バージョンは16kBのコードサイズに限定されています。
このアプリケーションノートの付属ファイルには16進形式のすべてのソースファイル、およびロードモジュールを加えた完全Keilプロジェクトが含まれています。ULINK JTAGユニットをお持ちの場合はJTAGポートを通してコードをコンパイル、ロード、そしてデバッグすることができます。これは、動作しているホストおよび/またはペリフェラルコードを目的に合わせて変更するUSBを効率よく開発する優れた方法です。ULINKボックスをお持ちでない場合でも、www.esacademy.comから入手可能なFlash Magicと呼ばれる無料のユーティリティを用いて16進ファイルをロードして実行することができます。このユーティリティの構成と用法についての情報はマキシムのアプリケーションノート3937を参照してください。
図3. MAX3241EEVKIT-1ボードのブロック図。陰影をつけた楕円形は主要なソフトウェアモジュールです。
コードの機能
図3はこのアプリケーションノートで説明するMAX3421EEVKIT-1ボードとソフトウェアモジュールのブロック図です。MAX3420EとMAX3421Eの両方とも、SPIバスを用いてそのレジスタセットにアクセスすることができます。LPC2138は2つのハードウェアSPIユニットを内蔵しています:
- 専用のSPIポート(SPI)
- 汎用シリアルインタフェース(SSP、シンクロナスシリアルポート)
SSPは2番目のSPIポートを実装するように設定されています。これらのポートの設定はおのおの異なります。例えば、SSPは深さ8の送信および受信用のFIFOを備え、他方、SPIは深さがわずか1の読取りバッファです。2つのSPIポートはMAX3420およびMAX3421Eと対応するために8ビットのデータモードで動作するように設定されます。ソフトウェアモジュールのSPI_FNs.Cには両方のUSBコントローラで使われるレジスタアクセス機能が含まれています。
MAX3420はSPIユニットに接続されていて、チップと会話する機能にはペリフェラル動作を示すために「P」の接頭字(例:PrregやPwregなど)が付けられています。MAX3421EはSSPユニットに接続されていて、そのアクセス機能にはホストとの動作を示すために、「H」の接頭字(例:Hwreg)が付けられています。
ペリフェラルコード
Cモジュールの3420_HIDKB.CはEVキットコネクタJ5を用いてPCに接続するUSBペリフェラルデバイスを実行します。MAX3420EのINT出力端子はARM7のEINT0 (外部割込みゼロ)端子に接続されています。MAX3420Eによって実装されたUSBペリフェラルがサービスを要求したときはいつでも割込みがアサートされます。
このアプリケーションは標準のUSB HID (Human Interface Device)としてエニュメレートされ、動作します。標準のWindows®デバイスクラスに準拠する利点はデバイスドライバがWindowsに組み込まれているため、特別なドライバをインストールする必要がないことです。Windowsはこのアプリケーションによって実装されたデバイスを標準のキーボードとして認識します。MAX3420EのGP-IN端子に取り付けられた4つの押しボタンのいずれかを押すと、テキストスを受け取る、例えばNotepadまたはWordpadなどのオープンウィンドウのいずれかに、「キーボード」がテキストストリングをタイプ入力することになります。
警告:このアプリケーションはEメール、コンパイラエディタ、またはワード文書などのテキストを受け取るどのようなアプリケーションにもタイプ入力します。ボタンを押す前にNotepad等をオープンしてアクティブにしておくなどの安全なアプリケーションを必ず開いてください。オープンしたCソースファイルへタイプ入力したルールに従わないテキストは正しくコンパイルしないということを経験から確信しています。
ホストのコード
3421_Host_EVK.CファイルにはコネクタJ4にUSBデバイスがプラグインされた時にPCが取る動作に似たエニュメレーションステップをMAX3421Eが実行するように指示するホストコードが含まれています。main( )関数はHIDキーボードファンクコードに対する割込みハンドラであるため、このモジュール内にあります。EINT0割込みハンドラは単純です:
// EINT0 Interrupt handler--MAX3420E INT pin void INT3420 (void) __irq { service_irqs(); // Do the USB thing in 3420_HIDKB_INT_EVK.C module EXTINT = 1; // Clear EINT0 interrupt flag (b0) VICVectAddr = 0; // Dummy write to indicate end of interrupt service }バックグランドプログラムのmain( )には次に示すエンドレスループが含まれています:
while(1) { detect_device(); waitframes(200); // Some devices require this enumerate_device(); wait_for_disconnect(); }enumerate_device()関数が仕事の大部分を行い、USBからの要求を接続されたデバイスへ送り、シリアルポートを通して結果を通知します。EV kit J1に任意のUSBデバイスを接続すると、この関数がデバイスにエニュメレーション要求を送り、シリアルポートを通して結果を通知します(図1)。
ホスト/ペリフェラルの同時動作
MAX3421EEVKIT-1ボードはUSBペリフェラルとUSBホストの両方を備えているためと、それらはARM7の別のSPIインタフェースを使うため、ホストとペリフェラルのアプリケーションが同時に動作するようにソフトウェアを容易に構成することができます。HIDペリフェラルコードがMAX3420Eの割込みを用いてservice_irqs( )関数をアクティブにしている間に、ホストアプリケーションがバックグランドでMAX3421Eと会話するためにmain( )を実行します。
USBケーブルをEVキットのJ5からJ1に接続すると、ARMプロセッサはペリフェラルデバイス、つまり自分自身と会話するUSBホストとして振舞うことができます。図4には3421_Host.C内のホストコードが3420_HIDKB.Cに実装されたペリフェラルを調べるときに、それが通知する内容が示されています。
図4. USBを使って自身を調べるデモコード。
ホストコードの開発
enumerate_device( )関数を調べると、USBホストの動作、およびホストがUSBデバイスをエニュメレートする場合にさまざまなホストの動作を行うためにMAX3421Eへどのようなコマンドを与えるかを理解するのに役立ちます。USBのホストコードを開発しているとき、ホストにプラグインされたペリフェラルがどのように応答しているかが明らかでない場合、問題を診断することが困難な場合があります。完全に制御することができるリファレンスペリフェラル(3420_HIDKB.Cモジュール)を備えているため、ホストのファームウェアを試験するためにデバイスの応答を知り、変えることが容易です。
ペリフェラルコードの開発
ホストはUSBペリフェラルコードの開発にとって優れた調査用ツールです。MAX3421Eと3421_Host.Cの組み合わせにより、簡単で強力なUSBパケット生成器と解析器を作り出すことになります。Cによるホストコードを書くことによってペリフェラルデバイスが理解することを制御します。つまり、MAX3421Eはペリフェラルがどのように応答するかを示してくれます。
例
USBストリングを処理するためにペリフェラルコードを書いているとしましょう。hidkb_enum_tables.hの中にメーカー名の文字列をXYZ Widget Companyとコード化すると次のようになります:
// STRING descriptor 1--Manufacturer ID { 18, // bLength 0x03, // bDescriptorType = string 'X','Y','Z',' ','W','i','d','g','e','t',' ','C','o','m','p','a','n','y' },これをコンパイルして、ARMフラッシュにロードして実行します。ホストプログラムが次のメーカー文字列を通知します:
図5. 旨く行かない場合。コード例はメーカー名が表示したいようになっていない場合を示しています。明らかにコードに問題があります。
XZWde opは何に問題があったのでしょう?そうです、USB仕様はテキストストリングを文字あたり2バイトのユニコードで表現することを要求します。ペリフェラルのソースコードに戻り、これを次のように変えます:
// STRING descriptor 1--Manufacturer ID { 35 // bLength 0x03, // bDescriptorType = string 'X',0,'Y',0,'Z',0,' ',0,'W',0,'i',0,'d',0,'g',0,'e',0,'t',0, ' ',0,'C',0,'o',0,'m',0,'p',0,'a',0,'n',0,'y' // Unicode! },コンパイルして、実行すると次のようになる筈です:
図6. 旨くゆきました。ユニコード形式を使うと、このような結果となります。
今度はずっと良いが、まだ完全ではありません。”Company”の中の”y”はどこにあるのでしょうか?ストリングの中で35文字を注意してカウントし、ストリング長を示す最初のバイトとしてこれを入力しました。しかし、何かを見落としています:ストリングの他に最初の2バイトを長さバイトの中に含める必要があります。コードに最終の変更を加えます:
// STRING descriptor 1--Manufacturer ID { 37 // bLength 0x03, // bDescriptorType = string 'X',0,'Y',0,'Z',0,' ',0,'W',0,'i',0,'d',0,'g',0,'e',0,'t',0, ' ',0,'C',0,'o',0,'m',0,'p',0,'a',0,'n',0,'y' // Unicode! },その結果次のようになります:
図7. うまくゆきました。今度は思った通りとなりました。
ペリフェラルコードを微調整してホストコントローラとコードを使って実行/解析を行うと、PCが見ているのと全く同じ内容を見ることになります。それは通知される結果がMAX3420EからMAX3421Eへ送信される実際のUSBトラフィックであるからです。非常によいのは、開発において間違いが起きそうなコードにPCがどのように応答するかを心配することなく、制御されたやり方でこれを行うことができることです。
コードの説明
図8. Keilプロジェクトの構造。
図8は3つの主要モジュールを示しており、展開してそのファイル構造属性が示されています。展開されていないモジュールはKeil環境で必要な補助ファイルです。
SPI_FNs.C
このモジュールには他の2つのモジュールからコールされるユーティリティファンクションが含まれています。
void init_PLL(void)
この関数によってLPC2138のPLLとクロック分周器を設定します。LPC2138 (FOSC)に取り付けられている水晶は12.000MHzです。CPUの周波数は式CCLK = FOSC x M、ここでM = 4、に従って48MHzに設定されます。LPC2138はFOSCを逓倍してさらに高い周波数にするために内蔵CCO (電流制御発振器)を使用しています。FCCO = CCLK x 2 x Pで表され、FCCOは156MHz~320MHzになければなりません。P = 2に対して、FCCO = 48MHz x 2 x 2 = 192MHzとなります。
注:Keilファイルのstartup.sにはPLLパラメータを設定するための起動コードが含まれています。init_PLL()関数はこれらの設定値より、実質的に優先されます。
重要な警告:これらの設定値の変更は使用者の責任で行ってください。不適切な設定値はLPC2138を仕様限界外に強制的に置くことになり、Keilデバッガーの機能停止を招きます。これが起こった場合、救済方法はLPC2138フラッシュを消去するためにFlash Magicユーティリティを使うことです(このためにKeilボードのP2に接続されている2番目のシリアルポートを使ってください)。そしてコードのPLL設定値を修正して再び実行してください。
init_IO
この関数によってLPC2138 I/O端子とSPIユニット(SPIとSSP)が初期化されます:
- SPIは最大許容値のCCLK/8のクロックで動作します。このSCLKは48MHz/8 = 6MHzです。
- SSPはCCLK/(2 x VBDIV)のクロックで動作します。VBDIFは1に設定されMAX3421EのSCK信号は48MHz/2 = 24MHzに等しくなります。MAX3421EのSCLK入力は最高26MHzまで動作可能です。
SPIインタフェースについて
SPIインタフェースは次の信号を使用します:
- MOSIマスタ出力、Slave入力データ
- MISOマスタ入力、Slave出力データ
- SCLKシリアルクロック、これはLPC2138から供給されます。
- SS#スレーブ選択、これはLPC2138によって駆動されます。
LPC2138のSPIハードウェアは最初の3つの信号を処理しますが、SS#はGP-OUT端子(P0.7)を用いて直接セットされ、クリアされます。
SSPインタフェースについて
SSPはハードウェアSS#端子を備えていますが、SS# (P0.20)に対してはGP-OUT端子を使う方がもっと簡単です。
Hwreg
Hwritebytes
これらの関数によってLPC2138のSSPハードウェアを用いてMAX3421EにレジスタおよびFIFOデータを書き込みます。接頭字のHはホストの動作を表します。Hwregによって1個のレジスタ値を書き込み、HwritebitesによってMAX3421EのFIFOに複数バイトを書き込みます。
Hrreg
Hreadbytes
これらの関数はLPC2138のSSPハードウェアを用いてMAX3421EからレジスタとFIFOデータを読み取ります。
SSPインタフェースの詳細説明
SSPハードウェアは送信および受信経路にデータ用のFIFOを備えることからくるコーディング問題が存在します。SPIの動作では、8ビットの転送出力ごとに、常に8ビットの転送入力が伴います。LPC2138は次のステップを用いてMAX3421EのSPIにアクセスします:
- SS#をアサート(ロー)
- レジスタ番号と方向ビットからなるコマンドバイトを送信
- 1バイト以上のデータを送信/受信
- SS#をデアサート(ハイ)
SPIの書込みは簡単ですーすべてが出力され、入力FIFO内のデータは無視されます。しかし、読取りはもっと複雑です。それは読取りFIFOには、ステップ2で自動的にクロック入力された少なくとも正しくない1バイトが存在するからです。また、複数バイトを書き込んだ前の動作で、データの中に古いものが存在する可能性もあります。入力FIFOはハードウェアによって禁止されたり、または消去されたりすることができません。したがって、SPIデータを読み取るコードは最初に、「read FIFO not empty (読取りFIFOが空ではない)」というフラグがデアサートされるまで、SSPDRから複数バイトを読み取ることによって、マニュアルで消去しなければなりません。
Pwreg
PwregAS
Pwritebytes
これらの関数によってLPC2138のSPIハードウェアを用いてMAX3420EにレジスタおよびFIFOのデータを書き込みます。2番目の関数によって最初の関数と同じ1個のレジスタに書き込みます。しかし、同時にSPIコマンドバイトのACKSTATビットもセットします。これはUSB CONTROL転送を終結させるショートカットです。詳細はアプリケーションノート3598 「MAX3420Eプログラミングガイド」を調べてください。
Prreg
PrregAS
Preadbytes
これらの関数によってLPC2138 SPIハードウェアを用いてMAX3420EからレジスタおよびFIFOのデータを読み取ります。2番目の関数によって最初の関数と同じ1個のレジスタから読み取ります。しかし、同時にSPIコマンドバイトのACKSTATビットもセットします。
readout
この関数はMAX3421Eの汎用出力端子GPO[6:0]に接続された7セグメントの読取り値を更新します。このことにより、USB 「A」コネクタ(EVキットのJ1)に接続されたVBUSスイッチを制御するGPO[7]の設定値が保存されます。
3421_Host.C
このモジュールはUSBデバイスを調査してMCB22310のシリアルポートを使ってエニュメレーションデータを通知するMAX3421E USBホストを実装します。参考のために、付録Aは3420_HIDKB.Cに実装される組込みデバイスをホストがエニュメレートするのをLeCroy (CATC)がバストレースしているところを示しています。
このモジュールには3つのタイプの関数があります:
- 初期化
- ユーティリティ関数
- main( )にコールされるハイレベル関数
以下に示す説明はこの順序に従っています。
Reset_Host
MAX3421Eには電源オンリセットが備わっているため、この操作は必須ではありません。しかし、コードを開発するとき、電源はおそらくサイクルされていないため、各デバッグセッションの最初にチップをリセットするのは良い考えです。リセットするとマシーンはクリアな状態で始動し、前のデバッグセッションから引き継ぐものは何もなくなります。
MAX3421Eをリセットすると、内蔵の発振器が停止します。リセットがデアサートされた後、この関数はOSCOKIRQビット(Oscillator OK Interrupt Request)が有効になるまで、待機し、その後で復帰します。
initialize_3420
この関数は3420_HIDKB.Cモジュール内にあります。
initialize_ARM_Interrupts
この関数はARMベクトル割込みを次のように設定します:
- EINT0はMAX3420E INT端子に接続され、プライオリティ0 (最優先順位)を使います。
- タイマー0は優先順位1を用いて、アクティビィティライトを点滅するために使われます。
- EINT2には優先順位2が与えられ、MAX3421E INT端子に接続されます。これはこのプログラムでは使用されておらず、単に参考として提供されています。
- Timer1は優先順位3を用いて送信/停止押しボタン(3420_HIDKB.Cで使われる)をチェックするために使われます。
service_irqs
この関数は3420_HIDKB.Cモジュールの中にあります。これはHIDキーボードエミュメレーションを行います。ARM割込みを初期化するコードはこのアドレスを割込みベクトルとしてインストールするためにのみ必要です。
waitframes
USBホストが時間計測を行う簡単な方法は1msのフレームマーカーを計数することです。µCがレジスタのビットSOFKAENAB = 1と設定するとき、MAX3421Eは自動的にこれらのフレームマーカーを生成します。フレームマーカーはフルスピードモードでのSOFパケットまたはロースピードモードでの「keep alive」パルスから構成されます。FRAMIRQビットは、その場合、1ミリ秒ごとにアサートされます。
USB仕様は一定の長い遅延時間を強制します。例としてはデバイスをリセットした後、その「リセット回復時間」を与えます。waitframes関数をコールするのはこれらの比較的長い遅延を実装する容易な方法です。
detect_device
この関数はUSB-AコネクタJ1にプラグインされたUSBデバイスを検出した後で復帰します。
wait_for_disconnect
この関数はUSB-AコネクタJ1にプラグインされたUSBデバイスが外された後で復帰します。
Send_Packet
この関数はUSBパケットを送信するすべての関数によってコールされます。図9はINトランザクションのバストレースとそれを作り出すCステートメントを示しています。
図9. MAX3421EへのC関数のコールがUSBバスアクティビティを引き起こしています。
- µCはFNADDRレジスタの関数アドレスを設定します。これは各パケットで毎回繰り返す必要はありません。それはロードされた値はµCがFNADDRレジスタを再ロードするまで続くからです。
- µCはUSBトークンとエンドポイントを決定して、HXFRレジスタに書き込むことによって転送を開始します。その後、HXFRDNIRQ (Host Transfer Done) IRQがアサートされるのを待機し、転送の終了を通知します。
- µCはトランザクションの出力を決定するためにHRSL (ホストの結果)レジスタを読み取ります。その結果得られる16個のコードは次のことを示します:
A. 成功(ACK)
B. デバイスビジー(NAK)
C. 異常なハンドシェーク(STALL)
D. タイムアウト、バブル、またはバスエラーのようなデバイス問題
- µCはバイトカウントレジスタを読み取り、その後、RCVFIFOをアンロードし、データをバイトアレイの中に退避します。
この関数はNAKのリトライを扱います。この転送は次のことが起こるまで続きます:
- ACKハンドシェークを得る、または
- 定数NAK_LIMITによって設定されたプリセット限界を超える。
デバイスが応答しない場合は、関数は限界値のRETRY_LIMITに達するまで、転送をリトライします。
CTL_Write_ND
この関数はデータ段なしに(_ND = no data)CONTROL-Writeトランザクションを実行します。この関数はホストのSet_Addressリクエストに対してのみコールされます。このためにSend_Packetに対して2つのコールを行います:最初がSETUPパケットに対して、2番目はINハンドシェークパケットに対してです。
IN_Transfer
この関数はSend_Packet (INを規定)に対してUSBデータレコードを探索するために必要とするだけ、コールされます。MAX3420EとMAX3421EのエンドポイントFIFOは64バイト長と長い記述子であり、例えばパケットデータを繋ぎ合わせて大きなアレイ(XfrData[2000])にするために、複数回のINリクエストを必要とします。
CTL_Read
この関数は3段のCONTROL-Read USBトランザクションを実行します。3つのコールを行います:
- SETUPパケットを発行するために、Send_Packetを実行する
- データをXfrData[]に得るためにIN_Transferを実行する
- OUTハンドシェークパケットを発行するためにSend_Packetを実行する
enumerate_device
この関数によって付録Aに示すように10個の転送が実行されます。この関数はローレベルのUSBの仕事を行うために前の関数をコールするため、この関数を調べることによってエニュメレーションステップを追いかけるのは容易です。
print_error
この関数は最後のホスト転送の出力を印刷するために4ビットのHRSL値(図9の項目3)をチェックします。渡された値がゼロの場合は何も印刷されません。この関数ではHRSL値が返されるため、この関数をコールすることにより簡単にエラーのチェックを行うことができます。例を次に示します。
if(print_error(HR)) return;
3420_HIDKB.C
このモジュールはMAX3420Eを用いてUSBペリフェラルを実装します。これは標準HIDクラスに準拠しており、標準のキーボードからテキストが発生したかのように、テキストを自動的にタイプします。エントリポイントはservice_irqs関数であり、それはLPC2138 EINT1端子に応答して割込みサービスルーチンとして開始されます。EINT1はMAX3420EのINT出力端子に接続されています。
Reset_Peripheral
この関数はReset_Hostと同じ方法でMAX3420Eをリセットします。
initialize_3420
この関数は次の3つのことを行います:
- MAX3420EのSPIインタフェースをフルデュープレックス動作(MOSIとMISO端子を別にする)に構成する。
- MAX3420EのINT端子を正のエッジアクティブに構成する。
- アプリケーションで使われているMAX3420Eの割込みをイネーブルする。
service_irqs
この関数は直接バスリセットとデバイス切断を行います。また、この関数はエニュメレーションを取り扱うためにdo_SETUPを、キーボード入力するためにdo_IN3をコールします。
注:コードサイズを小さくするために、このアプリケーションはUSBサスペンド-レジュームを取り扱いません。これを行う方法の例はアプリケーションノート3690 「MAX3420EのUSBエニュメレーションコード(およびその他)」に記載してあります。AN3690の中のエニュメレーションコードは3420_HIDKB.Cに対する基礎として使われました。
do_SETUP
この関数は8バイトのSETUPパケット内のさまざまなバイトを検査することによってデバイスエニューメレーションを取り扱い、その後、各関数をコールして個々のリクエストを取り扱います。このコードはUSB標準のリクエストタイプのみを扱います。その理由はアプリケーションがUSBクラスもベンダーリクエストも実装しないからです。
do_IN3
この関数はHIDKB_enum_tables.hの中のMessage[]文字アレイに従ってキーストロークを送信します。図10に示すように、文字当たり3バイトのフォーマットは同じインクルードファイル内のHIDレポート記述子で定義されます。
図10. このレポート記述子はキーボードのキーストロークのための3バイトデータフォーマットを規定します。
最後の考察とお断り
J1に接続するUSBデバイスは10億種程度の入手可能ないずれでも可能です。したがって、言うまでもなく、ホストのエニュメレーションリクエストに対し様々な応答があります。準拠テスト済み(USBのロゴ表示があることで分かる)のデバイスはエニューメレートされてもエラーを示さない筈です。このプログラムのエラーチェック機能は各ホストトランザクションの後で、HRSLの値を調べる構成となっています。このエラーチェック機能は広範には試験されていません。その理由は多くのエラー状態を作り出すことが困難だからです。
付録A
3420E_HIDKB.C エニュメレーションに対するUSBバストレース
図の拡大(PDF、234kB)