ホストコントローラの使い方

目次

初期化
デバイスの接続
コントロール転送
    セットアップステージ
    データステージ
    ステータスステージ
デバイスの調査
    デバイスディスクリプタ
    コンフィギュレーションディスクリプタ
    インターフェースディスクリプタ
    エンドポイントディスクリプタ
ホストの役割
    通信の割り当て
    通信手順
    通信結果への対応
    フレーム中のひとつのチャネルのトランザクション数

初期化

ホストコントローラはデバイスの接続を待たなければ どこにも通信できません。 デバイスの接続は接続検出レジスタ DETAR の変化を待ちます。

接続検出レジスタの変化は割り込みで待つこともでき ます。

割り込みレジスタ IR に対して次の操作を行います。

  1. ビット7を1にして割り込みを有効にします。
  2. ビット5を0にして接続検出の割り込みマスクを解除し ます。
  3. 接続検出が原因で割り込みが要求されたときビット1が 1になります。

リセット後のホストコントローラの初期化は割り込み の設定くらいです。

デバイスの接続

デバイスが接続されたときアドレス0のエンドポイント 番号0にコントロール転送で通信が可能になっています 。

ホストは新しくデバイスが接続されたときにはデバイ スと通信して0以外のアドレスを割り当て、 構成 を設定しなくてはなりません。

構成 は USB ではコンフィギュレーションと言われています 。 デバイスは通信仕様をいくつも持つことができるよう になっていますが、それらを構成と言い、そのどれか を選択して構成を設定します。これを「デバイスの構 成を完了する」などと言います。

アドレスを割り当てたり構成を設定したりするにはデ バイスに対してデバイスリクエストを発行します。

デバイスリクエスト

デバイスがデバイスリクエストを認識するのはToken パケットにSETUPが使われたときです。 TokenにSETUPが使えるのはコントロール転送に限られ ています。


デバイスの構成を設定するにはデバイスの持っている 構成をホストが調査する必要がありますがこれもデバ イスリクエストを使ってデバイスから読み出します。

デバイスが接続されたときにホストは次のことを行い ます。

  1. デバイスリクエストを発行してデバイスの構成を読み 取る。
  2. 構成を調査して構成値を決定する。
  3. デバイスリクエストを発行して構成を設定する。
  4. デバイスリクエストを発行してアドレスを割り当てる。

これらはホストコントローラで自動的に行われません のでプロセッサがホストコントローラを操作して行い ます。

コントロール転送

デバイスリクエスト を発行するには Token にSETUPパケットを使うので コントロール転送 で通信します。 デバイスリクエスト専用の通信方法と言えると思いま す。

コントロール転送は3種類のトランザクションから成り ますが、それぞれは性質が異なるためそれぞれにプロ セッサが関与します。

デバイスの接続後にはデバイスの情報を読み取るため にデバイスリクエストの GetDescriptor を発行します。

セットアップステージ

通信は次の順番で行います。

  1. ホストがデバイスにTokenパケット(SETUP)を送る。
  2. ホストがデバイスにDataパケット(Data0)を送る。
  3. デバイスがホストにHandshakeパケット(ACK)を返す。

Dataパケットの内容に デバイスリクエスト が入ります。

準備

ホストコントローラの通信を実行する直前までの操作 は次のようになります。

  1. チャネル選択レジスタ CHSEL に0を書き込んでチャネルにAを選択します。
  2. デバイスリクエストの内容をチャネルのメモリに書き 込みます。

    0 1 2 3 4 5 6 7
    80h 6 0 1 0 0 8 0

    1. 下ポイントレジスタ POINTL のビット0と1に1を書き込んでメモリ位置を0にします 。
    2. データレジスタ DATA にデータを書き込みます。 (メモリ位置は書き込み後に自動的に進みます。)

  3. チャネル設定レジスタ0 CHR0 に0を書き込んで端子の選択を0、エンドポイント番号 を0にします。
  4. チャネル設定レジスタ2 CHR284hを書き込みます。
  5. チャネルコントロールレジスタ CHCNR18hを書き込みます。
  6. 端子選択レジスタ TMSEL に0を書き込んで端子の0を選択します。
  7. セグメントレジスタ0 SEGR0 に0を書き込んでチャネルAを設定します。

実行

通信要求レジスタのビット0に1を書き込んでチャネル Aのトランザクションをホストコントローラに要求しま す。

この後のセットアップステージのトランザクションの 開始から終了までをコントローラが自動的に実行しま す。

チャネルAのトランザクションの終了は通信済みレジス タRDYRのビット0を1にして示されます。 割り込みが有効になっていれば割り込みで待つことも できます。 トランザクション終了の割り込みはマスクできない割 り込みです。

結果

セットアップステージのトランザクションの結果は正 常に終了した場合はACKです。 デバイスはデータに問題があった場合は本ステージで は応答してはならないことになっているのでホストコ ントローラはHandshakeパケットを待ってタイムアウト になります。

トランザクションの終了時には通信要求レジスタ REQRのビット0は0になりチャネルAの要求は解 除されます。

トランザクションが成功した場合は次のデータステー ジに移ります。 失敗した場合は通信要求レジスタREQRのビット 0を1にするとチャネルAの通信を要求できます。 トランザクションの再送を試みるかどうかはプロセッ サのプログラムの判断によります。

データステージ

通信は次の順番で行います。

  1. ホストがデバイスにTokenパケットを送ります。
  2. TokenがINのときデバイスがDataパケットを送ります。
    TokenがOUTのときホストがDataパケットを送ります。
  3. TokenがINのときホストがHandshakeパケットを送ります。
    TokenがOUTのときデバイスがHandshakeパケットを送ります。
 リクエスト Token  データ数 内容
 GetDescriptor IN  リクエストに指定  ディスクリプタ
 GetConfiguration IN 1  構成値
 GetInterface IN 1  代替値
 GetStatus IN 2
 SetDescriptor OUT リクエストに指定 ディスクリプタ
 Syncframe OUT 2 フレーム番号

データステージを使うのは表のデバイスリクエストで す。

これ以外のデバイスリクエストではTokenにINを送って ステータスステージに入ります。



準備

セットアップステージで行った設定が残っていること を前提にした操作です。

ホストからデバイスに送る場合
  1. 該当チャネルのメモリ位置を0にしてDataパケットで送 るデータを書き込みます。
  2. 上の操作で移動したデータ位置を0にします。
  3. チャネル設定レジスタ2 CHR2 のデータ数に Dataパケットで送るデータ数を代表値で設定します。
  4. コントロールレジスタ CHCNR のToken選択を1 にしてOUTを選択します。
デバイスからホストに送る場合
  1. 該当チャネルのメモリのデータ位置を0にします。
  2. チャネル設定レジスタ2 CHR2 のIOに0にして TokenにINを選択します。
データステージを使わない場合

ステータスステージに移ります。

実行

通信要求レジスタのビット0に1を書き込んでチャネル Aのトランザクションをホストコントローラに要求しま す。

トランザクションの実行はセットアップステージの場 合と同じです。

結果

ホストからデバイスに送った場合
デバイスからホストに送った場合

データステージの継続と終了

ホストからデバイスに送った場合

デバイスに送るデータが残っている場合には該当チャ ネルのメモリの内容の更新とデータ位置を0にして実行 を繰り返します。

すべてのデータを送り終わったときはステータスステ ージに移ります。

デバイスからホストに送った場合

デバイスが送ったDataパケットのデータ数はポイント レジスタ POINTL , POINTH に示します 。

データ数が0のDataパケットを受け取ったらステータス ステージです。 ここでコントロール転送は完了します。

データ数が0以上のDataパケットを受け取ったら該当チ ャネルのメモリ位置を0にしてデータを読み出してから またデータ位置を0にして実行を繰り返します。

ステータスステージ

ステータスステージはデータステージのトランザクシ ョンのDataパケットのデータ数が0であることで認識さ れます。

ステータスステージを開始するのはDataパケットの送 り側になります。

準備

ホストからデバイスに送る場合
  1. チャネル設定レジスタ2 CHR2 のデータ数に 0を書き込みます。
  2. コントロールレジスタ CHCNR のToken選択を1 にしてOUTを選択します。
デバイスからホストに送る場合

ホストコントローラがトランザクションの前にステー タスステージを知ることはないのでデータステージの 場合 と同じです。

データステージを使わなかった場合

チャネル設定レジスタ2 CHR2 のIOを0にして TokenにINを選択します。

実行

通信要求レジスタのビット0に1を書き込んでチャネル Aのトランザクションをホストコントローラに要求しま す。

トランザクションの実行はセットアップステージの場 合と同じです。

結果

デバイスの調査

デバイスの情報はコントロール転送のデバイスリクエ ストを使って読み出します。

デバイスディスクリプタ

接続されたデバイスが何であるかを知るのは デバイスディスクリプタ によってです。

デバイスの基本的な情報が置いてあります。 通信の設定に関係のあるものは次のものがあります。

デバイスリクエスト

デバイスディスクリプタを読み取るにはデバイスリク エストのGetDescriptorを使います。

2番目にディスクリプタの番号を3番目にディスクリプ タの 形式 を指定します。 デバイスディスクリプタの大きさは18バイトに決まっ ているのでこれを6番目と7番目の2バイトで指定します 。 2バイトで数値を指定する場合は下位バイトを先に上位 バイトを後にします。

1番のコンフィギュレーションディスクリプタを読むデ バイスリクエストは次のようなデータ列になります。

0 1 2 3 4 5 6 7
80h 6 1 1 0 0 18 0


コンフィギュレーションディスクリプタ

FG05L26E.jpg(16056 byte)

デバイスの構成を決める情報を得 るために コンフィギュレーションディスクリプタ を読み出します。

構成とはエンドポイントの特性を決めるときの選択肢 のことです。 選択肢の数はデバイスディスクリプタの bNumConfigurations に示されます。

エンドポイントの特性はエンドポイントディスクリプ タにまとめられています。

エンドポイントディスクリプタはインターフェースデ ィスクリプタにまとめられています。

インターフェースディスクリプタはコンフィギュレー ションディスクリプタにまとめられています。

まとめられていると言ってもインターフェースディス クリプタはエンドポイントディスクリプタの見出しの ようなものです。
コンフィギュレーションディスクリプタもインターフ ェースディスクリプタの見出しのようなものです。

bNumInterfaceでコンフィギュレーションの持 つインターフェースの数が示されます。

構成を示す主要なディスリプタは次の3種類です。

デバイスリクエストGetDescriptorで読み出せ るディスクリプタはコンフィギュレーションディスク リプタだけです。

インターフェースディスクリプタとその配下のエンド ポイントディスクリプタは図のようにコンフィギュレ ーションディスクリプタに続いています。

コンフィギュレーションディスクリプタの「本構成の 全ディスクリプタのバイト数」のwTotalLength に構成の全長が示されています。


FG05L26F.jpg(13785 byte)

構成を示すディスクリプタは図のような木構造になっ ています。

エンドポイントディスクリプタは実体の内容を記述し たものですがインタフェースディスクリプタやコンフ ィギュレーションディスクリプタはエンドポイントの 情報をたどるためにあります。


デバイスリクエスト

構成を読み取るには2段階のデバイスリクエストの発行 が必要です。

  1. コンフィギュレーションディスクリプタを読み取る。
  2. wTotalLengthで示されるバイト数で構成の全デ ィスクリプタを読み出す。

1番のコンフィギュレーションディスリプタを読み出す データ列です。 コンフィギュレーションディスリプタは9バイトです。

1番目のGetDescriptor
0 1 2 3 4 5 6 7
80h 6 1 2 0 0 9 0

2番のコンフィギュレーションディスリプタを読み出す データ列です。 コンフィギュレーションディスリプタを含んで構成の 全体をwTotalLengthのバイト数で読み出します 。

2番目のGetDescriptor
0 1 2 3 4 5 6 7
80h 6 1 2 0 0 wTotalLength

上のデバイスリクエストで構成の全体を示すコンフィ ギュレーションディスクリプタとインターフェースデ ィスクリプタとエンドポイントディスクリプタが読み 出されます。

読み出した構成のデータ中のディスクリプタの位置は 次のことで探索できます。

プロセッサは構成の情報から求めるエンドポイントの ディスクリプタを読み出してホストコントローラのチ ャネル設定レジスタの設定値の根拠とします。

インターフェースディスクリプタ

通信に必要な情報はエンドポイントディスクリプタに あります。 この上位にあるディスクリプタはエンドポイントディ スクリプタをたどるためにあります。 この頭にあるのがコンフィギュレーションディスクリ プタです。

インターフェースディスクリプタ は中間にあるのですがこれを介在させる理由は代替値 にあります。 インターフェースの代替値を変えることで全体の構成 を変えなくてもそのインタフェースの配下にあるエン ドポイントをデバイスが予め準備した別の設定で使う ことができます。

インターフェースディスクリプタは個別にデバイスリ クエストで読み出すことはできません。 コンフィギュレーションディスクリプタの全体構成の 一部として読み出されます。

インターフェースの代替値

デバイスがエンドポイントをいくつかの使い方ができ るように作っていてホストにそれを選択できるように 公開していればひとつのエンドポイントは複数の使い 方に違いのあるエンドポイントディスクリプタを持っ ています。

同一の構成中にある違う値の代替値を持つ同じ番号の インターフェースディスクリプタは代替値を切り替え ることでエンドポイントの使い方を変えることを実現 するために同じエンドポイントに違う使い方を記述し たエンドポイントディスクリプタを持っています。

エンドポイントディスクリプタ

エンドポイントディスクリプタ は構成の最も下位にあってエンドポイントの使い方の 情報を記述してあります。

ディスクリプタによって示されるエンドポイントの情 報は次のものです。

エンドポイントディスクリプタは個別にデバイスリク エストで読み出すことはできません。 コンフィギュレーションディスクリプタの全体構成の 一部として読み出されます。

ホストの役割

通信の割り当て

転送量と時間
パケット バイト数 時間(us)
1.5Mbps 12Mbps
Token 4 21.44 2.66
Handshake 2 10.72 1.33
Data 4+8 64.32 7.97
4+16 - 13.28
4+32 - 23.90
4+64 - 45.15
4+1023 - 679.27
1バイト 5.36 0.664

フレームをセグメントに分割してチャネルを割り付け る単位としています。 フレームは1msの時間に固定されているので表の時間を 参考にして時間内に納まるようにチャネルを収容しま す。

ひとつのセグメントではひとつの通信単位を実行しま す。 通信単位はトランザクションで Token → Data → Handshake の3パケットを通信します。

図のようにセグメント0にチャネルDを割り当てるとSOF の直後にトランザクションを実行します。

セグメント4から7はチャネルの割り当てがなく空なの で通信は行われません。

セグメントにチャネルが割り当てられていても通信要 求レジスタREQRの該当のビットが1になってい ないと通信は実行されません。

ホストコントローラは要求のあったチャネルのセグメ ントのトランザクションを自動的に実行しますが時間 の管理まで行っていないのでホストプロセッサは実行 されるチャネルのトランザクションの全時間がフレー ム内の1ms以内に納まるように予定します。


FG05L23A.jpg(18427 byte)

通信手順

エンドポイントの特性に合わせて チャネルレジスタ を設定しておきます。

送信

  1. トランザクションの通信するデータをホストコントロ ーラの該当チャネルのメモリに書き込みます。
    1. 下ポイントレジスタPOINTLのビット0と1に 1を書き込んで位置を0にします。
    2. データレジスタDATAにデータを書き込みま す。
    3. 下ポイントレジスタPOINTLのビット0と1に 1を書き込んで位置を0に戻します。
  2. 通信要求レジスタREQRの該当チャネルのビット を1にします。
  3. 通信済みレジスタRDYRの該当チャネルが1にな るのを待ちます。

受信

  1. 下ポイントレジスタPOINTLのビット0と1に 1を書き込んで位置を0にします。
  2. 通信要求レジスタREQRの該当チャネルのビット を1にします。
  3. 通信済みレジスタRDYRの該当チャネルが1にな るのを待ちます。
  4. ホストコントローラの該当チャネルのメモリに受信デ ータがあります。

受信データ数はポイントレジスタに示します。

  1. 下ポイントレジスタPOINTLのビット0に1を書き 込んで位置を0にします。
  2. トランザクションが受信したデータをデータレジスタ DATAから読み出します。

通信結果への対応

ACK 肯定応答

次のデータをホストコントローラの該当チャネルのメ モリに書き込んで通信要求レジスタREQRの該当 チャネルのビットを1にします。

次のデータがない場合またはホスト側が時間をあけた い場合は通信要求レジスタREQRの操作をしませ ん。 (該当チャネルのビットを1にしないことです。)

NAK 否定応答

再送

現在のデータはそのままで通信要求レジスタREQR の該当チャネルのビットを1にします。

エラー

NAKが連続する場合は再送を繰り返せますがホストプロ セッサ判断で通信を停止することもできます。 この場合は通信要求レジスタREQRを操作しませ ん。

通信の再開はホストプロセッサの判断によります。

STALL 停止中

再送を繰り返せますがホストプロセッサ判断で通信を 停止することもできます。 この場合は通信要求レジスタREQRを操作しませ ん。

通信の再開はホストプロセッサの判断によります。

タイムアウト

再送を繰り返せますがホストプロセッサ判断で通信を 停止することもできます。 この場合は通信要求レジスタREQRを操作しませ ん。

通信の再開はホストプロセッサの判断によります。

フレーム中のひとつのチャネルのトランザクション数

USBの仕様では最多の頻度でもひとつのエンドポイント は1フレームに1回のトランザクションを受けるのを上 限として前提にしているようです。 バルク転送以外では仕様で1フレームに2回以上のトラ ンザクションは置けません。 バルク転送でも設定上は可能ですが当方ではUSBでは1 フレームに1回のトランザクションが上限と理解してい ます。 当方のホストコントローラとデバイスコントローラが バルク転送のチャネルにセグメントを2個以上割り当て て1フレームに2回以上のトランザクションがあるのは 何の問題もありません。