Sim's blog

電子工作はじめてみました

スイッチサイエンスさんもGainer mini

2009-01-20 23:11:27 | その他のマイコン
スイッチサイエンスさんもGainer miniの取扱いをはじめました。1月中は3980円と安く販売されるそうです。


Gainer miniクローンの方は、おぐらむさんに色々教えてもらいながらぼちぼち進めています。
なぜかUSBパケットキャプチャをすると、今まで動作しなかったUSBハブ経由でも動作します。たぶんタイミングにセンシティブな動作にパケットキャプチャのディレイがはいったせいで動作するようになった雰囲気です。場所はrxtxSerial.dllの中身じゃないかと思います。
使ってみたUSBパケットのキャプチャソフトはUSB Sniffer for Windows(ファイル名はSnoopyPro.exe)というものです。

なんか全然Gainerっぽいことしてない気がします。

最新の画像もっと見る

57 コメント

コメント日が  古い順  |   新しい順
Unknown (おぐらむ)
2009-01-21 21:27:41
こんにちは
私も追試しました。
十数回buttonとLEDを交互に実行してみたりしてみましたが、確かに安定して接続できます。
だいぶ犯人が絞れましたね。
返信する
Unknown (Sim)
2009-01-22 11:25:14
こんにちは、おぐらむさん
追試ありがとうございます。私もGainerフォーラムに動作レポートを出しておきました。
返信する
Unknown (Tsuneo)
2009-01-22 17:12:13
通りすがりのUSBマニアです。:-)

> なぜかUSBパケットキャプチャをすると、今まで動作しなかったUSBハブ経由でも動作します。

これはPICの話ですか?
Gainerには手を出して無いので、ちゃんと話題を追えて無くてすいません。

フルスピード・デバイスにUSBハブをかませると動作しなくなる、というのは、多くの場合
a) Windows XP SP2 のバグ
b) デバイス・ファームウェアのタイミングのバグ
というのが相場です。

a) は、XP SP3 にアップデートすればOKです。
b) は、ハブがフルスピードのコントロール転送のタイミングを加速するのに、ファームウェアの処理がついていけないと出現します。
Java RXTX を使っているということで、CDC-ACMを使ったバーチャルCOMポートの話のようですが、CDCだと、
SET_LINE_CODING ー ボーレートなどの設定
GET_LINE_CODING ー ボーレートなどの読み出し
SET_CONTROL_LINE_STATE ー RTS、DTRのon/off
SEND_BREAK ー breakのon/off
などのクラスリクエストをホストが続けざまに出すと、ファームウェアがコントロール転送の処理タイミングに失敗するということになります。

PICの場合、PIC18F、24F、32、とUSBデバイス・エンジンはほぼ共通ですが、どれもエンジン独自のエンドポイント・バッファを持っていないので、ファームウェアがコントロール転送をすばやく処理しないと上記のタイミングエラーが発生します。とくに、前のコントロール転送のステータス・ステージ(OUT)から、次のコントロール転送のSETUPステージまでのタイミングが問題になります。このタイミングは、ハブで加速され、ソフトウェア・パケットキャプチャで多少遅延されます。

> (3)USB増設PCカード経由
このカードにのっているのは、EHCI + OHCI ホストコントローラじゃないでしょうか。OHCIでもハブと同様にコントロール転送のタイミングが加速されます。

以上のことからおそらくファームウェアの問題だと思いますが、ハードウェア・バスアナライザで、SETUPトランザクションにデバイスがACKが返さないのを確認できれば、ファームウェアのタイミングエラーが確定です。

この対策は、ファームウェアにMicrochipのMCHPFSUSB v2.3フレームワークを使っているのなら、
1) エヌメレーションの後も、USBDeviceTasks()を頻繁に(100us以内の繰返し頻度で)呼ぶ。
あるいは、
2) デフォルト・エンドポイントをUSBインターラプトで処理する。
http://forum.microchip.com/tm.aspx?m=390042&mpage=2&#392892
といったところです。
1)だとユーザがProcessIO()に追加したコードにも大きな制約(100us以下に細分化しなければならない)がかかってしまうので、2)のインターラプトで処理するのが良いのではないでしょうか。

それにしても、Microchipはどうしてこんな原始的なUSBエンジンをいつまでも使っているんでしょうかね。Setupトランザクション用に8バイトのバッファをエンジン側にのせて、エンジンが自動的にSETUPにACKを返すようにするだけで、ファームウェアのタイミング制約が大いに緩和されるし(100us -> 50ms)、コントロール転送処理ルーチンもすっきりするんですが。セコハンのシリコンプロセスで作ったPIC18Fはいざしらず、PIC24F、32まで引きずるのは、Microchipはこのタイミング制約がどれほど大きな問題かを全く分かってないんでしょうね。他のMCUのフルスピードUSBエンジンは通常エンジン側にバッファを持っているので、これほどタイトなタイミング制約はありません。

Tsuneo
返信する
re:Unknown (Sim)
2009-01-22 22:13:52
こんにちは、Tsuneoさん。以前hamayanさんや、のりたんさんの所でお見かけしたことがあります。
>これはPICの話ですか?
はい。元々のGainerはPSoCなのですが、Gainer miniというPIC18F2550を使ったモジュールが最近発売になりました。
a)かb)という話ですと、XPはSP3なのでb)ということになります。
現在、USBハブ経由はtera termだと動作してrxtxSerialだと動作しないという状況です。rxtxSerialではSetCommStateという関数でエラーが出ているそうです。少なくともteratermでは動作しているのでrxtxSerialにパッチを当てることで動作可能にできないかと考えています(まだコンパイル環境すら整っていません><)。コメントされていることからすると、SetCommStateを短い間隔で何度も実行するとエラーになるのではないかと思いました。
ところでホストコントローラの種類はどうやって見分ければいいのでしょうか?windowsから調べる方法はありますか?
返信する
Unknown (おぐらむ)
2009-01-22 22:45:06
こんにちは
Tsuneoさん、勉強になりました。
GAINER miniのファームはUSBフレームワーク1.3を使っているよう(USB関連のディレクトリ構成から推測しましたが、どこで断定すればよいか自信がありません)ですが、ソースを眺めてみます。
あつかましいお願いですが、GAINER forumでも本現象が問題になってきておりますので、そこでもアドバイスをいただけると助かります。
私はPIC環境のみでしか動作確認できないのですが、SimさんはPepper、GingerというAVRベースのGAINER互換ボードをお持ちで、こちらでも類似症状が出ていること、また同PIC18F2550ボードで構成したUBW環境は問題なく動いていることから、PC側ソフトの問題ではないかと考えておりました。
しかしながら、Arduinoでもrxtxが使われており、PICで不具合のでる環境でも問題なく動くことが確認できましたので、混乱している状況です。
また発症するのがOHCI環境というのもそのとおりです。

Simさんへ
ホストコントローラの種別は、デバイスマネージャのUSB(Universal Serial Bus)コントローラからわかりますよ。
Open HCD USB Host ControllerがOHCI
Universal Host ControllerがUHCI
といった感じです。
返信する
Unknown (のりたん)
2009-01-23 09:26:30
Tsuneoさん、おひさしぶりです。

これは、以前、この記事で悩んでいた問題ですね。

http://noritan-micon.blog.so-net.ne.jp/2008-03-26
USBプロジェクト - ファームウェアに立ち返る (7)

MC908JB16も、SETUP専用のバッファを持っていません。そのため、SETUPトランザクションを取りこぼさないようにバッファのデータをさっさと引き取るように構成していました。(本人はすっかり忘れていて、BLOGが記憶していただけなんですけどね。)ロースピードで悩んだのだから、フルスピードだとさぞ大変でしょう。

それでも、MC908JB16は、SETUPに対するACKを自動的に返していました。
返信する
re:Unknown (Sim)
2009-01-24 00:29:33
こんにちは、おぐらむさん
フォローありがとうございます。Tsuneoさんが来てくれたら鬼に金棒です。

そういえばpepperも似た様な現象でした。USBハブ経由だとデバイスは認識するけど通信できませんでした。USB拡張PCカードは通信もokでした。

rxtxSerial.dllの再ビルドもしてみました。エラーが変わってしまいました。うーむ。

うちの外付けUSBハブはデバイスマネージャで見ても「汎用 USB ハブ」という名前しか見えないのです><。
返信する
re:Unknown (Sim)
2009-01-24 00:52:44
こんにちは、のりたんさん
のりたんさんのところはUSBカテゴリが38件もあるんですね。Tsuneoさんのコメントもいっぱいです。当時はUSBの仕様書まで読んでられたんですね。やっぱりUSBって難しいです><

返信する
Unknown (Tsuneo)
2009-01-24 11:18:47
Simさん、
> rxtxSerialではSetCommStateという関数でエラーが出ているそうです。
> SetCommStateを短い間隔で何度も実行するとエラーになるのではないかと思いました。
SetCommState() (Windows COM API)をusbser.sys に送ると、usbser.sysはUSB側に次のクラスリクエストを連続的に出力します。たった1回のSetCommState()に対して7個のクラスリクエストが出てきてしまいます。大変な無駄ですね。
1) GET_LINE_CODING
2) GET_LINE_CODING
3) SET_LINE_CODING
4) GET_LINE_CODING
5) SET_CONTROL_LINE_STATE
6) SET_LINE_CODING
7) GET_LINE_CODING

実際には、SetCommState()は複数のデバイスコントロール (IOCTL_SERIAL_GET_LINE_CONTROL, IOCTL_SERIAL_SET_LINE_CONTROLなど) をusbser.sysに送り、個々のデバイスコントロールがまた複数のクラスリクエストに対応しているので、USB側で見ると重複が出てきます。
というわけで、SetCommState()ひとつで、ファームウェアのタイミングエラーが起こる条件を充分満たしています。

> ところでホストコントローラの種類はどうやって見分ければいいのでしょうか?
a) デバイスマネージャ
おぐらむさんの説明を補足して、ホストコントローラをサポートしているデバイスドライバのファイル名で判別する方法を紹介します。

デバイスマネージャで
- USB(Universal serial Bus)コントローラを展開する
- ~~ Host Controller - xxxx といった項目がいくつか並ぶ
- 上記の項目をダブルクリックするとプロパティダイアログが出てくる
- このダイアログで「ドライバー」タブを選び、さらに「ドライバの詳細」ボタンを押す
- ドライバファイルの一覧が表示される
この一連のファイルの中に次のどれかがあるはず。
usbehci.sys - EHCI - ハイスピード
usbuhci.sys - UHCI - フルスピード・ロースピード
usbohci.sys - OHCI - フルスピード・ロースピード

b) HCList
USB-IFの常連回答者であるtombさんが作ったユーティリティをAxelsonさんがUSB Centralで公開しています。
USB Central
http://www.lvr.com/usb.htm
HCList
http://www.lvr.com/files/HCList.zip


おぐらむさん、
> SimさんはPepper、GingerというAVRベースのGAINER互換ボードをお持ちで、こちらでも類似症状が出ていること、また同PIC18F2550ボードで構成したUBW環境は問題なく動いていることから、PC側ソフトの問題ではないかと考えておりました。

なるほど、かなり面倒な状況のようです。原因がひとつではないのかもしれません。
秋月のPIC18F2550 モジュールは私も持っているので、GainerMiniのコードをのせて、PICで何が起きているのかバスアナライザで見てみようと思います。ファームウェアの問題だと確認がとれれば、GAINER forum に移動するかもしれません。

Tsuneo
返信する
Unknown (Tsuneo)
2009-01-24 11:25:07
のりたんさん、
お久しぶりです。
> ロースピードで悩んだのだから、フルスピードだとさぞ大変でしょう。
まさにその通りです。

> それでも、MC908JB16は、SETUPに対するACKを自動的に返していました。
PICも、ファームウェアがバッファのownerをSETUPが来る前にUSBエンジンに返しておけば、USBエンジンはSETUPに対するACKを自動的に返します。ファームウェアがバッファのownerを返上するタイミングが遅いと、エンジンはSETUPにACKを返しません。ホストはACKを見るまでSETUPを3回リトライしますが、すべて失敗するとホストはエラーが起こったと判定します。ハブやOHCIホストコントローラでは、このあたりのタイミングがUHCIホストコントローラよりも加速されます。


Simさん、
> やっぱりUSBって難しいです
いやいや、たまたま一番難しいところに当たってしまったという感じですね。
USBはきっちり仕様を決めるためにやたらと決まりごとが多いので、とっかかりでは難しい印象を持ってしまうのでしょう。またUSBはRS232に比べて一つ上のプロトコル層まで決めているので、よりスペックの範囲が広がっています。しかし、肝心な部分は最初に思ったほど多くは無いのです。


ところで、
GAINERminiのファームウェアをのぞいて、ハードウェア・インターラプトに簡単にできそうかどうか見てみました。
コントロール転送 ー クラスリクエストの処理は、USBDriverService() (\system\usbdrv\usbdrv.c)でやっていて、このサブルーチンはmain()のスーパーループで呼ばれています。そのままインターラプトに持ち込めそうです。MCHPFSUSB v2.3とほぼ同じですね。

ちょっと謎なのは、USBCtrlEPService() (usbctrltrf.c)に埋込まれた

byte USBCtrlEPService(void)
{
...
// Gainer code start
TIMER1_STOP;
TIMER3_STOP;
REBOOT_ON;
//Gainer code end

の部分で、何故このコードがここにあるのか意図が今ひとつ分かりません。
USBCtrlEPService()は、デフォルトエンドポイントへのトランザクションを受ける度に毎度呼ばれます。つまり、このコードはエヌメレーションが終わった後でも、クラスリクエストが来ると呼ばれてしまいます。それでいいんでしょうか。

このコードにこだわっているのは、デフォルトエンドポイントの処理をインターラプトに持って行ったときにこのコードもインターラプト側に入ってしまう点です。main()のスーパーループでやっているタスクと非同期にタイマーが止まったり、リブートフラグがあがったりするので、何かこのあたりで新たな問題が発生するやもしれません。

Tsuneo
返信する

コメントを投稿