usb

2011年10月 2日 (日)

stm32ループバック(HID)&BCB6アプリ

stm32ループバック(HID)&BCB6アプリ

急に思い立ち、STM32(CQ-STARM)をHIDにして
BCB6で制御しようと思いました。
とりあえず、ループバックするだけのもの。

はじめは素直にSTの
STM32_USB-FS-Device_Lib_V3.3.0
のCustom_HIDを使おうとしたのですが、
なぜか「STM3210B-EVAL」でビルドすると
PCから認識されなくなるので、あきらめました。

そこで、
ARMCortexM3のHP

PICでUSBを!(知識ゼロからのスタートです)
を参考に(ほぼコピペに近いですけど)
作りました。

STM32のfirmwareはデバッグ用にLED on/offを入れている程度。
以前と同様Ride7を利用してビルド(最新版ではないです)。

アプリのほうはBCB6だけでいけるようにするために、
(DDKなどをインストールしないでもやれるように)
http://www.intel.com/intelpress/usb/examples/ZipFiles/FromDDK.htm
のFromDDK.zipの.hファイルを利用し、
BCB6のimplibを使って
implib hid.lib hid.dll
implib setupapi.lib setupapi.dll
としてlibを作成して使ってます。

なんとかこれで動作するようになりました。
どちらも「HidAppTest.7z」に入れてます。
「HidAppTest.7z」をダウンロード

しかし、なぜ、STM32_USB-FS-Device_Lib_V3.3.0のものはビルドすると
HID以外のものでも認識しないのか…。
※わかりました。 Vector Table Relocationを0x3000ずらさないと
いけなかったのでした。

#define VECT_TAB_OFFSET  0x3000

としたらあっさり動きました…。

| | コメント (0) | トラックバック (0)

2010年7月13日 (火)

BCB6でWinUSB

uusbdもlibusbもbcb6で動かしたので
その延長でwinusbも動かそうとしたのですが
やっぱりbcb6はかなり古いものになってしまったので
対応できてない部分があるようでした。
(私が知らない設定もあるのかもしれません。)

かなり無理やりで信頼性がないですが
とりあえず下のようにすると動きました。
interface2010年2月号「第5章 WinUSBを使ったUSBターゲット機器の制御プログラミング」も参考。

---

・bcb用ライブラリを作り直す
implib winusb.lib winusb.dll
で。これはwinusbに限らずuusbd/LibUsbでも必要。

・bcb6そのままではsetupapi関連がうまく動作しないので、
update4を適用する。

・_tcscpy_s()はbcb6にはないので_tcsnccpy()にとりあえず置きかえ。
引数に注意。

・BCB6では宣言が無いためにエラーになるものがある。とりあえず

#define __in
#define __out
#define __out_bcount_part_opt(a,b)
#define __inout
#define __out_bcount(a)
#define __in_bcount(a)
#define __out_opt
#define __in_opt

として、消す。

・WinUsb_QueryPipe()で受け取ったEndpointの情報pipeInfoの
メンバーの値がおかしい。
なぜか
PipeId→pipeInfo.Interval,0→pipeInfo.PipeId,0→pipeInfo.MaximumPacketSize
のようになる。

winusb.dllを動的にロードするようにしてみても全く同じ。
とりあえずpipeInfo.IntervalをPipeIdとして扱うように修正すれば
とりあえずなんとかなるけど他のパラメータは使えないので注意。
私はConfiguration Descriptorを取り直してpipeInfoをつくる
関数を作って使うようにしてみた。

---
ちなみに、C++BUILDER 2010をインストールしてみて
ためしたら、上記のうち、ライブラリの作り直し以外のことは
不要で、普通にコンパイルでき、普通に動作しました。

| | コメント (3) | トラックバック (0)

2010年6月20日 (日)

stm32でさらにWinUSBも試す

LibUsbはuusbdと大して変わりなく、
すぐ使えるようになりました。
infもアプリケーションが付いているので
簡単に作成できました。

で、調子に乗ってWinUSBも試してみようかと。
まだとっかかりのところですが。

早速、はまったのが、stm32ではinterfaceが2つあるのですが
その場合2番目のinterfaceはどうやったら使えるのか
ということ。

サンプルとかでもinterface0にbulkのin/outとinterruptが
一つに入ってるものだったりして。

結局、

bResult = WinUsb_Initialize(hUsb, &hWinUsb);

のあとに、

bResult = WinUsb_GetAssociatedInterface(hWinUsb, 0, &hWinUsb1);

bResult = WinUsb_QueryInterfaceSettings(hWinUsb1, 0, &desc);

bResult = WinUsb_QueryPipe(hWinUsb1, 0, (UCHAR)i, &pipeInfo);

のようにするのでした。
WinUsb_Query~()の真ん中の引数にいれる数字を変えていくのかと
勘違いしてました。

でも複数デバイスで同じホスト側アプリをつかうようにしたい場合、
やりづらい気が。

| | コメント (0) | トラックバック (0)

2010年6月16日 (水)

stm32の動作

ループバックするようにしたもので
手作りダブルバッファが不要?な感じがあったので
stm32でuusbdをためしてみたら」に書いたあと、
わかってないのにがた老さんにも問い合わせたりして
ご迷惑をおかけしてます。
(結局PCから送ってきたときだけ送るから問題がないだけ
だったようです。)

stm32でuusbdをためしてみたら」を書いた後に
うまくいかないPCがでてきたので調べていて、そのときは
がた老さんのプログラムでもうまくいかず(添付してあったHEXを使っても)、
結局64byteをIN転送しようとするととたんにおかしくなることが
わかりました。63byteまでは大丈夫なのですが。

もう少し調べてみると、
問題がある場合はUSB HUBにstm32をさしており、
そこにキーボード/マウス、232c変換、USBドングルなども
さしていました。ひとつ抜いてみるとあっさりうまくいくようになりました。
逆にうまくいってるときにさしてみると即うまくいかなくなります。
(こっちのほうがすぐ気づきそうなのに、いつもそうしてると
気づかないものですね。)

じっくり調べていかないといけませんが、
今のところそれだけわかってれば問題なく先にいけるので
今度はLibUsbあたりを試してみたいと思います。

| | コメント (0) | トラックバック (0)

2010年6月12日 (土)

stm32でuusbdをためしてみたら

がた老さんの手作りダブルバッファ+空振り作戦により
stm32もループバックをさせることができるようになりました。
そこで78kでもやったようにi2c制御をくっつけてみたら
あっさり動きました。
i2cは、78kでのノウハウ(とまではいえないか)
に加え、ねむいさんが公開してたもの
http://nemuisan.blog.bai.ne.jp/?eid=157305
があったので
参考にさせてもらった(いや、ほとんどパクッた)のが
大きかったです。

で、次の段階として78kでやったように仮想comからuusbdに移行して
処理高速化を図ろうとしました。

78kのときはPCアプリケーションでは決めうちのインタフェース番号、
エンドポイント番号にでつなげましたが、共通化のため
bulkのエンドポイントが2つそろって入っているインタフェースを
見つけるロジックをなんとかつくりました。
これも意外とすんなりいきました。

しかし問題発生。
データ転送でぶっとんでしまいます。
stm32側は何も変えないので、バルク転送でデータをやり取りすることに
なりますが、データをstm32に送ったら直ちにレスポンスを待ちます。
このときレスポンスデータが0個だったらエラーという風にしてましたが
別にそれ以上の処理をしてなくて現象となってました。

※これ以下、勘違いして書いていることが多いので注意!!
0個、よく考えたらstm32では「空振り」させるようになってるから
あたりまえなのか。
でも78kの時は0個を送ってくることはなく、いっぺんにほしいだけ
(2、30バイトくらいですけど)とれていたので
そういうつくりにしてました。

そう考えると、「空振り」を回避したくなりました。
で、データがないのにPC側からINの要求が来たら、
データを渡すんじゃなくてなにかあるのでは?
と、ネットで検索。
そういう時はNAKを出すと。
ということは、いまの状態はACKを出してたのかな、
と思いました。

そこで送信しないときNAKの状態にして
やる方法がないか、ソースを検索してたら

    SetEPTxStatus(ENDP1, EP_TX_NAK);

とすればできそうなことがわかりました。
※これは入れても入れなくても何も変わらないとわかりました。

早速、STM32_USB-FS-Device_Lib_V3.1.1を
ループバックに修正してmainループにはいる直前と
mainでデータ受信を検出した直後に上記を入れ、
送信データの設定をした後に

    SetEPTxValid(ENDP1);

を入れてみるとあっさり通信がうまくいきました。
※すみません。これは必ず入れないといけないもので
勘違いでかいてました。(なにもわかってなかったともいえますけど。)

0個のデータでなくほしい個数のデータが
くるようになりました。
仮想comでも大丈夫です。

さらにどうせなら受信完了直後にNAKの状態
にしたいと、EP1_IN_Callback()の中においてみたら
これも問題なし。
「ride7stm32vcp_loopback2.zip」をダウンロード
※あとで確認しました。
メインループに入る前とEP1_IN_Callback()に入ったときの
状態は確認時いつもnak状態でした。
つまり不要です。

私はSTM32_USB-FS-Device_Lib_V3.1.1では
USB通信が全くうまくいかなかったので
がた老さんの手作りダブルバッファ+空振りを
使わせてもらってました。
もしかするとがた老さんのプログラムでも
nak状態に入れるよう修正すれば
手作りダブルバッファ+空振りがいらなくなるのか?
と、ちょっとやってみました。
「stmvcpd_kai.zip」をダウンロード

一見うまくいってるような…。
※オリジナルでの時間計測では表示上2Mbps出てますが、
私の修正版では
USB_PutLine()ごとに転送してるから350kbps程度です。
効率よく64byteずつ転送すると逆に4Mbps程度となります。
「stmvcpd_kai_main2.zip」をダウンロード →main.cを入れ替えると
時間計測の部分だけ64byteずつになります。
「stmvcpd_kai_main2hex.zip」をダウンロード→そのhex/dfu です。
…さらに訂正。うまくいかなくなる状況がありました。USB HUBを
使ったときで他にもデバイスをいくつかさしていたときです。
他のデバイスを抜いたりしたらうまくいきます。

少なくとも私がやってるような、
データをもらったらそれにあわせてレスポンスを出す、
くらいな処理ならこれでいいのかも。
※きたときだけ送る方式なので大丈夫だったようです。
またUSB HUBにさしていた場合、他にさしている
デバイスの影響で、64byteごとで全く問題ない場合と
そうでない場合がありました。他のデバイスを抜いたり、
直接PCにさして試すほうがよさそうです。

| | トラックバック (0)

2010年6月10日 (木)

stm32ループバック

がた老さんの
ダブルバッファーでUSB仮想UARTの内部速度が2Mbps
のstm32→pcの送信部分を使わせていただき、
CQSTARM用の仮想comポートのループバックプログラムを作りました。
「ride7stm32vcploopback.zip」をダウンロード

STM32_USB-FS-Device_Lib_V3.1.1(um0424.zip)の
Virtual_COM_Portをベースにしてます。
単なるループバックなのでSTM32に送ったものが
そのまま返ってくるだけになってます。

| | コメント (0) | トラックバック (0)

2010年6月 4日 (金)

stm32もつかってみる

78kもそこそこ動かせるようになりましたが、自分の持ち物じゃないので
買うかどうか迷ってました。

で、DWMにstm32がついていたのを買って
ほとんど使わずにしまっていたのに気づきました。

さらにその当時より簡単に安定した開発環境が構築できる
とわかったので、早速やってみました。
Ride7というのを使ってます。
やり方はほとんどパクリですがSTM32開発環境
書いてます。

で、まずはvirtual comをモディファイしてみましたが
反応なし。
調べていくと、がた老さんの
STM32のUSB仮想UARTモニター遂に完成
virtual comがうまくいかない話しがありました。

しかし、その後の記事
ダブルバッファーでUSB仮想UARTの内部速度が2Mbps
でファイルがダウンロードできるようになっており、
それをなんとかRideでbuildできるようにしたら
あっさり動作しました。
とはいえ、ベースが古いバージョンだったので
新しいものにしたい欲が出てきて。

まだ先は長いなあ。

| | コメント (0) | トラックバック (0)

2010年5月24日 (月)

78kでI2C

FT2232DでI2Cをやるよりも
78kでI2Cをやるようにしたほうが早くなりそうな
気がしてきたので、考えてみました。

既にルネサス製の仮想comドライバを使う手については
実現させていました(I2CのH/WがなかったんでI/Oポートで実現)。
どこかに仮想comは遅いという書き込みもあったので、
HIDにするとか簡単に別のドライバにできるといいなと
思い調べていたらuusbdの記事を発見。
そういえば昔Interfaceに記事があったなと見つけ出してきて
見てみると、マウスのドライバをuusbdにする方法が載ってました。

uusbdのインストール用infファイルにデバイスのデバイスのVID,PIDを
書き込み、ドライバの更新をしてやるだけ。
この方法でいけるならF/Wの変更なしにホスト側を変更するだけで
いけます。

さっそくやってみると簡単にドライバは置き換わりました。
あとはホストの変更ですが、uusbdにあったサンプル(pipedump)をみて
openやclose、checkのやり方をまねし、あとはWriteFile()でコマンド転送、
ReadFile()でレスポンス受信というだけのものを作りました。
※WriteFile()/ReadFile()をやるためにそれぞれにOpenPipe、終わったら
CloseHandleも必要でした。

この方法に置き換えると、仮想comで500ms程度かかっていたのが
30数msec程度になりました。驚きました。
本当に仮想comっておそかったんだ。
(とはいえI2C処理中のUSB転送中にはbulk転送しかなく
シンプルだったので、
通信以外の処理に時間がかかってるのかな。)
まあ、もしかすると何か足らない処理もあるのかもしれないけど、
かなり高速化できることだけはわかりました。

| | コメント (0) | トラックバック (0)

2010年5月20日 (木)

FT2232DでI2C(その2)

FT2232をFTCI2C.dllで使ってみました。

I2CのEEPROMから16byteリードするところを
デジタルオシロでI2Cの波形を見てみたら、
なんだか8bit転送?する間隔(先頭から次の先頭まで)が
1ms以上ありました。

USB to I2C IntefaceにあるDelphiサンプルについていた
eeprom読み出しのexeファイルでも、

FTCI2C.dllを使っておらず直接ftd2xx.dllを使っているためか
若干間隔が短いですが、それでもそれなりの間隔がありました。
(こちらは1byteずつアドレス指定して読み出してますけど。)

I2C用のdllまであるということで期待してましたが、
だからといってI2Cの1リードパケット分実行したら
それをUSB経由で返す、というわけじゃなさそうです。多分。
1byteリードしたらそのままそれをUSBで返してるのかも。
※SnoopyProで見たら、ホストからコマンドがきたときに
1byteずつ返している様子がわかりました。
確かにi2cで100kHzでデータ転送してるけど
転送部分だけ100kHzでもなあ。

これだったら78kとかでプログラム組んだ方が
波形も追いやすいし、もう少し早くできるかも。
トラ技付録78kにルネサスの仮想comポートのサンプルを
修正してためしてみていたのでそんな気がしてきました。

あまり手をかけたくないのですが、
やっぱりF/Wを作成するほうが柔軟にできそうです。
もう一回78kのほうをいじってみようかな。

| | コメント (0) | トラックバック (0)

2010年5月19日 (水)

FT2232DでI2C

I2Cの制御ができるUSBデバイスで、手ごろな値段のものが
秋月で売ってあるというので、ためしに買ってみました。
「FT2232D USB-シリアル2ch変換モジュール」というやつです。
I2CやJTAGのような機能を使う場合は、EEPROMも必要とのことで、
一緒に購入。でも、DIPだったので「AE-FT2232ボードにEEPROMを実装する
をまねてつなぎました、意外と大変。

FT2232DにはFTCI2C.dllというI2C制御用のdllが用意されています。
FTDIでダウンロードできます。また、EEPROMに設定を保存するツールや
PCのドライバなどもFTDIからダウンロードできます。

で、このdllを使えば簡単にI2Cが使えると思ってたら
なぜかとっかかりのI2C_GetNumDevices()で検出できません。
もちろんI2C_Open()もできません。
でも、USB to I2C IntefaceにあるDelphiサンプルについていたeeprom読み出しの
exeファイルではあっさり動きます。


で、FTCI2Cのソースをチェックしていたらわかりました。
FT2232DのEEPROMのUSB String Descriptersに
「USB <-> I2C and UART」と書いていたのですが、
ソースではdevice descripterを読み出して、「 A」があれば
それも含めてそれ以降が2文字であればI2Cが使えるデバイスという
判断になってました。私の場合、途中に「 a」があり大文字に変換されていたようで
これが原因でデバイスなしとなってました。
結局、「USB<->I2C/UART」のように変更したら
FTCI2Cで動かせるようになりました。

多分、descripterの一番後ろ2文字が「 A」だったらという判断に
したかったのでは。

で、I2Cを動作させてみましたが、思ったよりかなり遅くて驚きました。
うーん。まだなんかあるのかな。
※FT2232Dの抜き差しで少し早くなりました、何だったのかな。

| | コメント (0) | トラックバック (0)