So-net無料ブログ作成
検索選択

USBプロジェクト - ファームウェアに立ち返る (5) [USB]このエントリーを含むはてなブックマーク#

1516092

正しいHIDデバイスを追い求めるシリーズ、五の段です。

SET_ADDRESSリクエストの処理

バス・リセットの次は、SET_ADDRESSリクエストが来るはずです。 このリクエストは、エンド・ポイント0にSETUPトランザクションとして届きます。 USBデバイスの状態に応じて、USB割り込みハンドラから以下の関数を呼び出します。

//----------------------------------------------------------------------------
//  Process for Default state.
//----------------------------------------------------------------------------
void doDefaultStateProc(void) {
  if(UIR1_RXD0F) {              // any data received via EP0?
    UIR2_RXD0FR = 1;            // Acknowledge
    UCR0_RX0E = 0;              // Turn off EP0 receiver
    if(USR0_SETUP) {            // SETUP packet?

      copySetupBuffer();        // Copy SETUP parameters

      if(USR0_RP0SIZ != 8) {    // SETUP Transaction must be Size=8
        forceStall();           // otherwise we have an Error Condition
      } else {               
        if((setupBuffer.bmRequestType & 0x60) == 0) {
          // Standard Request Decoder:
          switch(setupBuffer.bRequest) {
            case SET_ADDRESS:   // 5
              setAddressSetup();
              break;
            default:
              forceStall();
              break;
          }
        } else {
          forceStall();         // Unexpected request
        }
      }
    } else {                    // or a normal packet
      forceStall();             // Unexpected transaction
    }
    UCR0_RX0E = 1;              // Activate EP0 Receiver again
  }
  if(UIR1_TXD0F) {              // has EP0 sent Data?
    UIR2_TXD0FR = 1;            // Acknowledge
    UCR0_TX0E = 0;              // Turn off EP0 transmitter

    setAddressStatus();         // Expected SET_ADDRESS
  }
}

受信したSET_ADDRESSに対する処理は、setAddressSetup(void)関数で行われます。 続くステータス・ステージに備える処理もsetAddressSetup(void)関数で記述されています。

DEFAULT状態では、SET_ADDRESSリクエストしか期待されていません。 このため、他のリクエストおよび、SETUPトランザクション以外は、不正なトランザクションとみなされます。 その場合、STALLによる応答をすべく、forceStall(void)が呼び出されます。

//----------------------------------------------------------------------------
//  Force STALL Condition for EP0 (both IN and OUT)
//  as a Response to an invalid SETUP Request
//  Flags will be auto-cleared by the next SETUP Token
//----------------------------------------------------------------------------
void forceStall(void) {
  UCR3_OSTALL0 = 1;
  UCR3_ISTALL0 = 1;
}

forceStall(void)関数は、ステータス・ステージのハンドシェイク・パケットとしてSTALL送るための設定を行います。 このマイコンには、RX0E=0としておくと、ハンドシェイク・パケットとして、NAKを返すという機能もあります。 サンプル・プログラムを見る限りでは、どうやらSTALL設定の方が優先されているようです。

EP0は、いつでもSETUPトランザクションを受け付けられるように、RX0E=1として受信機を有効にしています。 本当に、SETUPトランザクションが続けて発行されるような事態がありうるのだろうか?

SETUPトランザクションが続けてくる事態は、正しく実装されたホストでは、起こりえないそうです。 ただし、ホスト側にバグがあった場合に備える必要はありそうです。 もし、予期せずにSETUPトランザクションが届いたら、処理中のSETUPトランザクションを破棄するのが正しい実装だそうです。

DEFAULT状態では、SETUPステージの後のステータス・トランザクションの処理も行います。 ステータス・トランザクションが終了したら、USBアドレスを更新して、状態を遷移させます。 実際の処理は、setAddressStatus(void)で記述されます。

割り込みハンドラのディスパッチャ

一方、割り込みハンドラのディスパッチャは、このようになります。

  switch (usbState) {
    case US_POWERED:
    case US_DEFAULT:
      doDefaultStateProc();
      break;
    case US_ADDRESSED:
    case US_CONFIGURED:
    case US_SUSPENDED:
    default:
      ;
  }

まだ、DEFAULT状態以外の処理は、未実装です。

doDefaultStateProc(void)関数は、SET_ADDRESSリクエストにのみ反応しますが、GET_DESCRIPTORリクエストは、DEFAULT状態でも有効なリクエストなので、修正が必要です。 他のリクエストについても調べなくては。

このプログラムでは、状態による分岐を優先する書き方をしてみました。 どうしても状態コードとリクエスト・コードのマトリックス条件で処理を分けなくてはならないので、分岐が複雑になってしまいます。 もうちょっと、スマートにならないかな。

USB2.0の仕様書を読んでみると、リクエストごとに各状態で行うべき動作が記述されておりました。 どうも、仕様書と見比べてプログラムを作る分には、これに従ったほうが良さそうです。 次回、方針変更をする予定です。

SET_ADDRESS処理関数

SETUPトランザクションの終了時に実行される処理は、setAddressSetup(void)に記述されます。

//----------------------------------------------------------------------------
//  SET_ADDRESS Standard Device Request Handler
//  called by SETUP handler.
//  according to USB2.0 spec page 256
//----------------------------------------------------------------------------
void setAddressSetup() {
  // SET_ADDRESS transaction validation
  if (
    (setupBuffer.wIndex == 0) &&
    (setupBuffer.wLength == 0) &&
    (setupBuffer.wValue < 128)
  ) {
    // configure endpoint #0 to send an empty DATA1
    // at the next IN Transaction
    UCR0  = 0b10100000;
    //        ||||++++-- TP0SIZ = 0 reset packet size register
    //        |||+------ RX0E = 0   disable EP0 receiver
    //        ||+------- TX0E = 1   enable EP0 transmitter
    //        |+-------- Reserved (0)
    //        +--------- T0SEQ = 1  set TX sequence bit
  } else {
    // response for illegal SETUP packet.
    forceStall();
  }
}

まず、SETUPパケットで送信されたパラメータが正しい値であるかどうかを比較します。 SET_ADDRESSは、wValueに7ビットのUSBアドレスが入り、wIndexとwLengthには、0が入ります。 もし、入っている値が範囲外であれば、forceStall(void)で処理が正常に終了できなかったことを示します。

値が正しいことが確認されたら、次に発生するステータス・トランザクションに備えて、EP0送信機を起動します。

ステータス・トランザクションの終わりが、コントロール転送の無事終了を示しています。 SET_ADDRESSリクエストは、ここで初めて終了するので、ホストから指定されたUSBアドレスを設定することが出来ます。

//----------------------------------------------------------------------------
//  SET_ADDRESS Standard Device Request Handler
//  called by STATUS handler.
//  according to USB2.0 spec page 256
//----------------------------------------------------------------------------
void setAddressStatus(void) {
    // A STATUS transaction was received.
    // Set the USB address.
    UADDR = (byte)setupBuffer.wValue | UADDR_USBEN_MASK;
    if (setupBuffer.wValue == 0) {
      // make a transition to DEFAULT
      usbState = US_DEFAULT;
    } else {
      // make a transition to ADDRESSED
      usbState = US_ADDRESSED;
    }
    // Reset the request code.
    setupBuffer.bRequest = REQUEST_COMPLETE;
    // Activate EP0 Receiver for next request.
    UCR0_RX0E = 1;
}

アドレスとして、"0"が指定されていたら、DEFAULT状態に戻ります。 また、"0"以外の値が指定されていたら、ADDRESSED状態に進みます。 そして、次に発行されるSET_CONFIGURATIONリクエストを受信すべく、EO0受信機をイネーブルにします。

アドレスの変更がステータス・ステージまで待たされる理由は、USB2.0仕様書の256ページに書いてあります。 もし、SETUPステージであわててアドレスを変更したら、続くステータス・トランザクションは、アドレスが異なるために通信することができません。 かならず、トランスファが終了してからアドレスを変更しなくてはなりません。

setAddressStatus(void)が呼び出された後は、 次のセットアップ・トランザクションを待つためにRX0E=1としなくてはならないはずです。 ところが、サンプル・プログラムでもsetAddress(void)でEP0受信機がディセーブルされて以来、イネーブルされた形跡がありません。 何で、動いているように見えるんだろう?

私の見落としでした。 doDefaultStateProc(void)関数の最後でRX0E=1としておりました。

SETUPバッファ構造体に関する方針変更

どうもプログラムを書きにくいので、方針変更し、SetupBuffer構造体を変更しました。

//----------------------------------------------------------------------------
//  Structure of Setup Packet sent during
//  SETUP Stage of Standard Device Requests
//  according to USB2.0 spec page 248
//----------------------------------------------------------------------------
typedef struct {
    byte        bmRequestType;      // Characteristics (Direction,Type,Recipient)
    byte        bRequest;           // Standard Request Code
    word        wValue;             // Value Field
    word        wIndex;             // Index or Offset Field
    word        wLength;            // Number of Bytes to transfer (Data Stage)
}   SetupBuffer;

従来、使用されていたiword構造体を廃止して、16-bit符号無し整数wordを使っています。 エンディアンの変更は、エンド・ポイントをバッファにコピーする時に行っています。

//----------------------------------------------------------------------------
//  Copy SETUP packet into buffer.
//  Intel words are converted into MOTOROLA words.
//----------------------------------------------------------------------------
void copySetupBuffer(void) {
  setupBuffer.bmRequestType     = UE0D0;
  setupBuffer.bRequest          = UE0D1;
  setupBuffer.wValue            = (UE0D3 << 8) | UE0D2;
  setupBuffer.wIndex            = (UE0D5 << 8) | UE0D4;
  setupBuffer.wLength           = (UE0D7 << 8) | UE0D6;
}

HC08のような純粋な8-bitマイコンに16-bit整数を扱わせるのは酷なんだけど、コンパイラにがんばってもらいましょう。

2008-03-24 23:14 コメントでの指摘事項および情報を追加。

付録 : USBプロジェクト索引

参考文献

USBハード&ソフト開発のすべて―USBコントローラの使い方からWindows/Linuxドライバの作成まで (TECHI―Bus Interface)

USBハード&ソフト開発のすべて―USBコントローラの使い方からWindows/Linuxドライバの作成まで (TECHI―Bus Interface)

  • 作者: インターフェース編集部
  • 出版社/メーカー: CQ出版
  • 発売日: 2006/07
  • メディア: 単行本

nice!(0)  コメント(16)  トラックバック(0)  このエントリーを含むはてなブックマーク#

nice! 0

コメント 16

Tsuneo

Set_Address は他のリクエストと違い実装に注意が必要です。他のリクエストは、SETUP(とDATA)ステージで受けたリクエストを実行した後に、STATUSステージでその結果を報告するという実装になります。Set_Addressリクエストの場合、バス上ではSet_AddressリクエストのSTATUSステージが終わった直後にアドレスが切替わります。USBエンジンによって次の2通りの実装があります。
- 他のリクエストと同様SETUPの処理の中でアドレスレジスタを書換えておけば、USBエンジンがSTATUSステージの後、自動的に切り替えてくれる
- ファームウェアでSet_AddressのSTATUSステージの終了を検出した後にアドレスレジスタを書換える

残念ながら、MC68HC908JB16のデータシートにはどちらのタイプかちゃんと書いてありません。こういう場合は大抵ファームウェアで面倒を見なければならないのですが、メーカーに確認するか、信頼できるサンプルから読みとることになります。で、サンプルでは、ep0_txd()でUADDR_UADDを書換えているので、やはり後者ということのようです。


> DEFAULT状態では、SET_ADDRESSリクエストしか期待されていません。 このため、他のリクエストおよび、SETUPトランザクション以外は、不正なトランザクションとみなされます。 その場合、STALLによる応答をすべく、forceStall(void)が呼び出されます。

良い点に目をつけましたね。
USB2.0スペックは、それぞれの標準デバイスリクエストについてDefault、Addressed、Configuredの各ステートでどう応答すべきか細かく規定しています。
9.4.1 Clear Feature (usb_20.pdf p252)以下
ここで、応答が"not specified"の場合はエラーとしてSTALLを返します。
もちろん"Request Error"の場合もSTALLを返します。

このSTALLを返す、返さないというロジックの実装は煩雑ですが、
- サポートしないリクエストに対しては確実にSTALLを返す
- サポートするリクエストであっても、デバイスステートとSETUPパラメータが合致しなければSTALLを返す
という点が重要です。

そこで、
- 個々のリクエストハンドラでは、デバイスステートとSETUPパラメータをチェックし、規定の条件を満たすときのみ処理を行い、フラグを立てる
- 個々のリクエストハンドラから返ってきた時点でフラグを見て、処理が行われていなければSTALLを発行する
という実装にすると、サポートしないリクエストや条件に対して確実にSTALLが返ります。
また、ポジティブロジックで書けるのでコードが読みやすくなり、コードサイズもコンパクトに収めることができます。

具体的には、フラグをreq_Handledとすると、
- req_Handled = FALSE;
- リクエストタイプ(標準、クラス、ベンダー)による分岐
- - 各リクエストタイプハンドラ(標準デバイス、クラスもしくはベンダー)
- - リクエスト(bRequest)による分岐
- - - 個々のリクエストハンドラ
- - - デバイスステート、bmRequestType、wValue、wIndex、wLengthをチェック
- - - - リクエスト固有の処理
- - - - req_Handled = TRUE;
- if( ! req_Handled ){ 実際にSTALLを発行 }


では、どの標準デバイスリクエストをサポートすべきか、についてまとめておくと、

必須
Get_Descriptor, Set_Address, Set_Configuration

USBコンプライアンステストに準拠するなら、
Get_Status, Clear_Feature, Set_Feature
Get_Configuration, Get_Interface

必要に応じてサポートする(必要なければSTALL)
Set_Interface
- alternate インターフェースをインターフェース・デスクリプタで宣言している場合のみ(アイソクロナス転送など)
Synch_Frame
- アイソクロナス転送で、シンクロフレームを使用する場合のみ
Set_Descriptor
- デスクリプタの変更、通常使わない


USBコンプライアンステストで、USBCVがどの標準デバイスリクエストをどういった手順で発行するかという詳細は、"USB Command Verifier Compliance Test Specification.pdf"にこと細かく書いてあります。このPDFは、USBCV R1.3にドキュメントとして付属しています。なお、USBCV は USB.org からダウンロードできます。

USBCV R1.3
http://www.usb.org/developers/tools/

USBのロゴを取得するつもりがなくとも、確認のためUSBCVを一度通しておいた方が良いでしょう。
USBCVは、リクエストハンドラのデバッグツールとして使えます。

なお、USBCVを走らせるには、
- Windows XP SP2 (日本語システムで可)
- ハイスピード(USB2.0)のPCのポートとハイスピード(USB2.0)の外付けハブが必要です。
- PS/2マウス、キーボードを用意してください(あるいはノートPC)。
USBCVは走っている間はWindowsのUSBスタックを置き換え、完全にUSBを乗っ取ります。USBマウス、キーボードは通常の使用はできません(テスト対象となってしまう)。ノートPCのキーボード、パッドなどは通常内部でPS/2で接続されているのでOKです。またMCU開発のためUSBデバッグアダプタを使用している場合、USBCVが走っている間は使えなくなります。シリアル接続のアダプタを用意するか、2台目のPCが必要になります。

Tsuneo
by Tsuneo (2008-03-24 17:50) 

Tsuneo

>EP0は、いつでもSETUPトランザクションを受け付けられるように、RX0E=1として受信機を有効にしています。 本当に、SETUPトランザクションが続けて発行されるような事態がありうるのだろうか?

ホスト側がきちんと実装してあればあり得ません。Windowsのようにバグだらけだとあり得ます。

このWindowsのバグは、KBには詳細は書いていませんがまさにその事態が起きていました。
"A USB device that is connected to a USB 2.0 hub is not detected in Windows XP Service Pack 2, Windows Server 2003 Service Pack 1, or Windows Server 2003 x64 versions"
http://support.microsoft.com/kb/892050/en-us

USB2.0スペックでは、前のコントロール転送が終了する前に新たなSETUPが送られてきた場合、現在のリクエストを破棄して新たなSETUPに対応することになっています。


>サンプル・プログラムでもsetAddress(void)でEP0受信機がディセーブルされて以来、イネーブルされた形跡がありません。

えーと、どのサンプル・プログラムを見てますか?
リンクをください。

Tsuneo
by Tsuneo (2008-03-24 20:21) 

noritan

毎度、おせわになっております。

1) SET_ADDRESSリクエストのお話
なるほど、USBアドレスがダブル・バッファ(これは一般に通じる言葉なのかな?)になっているチップもあるのですね。MC908JB16は、仕様書のP172、"11.5.1.3 Address Field (ADDR)"にちょこっとだけ、"This field is compared to the lower seven bits of the UADDR
register"と書いてあるので、バッファなぞせずに直接比較されているようです。

2) STALL扱いの話
サンプル・プログラムを改造しながらハンドラを書いた後、確認のため仕様書を見ました。そこで初めて、仕様書ではリクエスト別にそれぞれの状態で行うべき事が書いてある事に気が付きました。これを見ていたら、先にリクエストで分岐させるプログラムにしたことでしょう。きっと、次回方針変更すると思います。
仕様書には、あちらこちらに"not specified"といい加減な事が書いてあります。「決まっていないから何をしてもいい」と解釈すれば、どんな状態でも同じ動作にしてしまうのも可能だと思いますが、出来たら、STALL扱いにしてしまおうとおもっています。
フラグを立てて、一括してSTALL処理をする案、使わせていただきます。フラグ変数(いわゆる番兵さん)を立てなくても、"return FALSE;"でできますよね。Cでは、"try-catch"は使えないな。

3) USBCVのお話
実は、"HID Descriptor Tool"を見つけたときに一緒に落としてきて、良くわからないまま実行させていました。見事に、マウスが反応しなくなりました。幸い、ノートPCのキーボードが反応したので、復帰できましたが、危ないところでした。

4) 連続SETUPのお話
Windowsでは、あるんですね。USB2.0の仕様書に記述があるということですが、まだ、見当たりません。ボチボチ探します。

5) ディセーブルされたままのEP0受信機のお話
サンプル・プログラムのリンクは、ここです。
http://forums.freescale.com/attachments/freescale/8BITCOMM/769/1/TestHID.zip
フォーラムで提供されていたサンプル・プログラムなので、出所としては十分に怪しいと思います。でも、その怪しいファームウェアで通信できているようなので、謎です。
これの元になっている、ELMICROのサンプル・プログラムでも同様に見えます。たぶん、これです。
http://www.hc08web.de/usb08/files/usb08_fwv102a_icc08.zip
setAddressで、UCR0を設定するときに一緒にRX0Eをクリアして、handleINでもRX0Eをセットしているようには見えません。

と、思って、プログラムを見直してみたら、handleSetupの最後でRX0Eをセットしていました。私のプログラムでも、doDefaultStateProcの最後でセットしていました。これは、失礼いたしました。

by noritan (2008-03-24 22:47) 

hamayan

どうもです。進んでいますね。
風邪引いて一週間くらいなにもする気が起きなかったのですが、ようやく昨日(今朝)時間を掛けていじっていました。

で、ボーっとする頭でうっかり開発ボードのコネクタを接続したまま、JP2を外した状態でUSBコネクタを接続すると、
「あれ!Windowsが新しいハードウエアの検出を行っている!」

JB16のROMをブランクにして、D+、D-を470KΩでプルダウンしながらUSBに接続すると、内蔵のローダーが起動すると言う話は聞いていましたが、IRQに高電圧が掛かった状態でも同じ現象が発生するのかもしれません。

で、慌ててUSBICP.EXEを探して(苦労した!)、ハードウエアウイザードの時にinfを読ませましたが、どうも情報が一致しないらしく、ドライバーのインストールは失敗しています。残念。

ケーブルをあれこれ、あれこれ外す事無く書き換えができれば楽なんですけれどね。

by hamayan (2008-03-25 08:59) 

Tsuneo

>1) SET_ADDRESSリクエストのお話
「ファームウェアでSet_AddressのSTATUSステージの終了を検出した後にアドレスレジスタを書換える」というのは、もたもたしていると次の新たなアドレスでのリクエストがホストから来てしまうから、タイミング的にややつらい面があります。

たしかにこのあたりのファームウェアとUSBエンジンの細かい役割分担は、MCUによって色々ですね。Cypress EZ-USBのように「あんなこと」や「こんなこと」までやってくれるエンジンもありますが。まあ、このエンジンで鍛え上げれば大抵のエンジンは手の内です。ほら、あばたもえくぼって...

>2) STALL扱いの話
"return FALSE;"だと、"return TRUE;"も必要で、結局elseが必要になり、またハンドラを呼び出した側でもboolean変数で個々のハンドラの戻り値を受ける必要が出て...
あまりきれいなコーディングじゃないですが、グローバルフラグの方がすっきりします。

>3) USBCVのお話
USB-IFの大御所回答者のBarry Twycross (Apple関係者)が珍しくヘルプを出していたことがありました。
MacBookでBootCampにWindowsのせてUSBCVを走らせたところ、キーボードもパッドも全く動かなくなって、WindowsのUSBスタックが戻せなくなってしまったけど、どうすんの?
て、普通はWindows の再インストール以外どうしようもありません。
ちなみに、USBCV 1.3からUSBCVが走っている最中でもUSBマウスは動作するようになったということで、すわMacBookで走らせたところ途中でクラッシュしたというのが元のようです。
MacBookのキーボードとパッドは内部でUSB接続されている、というお話しでした。MacにはPS/2のポートもありません。ちなみにBlueToothもUSB経由です。結局BarryはParallels使ってremote desktopからDevice Manager立ち上げてなんとか戻したそうです。ごくろうさま。

>4) 連続SETUPのお話
さすがにWindowsでもこんなひどいバグはフィックスされます。
でも、このHIDは一応動くけどスピードが本来の半分以下だよというバグはWinXP SP3 RC でフィックスされていないので、放置になりそうです。
"The data transfer speed of a USB 1.x device may be slower than expected when you connect it to a USB 2.0 hub on a Windows XP SP2-based computer"
http://support.microsoft.com/kb/940021/en-us

Tsuneo


by Tsuneo (2008-03-25 12:25) 

noritan

2) STALL扱いの話
私のイメージは、
if (setupBuffer.wIndex != 0) return FALSE;
if (setupBuffer.wLength != 0) return FALSE;
if (setupBuffer.wValue >= 128) return FALSE;
という途中で処理をやめてしまう方法です。これだと"else"処理は出てきません。(意味が違うか?)

4) 連続SETUPのお話
"KB940021"読みました。回避方法は、「connect the USB 1.x device directly to the root universal serial bus (USB) port」だそうですが、"root port"が外に出ているPCって、まだあるんですか?デスクトップPCの本体についているやつかな?ノートPCは、もれなくハブにつながっているように見えますね。

by noritan (2008-03-25 12:39) 

noritan

hamayanさん、お久しぶりでございます。
大病を患って、入院でもされたのかと思っておりました。

JB16のUSBモニタがどういった条件で動くのかと言う情報は、マスクROM(だよな)を読むと良くわかります。私の解析結果は、倫理上、オモテには出せません。

by noritan (2008-03-25 12:44) 

Tsuneo

hamayanさん、お久しぶりです。
風邪ですか、今時は日によって温度差が大きいから。ご自愛ください。

>IRQに高電圧が掛かった状態でも同じ現象が発生するのかもしれません。
この状態でチップがUSBに出しているVID/PID は何でしょうか。
USBView かUVCView(Linux用ではありません)で見えますか。

USBView か UVCView のどちらかがあるとWindows PCに接続しているデバイスのデスクリプタが、このNIのFAQに出ているスクリーンショットのように見えます。USBView.exeも下の方に添付がありますね。

"USBデバイスのベンダIDとプロダクトIDを知るにはどうすればよいですか?" on NI.com
http://digital.ni.com/public.nsf/allkb/1DEC366794E3584A862570980007A73A


残念ながらMSは UVCViewの直リンクを落としてしまったので、MSから正式にダウンロードしようとすると、面倒なことにWDK (Windows Driver Kit)に入っているのをWDKごと拾って、WDKをインストールするしかないですね。さらにWDKはフリーですがMSに登録する必要があります。
"How to Get the Windows Driver Kit and the Windows Logo Kit"
http://www.microsoft.com/whdc/DevTools/WDK/WDKpkg.mspx

USBViewは、WinDDK にソースコードが入っていて、DDK付属のコンパイラでビルドできます。つまり、これまたDDKごとダウンロード・インストールが必要ということです。
"DDK - Windows Driver Development Kit"
http://www.microsoft.com/whdc/DevTools/ddk/default.mspx
このページのこのリンクです。
"Download the Windows Server 2003 SP1 DDK [236 MB ISO file]"

まあ、Linux ならこんな苦労をしなくても、lsusbコマンドでOKなんですけれど。

Tsuneo
by Tsuneo (2008-03-25 13:33) 

hamayan

> この状態でチップがUSBに出しているVID/PID は何でしょうか。

すいません、家に帰ったら詳しく調べますが、VIDは確か0x04**位の番号で、一応
Freescale Semiconductors HKとツールは表示していたと思います。

by hamayan (2008-03-25 14:38) 

noritan

この"In-Circuit Programming"の機能は、アプリケーション・ノートAN2399に書いてあります。
http://www.freescale.com/files/microcontrollers/doc/app_note/AN2399.pdf
これによると、VID=0x0425; PID=0x0301 という表示が見えます。

USBICP.EXE は AN2399SW.zip に入っているのですが、ほんとうだ、WEBからは探し出せない。さっさと、JMに移行しろということなのか。

by noritan (2008-03-25 15:12) 

hamayan

> さっさと、JMに移行しろということなのか

AN3561でJM60もこのツール使って書き換えできる様に見えますね。
http://www.freescale.com/files/microcontrollers/doc/app_note/AN3561.pdf?fsrch=1
フリスクも折角有る機能なんだから、もう少し大々的にやって欲しいな。

by hamayan (2008-03-25 15:43) 

Tsuneo

noritan さん、

2) STALL扱いの話
この辺のコーディングは好みの問題なので、実際の処理を行わないリクエストはすべてSTALLを確実に返すという形ができれば、後は個人の感性におまかせします。

4) 連続SETUPのお話
問題が複雑なのは、どちらのバグについても、すべてのメーカーのハブでこれらのバグが出てくるのではないのです。最初のKBでMSが次のように正直に述べてますね。
http://support.microsoft.com/kb/892050/en-us
"CAUSE
This problem occurs because the Microsoft USB 2.0 driver causes an Enhanced Host Controller Interface (EHCI) specification violation."

ホストコントローラのドライバのコーディングで規格外のことをやってしまったと。それでUSBハブのチップによって動作が変わってきます。つまり、ハブによってバグが全く出ないものと、しっかり出てしまうものとがあるわけです。さすがにすべてのハブでバグが出るようなら、いくら無知なMSでも開発段階で気がつきます。つまり、MSが開発や検証に使ったハブのチップと同じ、もしくは似たようなチップを搭載したハブはセーフで、そうではないハブはアウトとなったのです。

USBの開発にはプロは通常BELKINかAPCのハブを使います。これは、USBのコンプライアンステストで従来BELKINやAPCのハブを使ってきたからです。
"Full and Low Speed Electrical and Interoperability Compliance Test Procedure"
http://www.usb.org/developers/docs/USB-IFTestProc1_3.pdf
Gold Tree (page D-5)

だから、BELKINと同様のチップを使った高価なハブではバグが出ないで、安いハブでバグが出るということなのです。


hamayan さん、
デバイスのVID/PIDがわかれば、ドライバーをインストールしなくてもドライバのINFファイルをテキストエディタで覗いて、対応しているかどうかがわかります。INFファイルのなかで、VID_vvvv&PID_pppp (vvvvとppppはHEX)という部分が VID/PIDに対応します。
"VID_"という文字列をサーチすればすぐに見つかるでしょう。

また、USBView でデスクリプタがきちんと見えるということで、USB的にはデバイス側は問題なく動作しているという確認ができます。

ただ、デバイスがHIDだと、すでにドライバーがWindowsにビルトインされているのでこの手が使えません。しかし、Windowsが新しいハードウエアの検出を行うのなら、デバイスはHIDではないですね。


AN2399とAN2399SW.zipはフリスクのこのページのリストからダウンロードできました。
ダウンロードに際してしっかり登録させられますが。
"Universal Serial Bus (USB)" on Freescale.com
http://www.freescale.com/webapp/sps/site/overview.jsp?nodeId=0220502060&tid=tCNhl

Tsuneo
by Tsuneo (2008-03-25 20:02) 

noritan

そうか、アプリケーション・ノート関連プログラムは、USB専用ページに入っていたのか。何で、検索しても出てこないんだろう。

ハブによって、動いたり、動かなかったり、俗に言う「相性」でしょうか。仕様があいまいだと起こりうる事態ですよね。

"return"でエラーコードを返すコーディングをしてみました。STALL以外のエラーが出てくるかも知れないので、byte型にしてみました。まだ、泥くさい感じがします。

by noritan (2008-03-25 23:20) 

hamayan

JB16の出すvidは0x0425、pidは0xff02でした。
usbicp.infのvid、pidの記述は以下の通りです。
[USBMCU.icp]
%String2%=uicp.Install,USB\VID_1061&PID_ff01
%String3%=uicp.Install,USB\VID_0425&PID_ff01
%String4%=uicp.Install,USB\VID_0425&PID_ff02

エニュメレーションは
GET_DISCRIPTOR(device)

SET_ADDRESS(2番)

GET_DISCRIPTOR(device)

GET_DISCRIPTOR(configuration)

GET_DISCRIPTOR(configuration)

まで来たところでハードウエアウイザードが開始されています。
最終的には「このデバイスのドライバの場所がみつかりませんでした。」
でエラーとなります。

※一度ノーマルな手順でローダーの起動をやってみようと思います。470KΩの抵抗が無いなぁ。

by hamayan (2008-03-26 07:56) 

Tsuneo

noritan さん

4) 連続SETUPのお話
>ハブによって、動いたり、動かなかったり、俗に言う「相性」でしょうか。仕様があいまいだと起こりうる事態ですよね。

仕様があいまいというより、MSの仕様を策定した上級プログラマがEHCIのスペックを理解していなかったというのが真相でしょう。


>USB2.0スペックでは、前のコントロール転送が終了する前に新たなSETUPが送られてきた場合、現在のリクエストを破棄して新たなSETUPに対応することになっています。
>>USB2.0の仕様書に記述があるということですが、まだ、見当たりません。ボチボチ探します。

見つかりましたか? これです。
5.5.5 Control Transfer Data Sequences (usb_20.pdf p43)
...
If a Setup transaction is received by an endpoint before a previously initiated control transfer is completed, the device must abort the current transfer/operation and handle the new control Setup transaction. A Setup transaction should not normally be sent before the completion of a previous control transfer. However, if a transfer is aborted, for example, due to errors on the bus, the host can send the next Setup transaction prematurely from the endpoint's perspective.

Tsuneo
by Tsuneo (2008-03-26 16:48) 

Tsuneo

hamayan さん

このINFファイルのように複数のデバイスID(VID/PID)を指定する行が書かれていると、そのどのデバイスIDにでもこのINFファイルはマッチします。INFファイルに一致するVID/PIDがあるので、このデバイスドライバーにマッチするはずなんですが。

デバイスのインストールログをチェックしてみてください。
C:\WINDOWS\setupapi.log

これはテキストファイルなので適当なエディタで中身を見ることができます。
ただ、これまでの累積が長々と書かれているので、このデバイスに対するログを分離するのは大変です。
そこで、
1) デバイスをはずした状態で、setupapi.logを適当な名前に変更します。setupapi.oldとか。
2) デバイスを挿してインストールを通常どおり行います。(エラーになってもかまいません。)
エラーになったら、キャンセルして終了してしまいます。
新たなsetupapi.logが出来ているはずです。この内容は今回のセットアップだけに限定されています。

こうやって限定しても、訳の分からないエラーメッセージが何度も繰り返されていることと思います。
中身を見てみたいので、どこかにポストしていただけますか?

Tsuneo
by Tsuneo (2008-03-26 17:12) 

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

この記事のトラックバックURL:
※言及リンクのないトラックバックは受信されません。