УοRのWDM 開発日記

УοRのWDM開発日記


WDMでUSBドライバを開発する羽目になってしまいました。
そこで、メモ代わりにこのページを作ります。
もし、私と同様な羽目に陥った方がいらっしゃいましたら、
一緒に勉強していきましょう。

2002/01/18(Fri)

また間が開きまして、その間に年を越してしまいました。
とりあえず今まで判明したML66525関係の事を書きます。
二つありまして、片方はML66525チップを使う上での注意点、
もう一つはML66525用のエミュレーターを使う上での注意点です。

ML66525は、基本的にML60852というUSBコントローラーと
FLASH ATAコントローラーをMPUコアと一緒に乗せたものです。
そのため、それらのチップを制御するためのレジスタが儲けられています。
USBコントローラーにはそれ自身のソフトウェアリセット機能がありますが、
それとは別に、MPUからUSBCにハード的にリセット信号を出せるようになっています。
ところがそれがマニュアルでは別の場所に書いてあって、参照の文言がないので
しばらくの間気がつきませんでした。
USBCのリセットはP5IOというレジスタに有ります。
もし、USBCが反応しないと言うときには、そのレジスタの説明を読んでください。
bit0がUSBCのリセット信号になっていて、0(デフォルト)でリセットです。
ここを1にしないとUSBCは反応しません。

私が今回使っているエミュレーターはASHLING社のUltra-66Kというものです。
これにPOD66525という沖電気のエミュレータボードを取り付けています。
このボードには、ML66525に乗っているチップが実装されていて、
実機と「ほぼ」同様に動作できるようになっています。
このボードのマニュアルにも載っていますが、いくつかの機能が実機とは違います。
その違いの一つがUSBCのクロックの供給なのですが、
ボード上にはML60528AというUSBCがまんま乗っかっていまして、
それに48MHzのクロックが供給されています。
このチップには、内部でクロックをPLLで逓倍する機能がありまして
クロックとして12MHzや6MHzも供給できるようになっています。
そして、ML66525ではこのチップには内部で逓倍したクロックが供給されます。
逓倍の制御はSYSCONと言うレジスタでやるのですが、ML66525ではこのPLLは
動作するようにしなければなりません。
しかし、このボードでは最初から48MHzが入っているのでPLLは使わない設定にしなくてはならないのです。
この事はマニュアルには載ってないので注意してください。


2001/10/23(Tue)

更に間が開きました。と言うか、前メモってからアップしてないし。
実は、今度また別にUSBの仕事が入りました。
今度のターゲットはML66525という石
沖電気製で、USBインターフェイスを内蔵したワンチップマイコンです。
USBインターフェイスは沖電気製USBインターフェイスのML60852によく似た設計です。
これを内部DMAで接続してあるので、高速にデータのやりとりができます。
プレスリリースによりますと、もう一つ内蔵しているNANDフラッシュインターフェイスを使って、
USBから8Mbpsでフラッシュに書き込むことができるそうです。
フラッシュのインターフェイスは、基本的にATA互換でスマートメディアにも対応しています。
まあ、今回の仕事にはそっちは関係ないのですが。

もう一つ面白いのは、この石のUSBインターフェイスのFIFOが二面で構成されていることです。
そのために高速で処理できる、はずです。
また、DMA転送もできるので、CPUから見るとデータは直接メモリと転送されるような形になります。
そして、制御転送時にはセットアップステージのデータが、特殊レジスタに書き込まれる形になっていて、
セットアップステージを気にする必要がありません。
かなり面白い石です。

ただし、CPUコアがnX-8/500Sという16bitコアで、その内容がややこしいことこの上ありません。
非常に大量のアドレッシング、レジスタの種類、そしてi8086を思わせるセグメント・・・
ついでにROM空間とRAM空間が分かれているのにハーバートアーキテクチャではありません。
バスは同じで、ROM専用の読み出し信号が存在する形です。
このROMは、要するにプログラム専用メモリという扱いで、
どちらかというとメモリマップドでROMが配置され、RAMがI/Oマッピングされた形と言えるでしょうか。
このため、プログラムに書かれた定数はイミディエイトでしか取り扱えません。
このあたりはPICによく似ています。
これを回避するために、RAM空間にROMウィンドウを儲けるというオプションがあります。
また、セグメントはi8086のようなクロスレンジではなく、バンク切り替えのような使い方になっています。
そのために、バンク間の通信用に共通エリアが用意されています。
また、命令が2系統有り、片方は直交性の為に用意された拡張命令のようです。
とにかくややこしい。アセンブラで組むのは非常に困難です。

まあ、Cコンパイラも用意されているので、それを使うのがベストでしょう。と言うかアセンブラを使う気がなくなりました。
けど、Cもメモリモデルがまるで86系のようにスモールだのコンパクトだのラージだの・・・・・(;-;)

今回の仕事には、実は音の再生を行う部分が含まれています。
ここでアイソクロナス転送を行うかどうか今迷っていますが、基本的に使わない予定です。
理由としては、転送するデータにノイズ耐性の悪いエンコーディングが使われているのが主です。
ですので、多分バルク転送でやると思います。


2001/09/20(Thu)

凄く間が空きました。その間にずーっとUSBのfirmwareに填ってました。
で、今日、とりあえずWindowsがデバイスを認識するところまで来たので、
その間にわかったことをいくつか綴ります。

デスクリプタは、デバイス、コンフィギュレーション、インターフェイス、エンドポイント
などの種類がありますが、これらは決してホストとのやりとりの単位ではないと言うこと。
デバイスデスクリプタと、ストリングデスクリプタは単独でやりとりされますが、
コンフィギュレーション、インターフェイス、エンドポイントはひとまとめでやりとりされます。
つまり、インターフェイスやエンドポイント単位では、デスクリプタのやりとりは行われません。

制御転送は意外とややこしいです。
また、USBN930Xでは、セットアップステージにはいるためには
RX_ENを立てる必要はありません。
RX_ENは、データステージのやりとりと、
ステータスステージでのハンドシェイクに使われます。
データステージでデバイスからデータを送る時には、
ステータスステージでは、ホストが0長パケットを送ってきますので、
送信に成功したことを示すためにRX_ENを立てます。
失敗の時はSTALLに、ビジーの時にはNAK、つまりRX_ENを立てないことで意思表示をします。
また、データステージでデバイスがデータを受け取るときに、
ステータスステージでは、デバイスは成功の返答として0長パケットを送ります。
つまり、何も書かずにTX_ENを立てます。
ビジーならば何も送らず、つまりNAKが帰ります。失敗の時にはSTALLを返します。
どちらの場合も、間に合わないときには何もしないで良いわけです。
失敗の時にはSTALLを、処理が終わったらその場合によってTX_ENかRX_ENを立てることになります。

デバイスがUSBに認識されるときには、一度デバイスデスクリプタを要求されます。
これは、デフォルトパイプ(エンドポイント0)のバッファ長を調べるためで、
多くの場合、このやりとりはわざと失敗されます。
そのために、失敗しても大丈夫なように対処する必要があります。
今回は、デバイスからの送信中に受信要請に対するNAKが帰ってきました。
それに対して、バッファをフラッシュしてRX_ENを立てる必要がありました。
これは、ホストが強制的にステータスステージに移ったためと思われます。

制御転送では、PIDのトグルは送信終了時に次のデータが必要なときのみ必要です。
それ以外は、必ずDATA1から始まると決め打ってかまいません。

データのエンディアンには泣かされました。本にはほとんど述べられてません。
結局はリトルエンディアン(先にやりとりされるデータが下位)でした。
ネットワークバイトとは逆になります。Intel系ではデータを入れ替える必要はありません。


2001/06/27(Wed)

あ。明日とか言いつつ一日空いているし。
で、具体的に何をやったのかというと、
VC++5で、「ツール」「オプション」の
ディレクトリで、表示するディレクトリの
インクルードファイルに、(98DDKのるーと)\inc\win98を先頭に登録して、
表示するディレクトリのライブラリファイルに
インクルードファイルに、(98DDKのるーと)\lib\i386\freeを先頭に登録したのです。
それでコンパイルできるようになりました。
なんのこっちゃ


2001/06/25(Mon)

結構長い間が空いてしまった。
ずーっと他の仕事の割り込みがあったのもあるけれど、
実は一カ所で止まりっぱなしだったのだ。
やろうとしていたのはInterfase 2000年3月号
汎用USBドライバをコンパイルしてみようと言うこと。
しかし、様々な困難が待ち受けていた。

とにかくいろいろな意味でコンパイルができない。
そもそも、普通のやり方ではできない。
Makefileプロジェクトを使う必要があるし、
環境変数をいろいろ整備してやらないといけないし。
で、そこまでやってもなぜかデバッグ版が作れない。
理由を調べてみたら、DDKのその場所にlibが存在しない。
てわけで、細かいことはまた明日書きます。


2001/06/15(Fri)

今日はとりあえず最初の方針を決めた。
とりあえず、インターフェイス誌2000年3月号の記事にある
汎用USBドライバを利用してみることにする。
それと、ハードはUSBN9603を使ってみることにする。
最初はプロトコルの検証から。

USBデバイスの変更があったときには、WM_DEVICECHANGEメッセージが呼ばれる。
VxDでのCONFIG_SETUPメッセージとかと似たようなものだろう。


2001/06/14(Thu)

今日は基本的なハードウェアの仕様について話し合った。
具体的な仕様については守秘義務などもあるだろうから秘密だけど、
基本的に、オリジナルのハードウェアを駆動すると言うことになる。
で、いまだにUSBコントローラーの選定も決まっていない。
いくつかの候補はあるのだけど、まあ、決め手は値段と言うことになりそう。
ハード側のファームも私の担当なのだが。
ハード側では、何らかのプロセッサを使い、そのさきにプログラマブルロジックを
繋げて、またその先に電気的なインターフェイスをつなげて、
最終的なターゲットを操作するという構成になる。
ターゲットは比較的遅い動作で良いので、ファームにある程度の
操作をさせてもかまわない。
ただ、ターゲットに種類があるので、ファーム用のMPUが非力すぎても困る。
今考えられているMPUは、80186相当のものか、8051相当の物か、
PIC、AVRなどが候補になっている。
186ならばAMDのUSBインターフェイス(LSI内部に186相当のコアが入っている)
その他、TIやCypressなどのUSBインターフェイスには8051系列のが入っている。
NSのLSIにPICや、他にもV25などと言う組み合わせなどが候補にあげられている。
私は、長年86系アーキテクチャで仕事をしてきたので、
186やV25などは使いやすい。アセンブラも結構遊んだので問題はない。
8051も、その発展系のCPUの仕事をしたことがあるので、そんなに困難ではない。
PICなども、そのうちやってみたいので、まあ良い勉強になるだろうかと。

と言うわけで、まだ先は闇の中・・・

昨日の続き
エンドポイントのうち、番号0というのは特殊な機能を持っている。
このエンドポイントだけが双方向で、しかも必須。
他のエンドポイントは単方向になっている。
エンドポイントの使い方は、ターゲットによって決められるので、
ホストへはGET_DESCRIPTORリクエストでその情報を与える。
転送モードは4つ。
コントロール転送は先ほどのエンドポイント0を使う。
インタラプト転送は周期が決まった転送。
バルク転送はフレームの空きをみんな使ってしまう転送
アイソクロナス転送は1mSに最大1023バイトをコンスタントに送る転送。
フレームの先頭にはStart Of Frame(SOF)というパケットが出される。
アイソクロナスの時にはこのフレーム毎に伝送が行われる。
インタラプトの時には、一定フレーム毎に伝送が行われる。
データの一回のやりとり(リクエスト、データ転送、アクノレッジ)の組をトランザクションという。
バルク転送やコントロール転送用のトランザクションにフレームのうち10%が予約されている。

2001/06/13(Wed)

Interface 2001年1月号が手元にある。
他の仕事が入って全然進んでない。

いろいろと読みながら気がついたところを少しずつ書いてみる。
元々ここはメモ代わりですしね☆

USBは必ずホスト側から通信を始める
パケットでやりとりをする。
パケットのやりとりのことをトランザクションという
トランザクションは1mS単位でスケジュールされている。この1mSをフレームと呼ぶ
パケットの中のデータに、パケットの種類が書かれている。
パケット一個分のデータ長を持つ、エンドポイントというものが存在する。


2001/06/09(Sut)

Interface 2000年3月号が手元にある。
今日のところはそれだけ・・・他のことばっかりやってたから。


2001/06/07(Thu)

とりあえず、Win32環境ではアプリケーション側からはCreatFileを使って
アクセスするようになっている。これはWin16環境と違う点であって、
Win32ではどんなドライバでも共通だ。
このときデバイス名には"\\.\hoge"と言う名前を指定する。
んでもって、ReadFile、WriteFile、DeviceIoControlなどの関数でアクセスする。
ファイルアクセスと何ら変わらない。
非同期I/Oリクエストというものもあるらしい。これはややこしいのか本の後の
ほうで解説されるそうだ。
なんたらExと言う関数だろう。
まあ、Win32のHelp見てもなんやらややこしいことを書いているし、
これは後にしよう。使えるときに使えば良いや。

なにやらドライバは複数のアクセスに耐えねばならんらしい。
マルチスレッドだのマルチプロセッサだのどこぞのメイドロボットのような名前の(違
環境に耐えるために、リエントラントに作らねばならんのだそうだ。
つーて、こっちがスレッドセーフの環境だと思って作ったドライバが、
なぜかOSが勝手にスレッドの最中にスレッドを割り込ませるようなことをする
(Win9*でタイマーを使ったりしたとき)ので大変な目にあったことがある。
まあ、気をつけるに越したことはないが、こういうややこしいことを
一般のドライバ作者に要求するからOSが不安定になるのだ。
いや、ドライバを作るような人はそのくらいのスキルがあることが前提だけどさ。

ふむ。ReadFileもWriteFileも使わなくて良いのか。
そういや、VxDの時はもっぱらDeviceIoControlばっかりだった気もする。

基本的にWinのデバイスドライバでは他のアプリケーションと同様に
ディスパッチルーチンが存在して、メッセージドリブンになるようだ。
これはVxDも同じ。違いはVxDがアセンブラベースなのに対して
WDMはCベースだと言うこと。まぁVxDでもラッパー作っちゃえば同じなんだけど。
WDMではIRP(I/Oリクエストパケット)を使ってデータをやりとりすることになる。


2001/06/06(Wed)

前回から間があいたが、ただ単に間に仕事が入っただけで他意はない。
と言ったが・・・今日も大したことはしていない。
「WDMデバイスドライバ」を少し読んだだけで。
そう言っている間にこんなところを見つける。
後で買ってもらおう。
こんなメモも見つける。Windows98でのWDMの動作にはふれてないが・・・

とりあえずWDMはVxDとかなり密接に関わっている。
この本なども読みつつ進んでいこう。


2001/06/01(Sut)

手元には「WDMデバイスドライバ」なる本がある。
しかし、635ページもあるでかい本で、読むのが憂鬱になる。
とりあえず、Googleで「USB WDM」を検索してみる。
一応私は、VxDの開発経験があり、またファームでCPUを直接弄るような
仕事をやったこともある。だから、ソフトの下回りはかなりわかっているつもりなのだ。
かといって、こんな本をいきなり読んでも飽きるだけである。
まずはネットサーフでもしてみて、楽な道を探そう。

で、こんなところを見つけた。
まあ、技術的な正確さはともかく、図もあり、簡易に書かれているので
全体像を頭に入れるのには役立ちそうだ。
ふむふむ。NTではドライバはユーザーモードとカーネルモードにまたがるように
作られていたのか。それをパフォーマンスの向上のためにカーネルモードに
どんどん追いやっていく様子が分かる。
しかし安定性は・・・まあ、ある程度トレードオフだもんね。
って開発者の僕から言えば、責任が重大になるって事・・・
それと、ようするにWDMってのはハードウェアとのインターフェイス部分と
OSとのインターフェイス部分の間だと言うこと。
・・・ってドライバってのはそう言うものだが。
まあ、そこを階層化したものだと言うことはわかった。
それと・・え、OSによって互換性がないの?こまるじゃん

それにしても、本の紹介がやたらと目に付く。
何奴も此奴も、ペーパーレス化に貢献しようとは思わんのか!!
つーか、なんでこう数千円もする本ばっかりなんだろう。

とりあえず使えそうな掲示板を。
デバドラ掲示板
パソコン電脳職人道

まあ、と言うわけでそろそろネットサーフはやめて、本でも読むか・・・あうう
それにしても英語の文書ばっかり・・・もしかしてみんな英語読めるの?


著作УοR
無断転載禁止
フリーリンク(無断リンク許可)