Top
HIDaspx
DownLoad
HIDasp高速化
制作
AVR関係
AVR_Monit
AVR_term
W32_term
HIDmon88
HIDtester
usbRS232
Arduino2313
デジタルテスター
ATmega88生活
KeyBoardマニア
KeyBoardマニアII
Arduino400
PICライター
ARMライター
赤外線リモコン
ARM
STM32ブートローダー
STM8S-Discovery改造
STM8S-OpenOCDライター
LPCXpresso
LPC用ブートローダー
NXP用LPCUSB
NXP用ブートローダー
MARY基板
LPC1114FN28
OpenOCD JTAGアダプター
OpenOCDビルド方法
arm-gccビルド方法
mapleIDEの改造
libmapleで仮想COM
PIC32
PIC32MX
Pinguinoで遊ぼう
ブートローダーを作る
シリアルブートローダー
USB仮想シリアル
USBカスタムデバイス
USB簡易モニター
USBオシロスコープ
USBホスト
PIC32でBluetooth
USBAudio
USBStudy
VGA出力に挑戦
BASICを動かす
WinUSB
勝手に改蔵*PIC32
PIC18F
HIDブートローダー
AVR/PIC両用ライター
ARMライター
usb汎用クラス
usbシリアル変換
usbキーボード変換
sdccを使いこなす
mcc18を使いこなす
HIDmon-2550
HIDmon-14K50
PICmonitor
試行錯誤の記録
UBWを試す
旧HIDboot
PIC18F2550試用記
PIC18F4550試用記
その他マイコン
NEC78K
RX62N
SH2A
H8
FM3
XPからubuntuに乗り換え
Android
Xen-hypervisor
Windows8カスタマイズ
開発日記
2015-04
ノウハウ
AVRUSB_Tips
HIDasp情報
汎用USB-IO
・
リンク
フリースペース
ゲストブック
旧コンテンツ
WinVista
インターフェース考
最新の20件
2022-07-25
2008-10
HIDasp高速化
H8/3048F
AutoTicketLinkName
2021-12-11
FormattingRules
2021-12-08
PukiWiki/1.4/Manual/Plugin/O-R
PukiWiki/1.4/Manual/Plugin/L-N
PukiWiki/1.4/Manual/Plugin/V-Z
PukiWiki/1.4/Manual/Plugin/A-D
PukiWiki/1.4/Manual/Plugin/E-G
PukiWiki/1.4/Manual/Plugin/S-U
PukiWiki/1.4/Manual/Plugin/H-K
2020-02-23
YukiWiki
PHP
PukiWiki
WikiWikiWeb
2018-12-19
SandBox
InterWiki
2015-05-07
2015-04
2015-05-02
MenuBar
編集
差分
HIDasp高速化 の編集
-- 雛形とするページ --
(no template pages)
From:[[2008-09]] From:[[HIDasp]] ''このページは、瓶詰堂さんのHIDaspで実装されているHID Reportの転送速度向上について考察したものです'' -時間軸が逆になっていて、上の情報のほうが新しいです。 -最新版アーカイブと、制作に関する説明は、[[HIDasp]]のページをご覧ください。 ---- *HIDasp速度比較 [#x38a5e09] -[[HIDasp速度比較]]のページをご覧ください。 #contents ---- *AVRUSB FLOW_CONTROLの追加 [#x7c77c66] AMDマザーで計測.(SiSではこれより遅いです.) |8kB | -d0 | read | 1.453 sec (5.637kB/s) | |8kB | -d0 | write & verify | 3.157 sec (2.594kB/s) | bash-3.2$ time ./hidspx.exe -ph -d0 8kB.hex Detected device is ATmega88. Erase Flash memory. Write Flash: 8192/8192 B Verify Flash: 8192/8192 B Passed. real 0m3.157s user 0m0.015s sys 0m0.015s bash-3.2$ time ./hidspx.exe -ph -d0 -rp >rom.hex Detected device is ATmega88. Read Flash: 8192/8192 B Passed. real 0m1.453s user 0m0.047s sys 0m0.000s ---- *HID Report送信の遅延評価 [#c2b871b8] -HID Reportのパケットを受け取った後、isp書き込み時間がどの程度許されるのかを評価してみた。 -[[ソースアーカイブ:hidmon-test-1007.zip:http://psp.dip.jp/web/upload.cgi/hidmon-test-1007.zip]] -結果 -bench2コマンドは第一引数が試行回数、第二引数が遅延係数(単位は10μ秒) -HIDパケットサイズは39バイト固定。送信(ホストからデバイス宛)のみ。 -Low Speed USBパケットを8バイト受け取る毎に待ちループを呼び出している。 X:UHCI(intel i815e)>hidmon -i script AVR> bench2 100 1 hid delay write start hid delay write end, 3900 bytes/801 ms, 4868 bytes/s AVR> bench2 100 2 hid delay write start hid delay write end, 3900 bytes/791 ms, 4930 bytes/s AVR> bench2 100 3 hid delay write start hid delay write end, 3900 bytes/801 ms, 4868 bytes/s AVR> bench2 100 4 hid delay write start hid delay write end, 3900 bytes/811 ms, 4808 bytes/s AVR> bench2 100 5 hid delay write start hid delay write end, 3900 bytes/801 ms, 4868 bytes/s AVR> bench2 100 6 hid delay write start hid delay write end, 3900 bytes/801 ms, 4868 bytes/s AVR> bench2 100 7 hid delay write start hid delay write end, 3900 bytes/801 ms, 4868 bytes/s AVR> bench2 100 8 hid delay write start hid delay write end, 3900 bytes/801 ms, 4868 bytes/s AVR> bench2 100 9 hid delay write start hid delay write end, 3900 bytes/791 ms, 4930 bytes/s AVR> bench2 100 10 hid delay write start hid delay write end, 3900 bytes/802 ms, 4862 bytes/s AVR> bench2 100 20 hid delay write start hid delay write end, 3900 bytes/801 ms, 4868 bytes/s AVR> bench2 100 30 hid delay write start hid delay write end, 3900 bytes/801 ms, 4868 bytes/s AVR> bench2 100 40 hid delay write start hid delay write end, 3900 bytes/801 ms, 4868 bytes/s AVR> bench2 100 50 hid delay write start hid delay write end, 3900 bytes/801 ms, 4868 bytes/s AVR> bench2 100 60 hid delay write start hid delay write end, 3900 bytes/801 ms, 4868 bytes/s AVR> bench2 100 70 hid delay write start hid delay write end, 3900 bytes/802 ms, 4862 bytes/s AVR> bench2 100 80 hid delay write start hid delay write end, 3900 bytes/801 ms, 4868 bytes/s AVR> bench2 100 90 hid delay write start hid delay write end, 3900 bytes/1302 ms, 2995 bytes/s AVR> bench2 100 110 hid delay write start hid delay write end, 3900 bytes/1302 ms, 2995 bytes/s AVR> bench2 100 120 hid delay write start hid delay write end, 3900 bytes/1301 ms, 2997 bytes/s AVR> bench2 100 130 hid delay write start hid delay write end, 3900 bytes/1301 ms, 2997 bytes/s AVR> bench2 100 140 hid delay write start hid delay write end, 3900 bytes/1302 ms, 2995 bytes/s AVR> bench2 100 150 hid delay write start hid delay write end, 3900 bytes/1292 ms, 3018 bytes/s AVR> bench2 100 160 hid delay write start hid delay write end, 3900 bytes/1402 ms, 2781 bytes/s AVR> bench2 100 170 hid delay write start hid delay write end, 3900 bytes/1803 ms, 2163 bytes/s AVR> bench2 100 180 hid delay write start hid delay write end, 3900 bytes/1792 ms, 2176 bytes/s AVR> bench2 100 190 hid delay write start hid delay write end, 3900 bytes/1803 ms, 2163 bytes/s AVR> q Bye. X:OHCI(SiS M671T)>hidmon -i script AVR> bench2 100 1 hid delay write start hid delay write end, 3900 bytes/203 ms, 19211 bytes/s AVR> bench2 100 2 hid delay write start hid delay write end, 3900 bytes/297 ms, 13131 bytes/s AVR> bench2 100 3 hid delay write start hid delay write end, 3900 bytes/296 ms, 13175 bytes/s AVR> bench2 100 4 hid delay write start hid delay write end, 3900 bytes/329 ms, 11854 bytes/s AVR> bench2 100 5 hid delay write start hid delay write end, 3900 bytes/391 ms, 9974 bytes/s AVR> bench2 100 6 hid delay write start hid delay write end, 3900 bytes/406 ms, 9605 bytes/s AVR> bench2 100 7 hid delay write start hid delay write end, 3900 bytes/453 ms, 8609 bytes/s AVR> bench2 100 8 hid delay write start hid delay write end, 3900 bytes/485 ms, 8041 bytes/s AVR> bench2 100 9 hid delay write start hid delay write end, 3900 bytes/500 ms, 7800 bytes/s AVR> bench2 100 10 hid delay write start hid delay write end, 3900 bytes/500 ms, 7800 bytes/s AVR> bench2 100 20 hid delay write start hid delay write end, 3900 bytes/797 ms, 4893 bytes/s AVR> bench2 100 30 hid delay write start hid delay write end, 3900 bytes/1188 ms, 3282 bytes/s AVR> bench2 100 40 hid delay write start hid delay write end, 3900 bytes/1563 ms, 2495 bytes/s AVR> bench2 100 50 hid delay write start hid delay write end, 3900 bytes/1828 ms, 2133 bytes/s AVR> bench2 100 60 hid delay write start hid delay write end, 3900 bytes/2203 ms, 1770 bytes/s AVR> bench2 100 70 hid delay write start hid delay write end, 3900 bytes/2515 ms, 1550 bytes/s AVR> bench2 100 80 hid delay write start hid delay write end, 3900 bytes/2844 ms, 1371 bytes/s AVR> bench2 100 90 hid delay write start hid delay write end, 3900 bytes/3203 ms, 1217 bytes/s AVR> bench2 100 110 hid delay write start hid delay write end, 3900 bytes/3875 ms, 1006 bytes/s AVR> bench2 100 120 hid delay write start hid delay write end, 3900 bytes/4172 ms, 934 bytes/s AVR> bench2 100 130 hid delay write start hid delay write end, 3900 bytes/4500 ms, 866 bytes/s AVR> bench2 100 140 hid delay write start hid delay write end, 3900 bytes/4796 ms, 813 bytes/s AVR> bench2 100 150 hid delay write start hid delay write end, 3900 bytes/5188 ms, 751 bytes/s AVR> bench2 100 160 hid delay write start hid delay write end, 3900 bytes/5562 ms, 701 bytes/s AVR> bench2 100 170 hid delay write start hid delay write end, 3900 bytes/5828 ms, 669 bytes/s AVR> bench2 100 180 hid delay write start hid delay write end, 3900 bytes/6188 ms, 630 bytes/s AVR> bench2 100 190 hid delay write start hid delay write end, 3900 bytes/6531 ms, 597 bytes/s AVR> q Bye. -結果、なんと''UHCIでは1パケット毎に直後800μ秒のISPコマンド処理時間があったとしても、コンスタントに4.8kB/秒の転送速度を保っている!'' -つまり、HIDでもインターリーブの効果はあるということだ。 -逆に、OHCIでは800μ秒のISPコマンド処理時間があった場合、1.3kB/秒にまで転送速度が落ちている。 -これは謎だ。 ちなみに '-d3'オプションを指定した場合のSCLKは375kHzなので、 -8ビットのSPIを送るのに必要な時間は21.33μ秒。 -8バイトのファームウェアをページバッファにセットアップする時間はその32倍の683μ秒あれば良い。 --(SPIコマンドは常に4バイト単位になっていて、1コマンドで正味データ1バイト分しか転送できない) ---- *ファームウェアの容量削減 [#kd61a76d] -senshuさんにより取り纏め頂いたhidspx-0928b.zipに対して、firmware容量の削減を 行いました。 -機能やコンフィギュレーションは同一です。 -[[ソースアーカイブ:hidspx-0928c.zip:http://psp.dip.jp/web/upload.cgi/hidspx-0928c.zip]] avr-objcopy -j .text -j .data -O ihex main.elf main.hex avr-size --mcu=attiny2313 main.elf text data bss dec hex filename 2014 4 88 2106 83a main.elf -1988バイトは気の迷いでした。(とあるコーディングミスで最適化され機能削除されていました。) -WinAVRのバージョンは2006-0421でビルドしていますので、最新のWinAVRではサイズが変わる(増える)かもしれません。 おまけソフト -[[HIDmon:hidmon-0929.zip:http://psp.dip.jp/web/upload.cgi/hidmon-0929.zip]] ---- *SCK、MOSIのHi−Z化改良 [#z551790c] -senshuさんにより取り纏め頂いたhidspx-0928.zipに対して、SCK、MOSIのHi−Z化を 行いました。 -ライターが書き込み動作を行っていないときはSCK、MOSIをHi−Zにします。 -[[ソースアーカイブ:hidspx-0928a.zip:http://psp.dip.jp/web/upload.cgi/hidspx-0928a.zip]] ---- *高速化改良その6 [#p7941a5a] - address_set , page_write , isp_command を全部含んだ融合コマンドを実装しました。 - tiny2313では、かなり有効かと思われます。 - それに伴って命令セット体系に少し変更が生じました。 - %%ソースは現在整理中です。乞うご期待。%% ''任務完了!'' -[[ソースアーカイブ:hidspx-0927a.zip:http://psp.dip.jp/web/upload.cgi/hidspx-0927a.zip]] おまけソフト -[[HIDmon:hidmon-0927a.zip:http://psp.dip.jp/web/upload.cgi/hidmon-0927a.zip]] 注意 -%%HIDmonを使用される場合は命令Fusionが使えませんので、%% --使えるようにしました。 #define INCLUDE_FUSION 0 #define INCLUDE_MONITOR_CMD 1 %%でファームを作成しなおしてください。%% -ポートの方向初期値を適切に設定してあげてください。 たぶん、ここらで打ち止めです。 -残りはHIDmonの若干の機能強化と、汎用USB I/O DLLもどきの作成。 ---- *高速化改良その5 [#cf9dee00] ''変更内容''(わりと堅実路線) - '-d<delay>' オプションのクロックをUSBaspに近づけるように努力しました。 -- 詳細は firmware/main.c にあります。 - hidasp.c を少しリライトしました。 -- デバッグ文が多くて見づらかったためです。 - メモリーを減らしました。 -- -d<delay> で思いのほかメモリー使用量が増えたので、ダイエットです。 - タイマー0によるUSIクロック生成は諦めました。 -- うまくいく方法が見つかったらこっそり教えてください。 -[[ソースアーカイブ:hidspx-src-0925.zip:http://psp.dip.jp/web/upload.cgi/hidspx-src-0925.zip]] ---- *高速化改良その4 [#pb2d0ff9] -紆余曲折の末、8バイト単位でのインターリーブ転送を実施することに決定しました。 -つまり、図で書くとこんな感じ 時間軸 0mS 1mS 2mS +--------------------------+-----------------------------+------------------ ... |USB転送| |USB転送| |USB転送| +--------------------------+-----------------------------+------------------ ... |<=ISP書き込み===>| |<=ISP書き込み======>| |<=ISP書き込み -目標では5kB/S(但しSCLK1MHz弱程度を想定) -SCLKはタイマー0で与える。 -タイマー0のプリスケーラと分周比のペアを専用のコマンドで与える。 -ディレイオプション -d<delay> からペア値への変換表はホストPC側が担当する。 さて、うまくいきますやら・・・ ''結論'' -駄目でした。(テストマシンはintel UHCI) |8kB | -d0 | read | 1.862 sec (4.4kB/s) | |8kB | -d0 | write & verify | 5.368 sec (1.5kB/s) | ちなみにfirmのサイズは2048きっかりでした。 -LED,MONITORの両方削除 -アンロール削除 -vendor,productIDを1字に。 -HID Reportディスクリプタは最小限の3個(6,38,70) そもそも5kB/Sは読みか書きのどちらかの速度です。 -転送ベンチが5kだったので、書き&ベリファイで5kも出るわけないです。 -あと、現在の実装は書き込みパケットにかなり無駄があります。(page_writeの前後の2パケットは内包可能) コードエリアが足りません。(これは深刻・・・) avr-size --mcu=attiny2313 main.elf text data bss dec hex filename 2034 4 59 2097 831 main.elf -100mSのディレイが残っていたので、差し引くと1.762 sec -書き込み時には無駄パケットが少し多いので、パケットをうまく統合するとreadの倍の3.6 sec 程度まで行くかもしれません。 -でも、どう頑張っても5Kの半分(2.5k/s)よりは出ないでしょう。 -だったら、今の最速(W&Vで2K弱)をキープして、コード保守するほうが堅実なのかもしれません。 実計測結果~ [[テストアーカイブ:hidspx-test-0925.zip:http://psp.dip.jp/web/upload.cgi/hidspx-test-0925.zip]] -マシン=Athlon64 USBホスト=VIAチップPCIカード(UHCI) -delayループ取り払い状態(1.5MHz SCLK) -ATmega88へ8192バイトのHEXを書き込み&ベリファイ bash-3.2$ time ./hidspx.exe -ph -d0 xx.hex Detected device is ATmega88. Erase Flash memory. Write Flash: 8192/8192 B Verify Flash: 8192/8192 B Passed. real 0m3.859s user 0m0.031s sys 0m0.015s -ATmega88から8192バイトのHEXを読み込み bash-3.2$ time ./hidspx.exe -ph -d0 -rp >a.hex Detected device is ATmega88. Read Flash: 8192/8192 B Passed. real 0m1.438s user 0m0.015s sys 0m0.000s bash-3.2$ -まとめ(テストマシンはAMD + UHCI) -delay()ループ完全取り払い(SCLK=1.5MHz) |8kB | -d0 | read | 1.438 sec (5.696kB/s) | |8kB | -d0 | write & verify | 3.859 sec (2.122kB/s) | -書き込みパケット数を減量(統合)すれば、write & verifyはもうすこし速くなりますので、2.5kB/sも夢ではないかもしれませんが、そのまえにコードサイズのスリム化が必要です。(どなたか挑戦しませんか、アーカイブは上記のhidspx-test-0925.zipです) とりあえず、いい夢を見させてくれました。ありがとう>USBasp ---- *AVRbench [#baa8c2ec] usbFunctionWrite()の性能テスト. -usbFunctionWrite()内に遅延関数の呼び出しを入れる。 -どのくらい遅延すると、ホスト側の速度に影響するかのテスト. -0060 番地が遅延係数で 1 増えるごとに100uS -使い方は win32/ で term -iscript [[テストアーカイブ:AVRbench.zip:http://psp.dip.jp/web/upload.cgi/AVRbench.zip]] ---- *高速化改良その3 [#ke5da781] -たいした変更ではありませんので、ここに差分を書きます。 static uint8_t usi_trans(uint8_t data){ USIDR=data; USISR=(1<<USIOIF); + if(wait==0) { + uchar CR0=(1<<USIWM0)|(1<<USICS1)|(1<<USITC); + uchar CR1=(1<<USIWM0)|(1<<USICS1)|(1<<USITC)|(1<<USICLK); + { + USICR=CR0; asm("nop"); USICR=CR1; asm("nop"); + USICR=CR0; asm("nop"); USICR=CR1; asm("nop"); + USICR=CR0; asm("nop"); USICR=CR1; asm("nop"); + USICR=CR0; asm("nop"); USICR=CR1; asm("nop"); + USICR=CR0; asm("nop"); USICR=CR1; asm("nop"); + USICR=CR0; asm("nop"); USICR=CR1; asm("nop"); + USICR=CR0; asm("nop"); USICR=CR1; asm("nop"); + USICR=CR0; asm("nop"); USICR=CR1; asm("nop"); + } + return USIDR; + }else{ do{ delay(wait); USICR=(1<<USIWM0)|(1<<USICS1)|(1<<USICLK)|(1<<USITC); } while(!(USISR&(1<<USIOIF))); + } return USIDR; } bash-2.02$ time ./hidspx.exe -rp >1 Detected device is ATmega88. Read Flash: 8192/8192 B Passed. real 0m1.915s user 0m0.015s sys 0m0.000s bash-2.02$ time ./hidspx.exe 8K.hex Detected device is ATmega88. Erase Flash memory. Write Flash: 8192/8192 B Verify Flash: 8192/8192 B Passed. real 0m4.247s user 0m0.015s sys 0m0.000s ---- *高速化改良(案のみ) [#ybae0820] -書き込みのみですが、32バイトのHID Reportを送りつけられている間もSPI転送するような ソリューションが考えられます。 -具体的には、usbFunctionWrite()で全部貯めてからSPI書き込みではなくて、8バイト貯まったHEXをそのつどSPIで送るといった方法です。 -読み出しは今のところAVRUSB側にポインタと長さを渡してそれっきり、という方法でやってますのでこれも、usbFunctionReadに引っ掛けて、ちまちま読み出す、というところでしょうか。 -ただし、delayオプションが長い場合はUSB転送の足を思いっきり引っ張るような気もしています。 -readに対してだけ実際に試してみましたが、8Kのreadに1.4秒が限界でした. ---- *高速化改良その2 [#ke5da781] -たいした変更ではありませんので、ここに差分を書きます。 static uint8_t usi_trans(uint8_t data){ USIDR=data; USISR=(1<<USIOIF); + if(wait==0) { + do{ + USICR=(1<<USIWM0)|(1<<USICS1)|(1<<USICLK)|(1<<USITC); + } while(!(USISR&(1<<USIOIF))); + return USIDR; + }else{ do{ delay(wait); USICR=(1<<USIWM0)|(1<<USICS1)|(1<<USICLK)|(1<<USITC); } while(!(USISR&(1<<USIOIF))); + } return USIDR; } avr-objcopy -j .text -j .data -O ihex main.elf main.hex bash checksize main.elf 2048 128 ROM: 2010 bytes (data=4) RAM: 93 bytes 残りあと38バイトとなりました。 **6KB書き込み&ベリファイ時間計測 [#b82fcd7c] HIDspx -ph -d<Delay> test.hex |Delay|Time| | -d0 | 4秒 | | -d1 | 5秒 | | -d4 | 8秒 | -計測に使用したマザーボードはSiS製です。 -マザーとHIDaspの間にはELECOM製のUSB1.1ハブが挟まっています。 ToDo: -時間計測コマンド(unixのtime相当)をちゃんと作る。 --今使っているのは自作ツールで 16bit MSDOSのコード。 1993/07/09 02:33 11,682 WATCH.EXE -そろそろATmega88では限界なのでATmega644のボードを(''書き込み時間計測のためだけに'')制作する。 -Snoopy−Proを使ってUSB転送の様子を観察し、パケット送信間隔等を評価する。 なんかこう、''AVRに高速に書き込むこと''が目的化してしまいました。笑っちゃいます。 ---- *高速化改良その1 [#vf296265] ''内容'' -パケットサイズのバリエーションをさらに増やしてみました。 -usbHidReportDescriptorを6種類用意して、サイズをそれぞれ、6,14,22,30,38,46 にしました。 -但し、読み込みパケットサイズは38に留めています。(現在のところ固定) -waitのループを瓶詰堂さんのオリジナルに戻しています(nopを消してしまいました:実は書き込み速度向上にはこれ+オプション「-d0」が一番効きます。) -さらに速くするには、-d0のときはdelay()を外したusi_trans()を用意するか、あるいはHIDaspを20MHz動作させる等が考えられますが、ターゲットデバイスが遅い場合は意味がありません。 [[ダウンロードはこちらです:hidspx-src-0920.zip:http://psp.dip.jp/web/upload.cgi/hidspx-src-0920.zip]] -書き込み速度の実測値ですが、ATmega88に6kBの書き込み&ベリファイで約5秒に短縮しました。 -CMD_PEEKとCMD_POKEを追加してあります。(未デバッグ) -また、サイズは以下の通りです。 avr-objcopy -j .text -j .data -O ihex main.elf main.hex bash checksize main.elf 2048 128 ROM: 1992 bytes (data=4) RAM: 93 bytes 追加: -HIDsphの '-d4'オプションのほうが、こちらの '-d0'書き込みより速いのではないか疑惑 --上記調査中です。 ---- *HIDasp高速化完了 [#l2b87bfc] [[千秋様のHPへのリンク:http://www-ice.yamagata-cit.ac.jp/ken/senshu/sitedev/index.php?AVR%2FHIDasp]] [[瓶詰堂さんのHPへのリンク:http://www.binzume.net/library/avr_hidasp.html]] senshu様から頂いたソースと、瓶詰堂さんのHIDaspソースをもとに 作成しました。 ディレクトリ構成 | hidspx-src/ HIDspx.exe とそのソースです。 | firmware/ AVR側のファームウェアHEXとそのソースです。 変更内容: -HID Reportの転送をHidD_GetFeature()/HidD_SetFeature()で行うようにしました。 -usbHidReportDescriptorを4種類用意して、サイズをそれぞれ、6,14,22,30にしました。 -変更点はたったそれだけです。 -上位プロトコルは瓶詰堂さんのHIDaspと同じままです。 -配線はUSBのD+,D-だけを PORTD,3,2 に変えて、他は瓶詰堂さんのHIDaspと同じです。 -usbHidReportDescriptorが異なりますので、上記exeとファームはペアでないと動作しません。 [[ダウンロードはこちらです:hidspx-src-0919.zip:http://psp.dip.jp/web/upload.cgi/hidspx-src-0919.zip]] -期待したほど速くはなりませんでした。 --ATmega88に6KBのHEXを書き込み&ベリファイにて、所要時間6秒(AMDマザーボード) --(後でPentium4マシンで追試しましたところ9秒でしたので、実は遅くなっただけかも・・・) -USBの挿抜に対しては安定です。 -コードサイズは以下のとおりです。特に縮める作業はやっていません。 avr-objcopy -j .text -j .data -O ihex main.elf main.hex bash checksize main.elf 8192 1024 ROM: 1962 bytes (data=4) RAM: 86 bytes *考察 [#g58ea4f9] -HID Report30バイトの書き込みと読み出しを交互に1000回実行してみます。 -実行方法は、hidasp.cのソースにて、最初に4回testパケットを送る部分を改造して、30バイトのHID Reportを送るようにします。 -ループ回数を1000に増やします。 - hidspx.exe -ph -r を実行します。(書き込みデバイスは無くてよい) -OHCIのUSB付きマザーで試したところ、1000回の試行に6秒掛かりましたが、UHCIではその倍の12秒でした。 -すなわち、30バイトのHID Reportを送るのに3フレーム(OHCI)もしくは6フレーム(UHCI)掛かる計算になります。 -より正確な時間の推移を知りたい場合はSnoopy-proというWindows上のUSBスニッファーを入れて、パケットをキャプチャーすると良いです。 -30バイト単位でただひたすら読むだけなら、10kB/s もしくは 5kB/s くらいの速度が出るはずなのに、実際にSPI転送が入るとその1/10あるいは1/5になるのは、なにか要因があるのだと思いますが、まだ追求できていません。 ~ ~ ~ ~ *落穂拾い [#f285f099] -配線は森芳電子さんの方法が洗練されているので、それに合わせたい。 --クロック出力をターゲットに与えることが可能になっている。 --LEDをPB2,PB3に移してあるので、TxD,RxDを使用可能になっている。(実際tiny2313ではコードを入れる空きがないけれど、同じ基板を別の用途に転用しやすい) --但し、D+,D-の配置がさらに変わるので、usbdrv/以下のいくつかのソースにまで手を入れなければならない。 --さらに、INT0がINT1に変わるので、最小限必要な割り込みベクタが2バイト増加する。 -AVRmonitの一部の機能(RAMやI/Oに対するPEEK/POKE命令)を組み込んで、代わりにLED制御はそっちでやる。 --すると、余ったポートにPWMを設定して昇圧回路をドライブするとか、変な付加機能をPC側から好きなように実装できる。 --AVRを焼かないときでも汎用IO代わりに流用できるようになる。 --AVRを焼いた直後にターゲットをリセット起動させたり、ターゲットとSPIクロス接続になっているので通信(printfデバッグ)したり出来るようになる(かも) -高速化したいけれど・・・。(無理かなぁ) --すzさんの考察されているように、HIDデバイスに見せかけておいて、libusb経由でバルク転送とか。 --ファーム容量的に無理っぽいのと、けっきょくそうういったことは別のAVRライターでやり尽くされているような気もする --自分はATtiny2313しか知らないので、そんな世界も知らない。でも見てみたいかも。 ''こうやって、AVRライターの種類だけが増えていく''のは、なんだかむなしいなぁ *HIDasp高速化検討中 [#ab6a2305] 光が見えてきたので、作業記録を書いてみる。 ''現状'' -HIDaspはWindowsAPIのReadFile()/WriteFile()によってHID Reportを転送している。 -HID Reportというのは、たとえばマウスならボタン情報、座標などを含む、固定サイズのデータだ。 -そのReportの1パケットは8バイトになっている。ReadFile()/WriteFile()に与える転送長は+1した9を与える。 -Report_IDは0になっている。ReadFile()/WriteFile()のバッファ先頭にReport_IDを置く。 -他の例(AVR-DoperやHIDsph)を見るとReportIDは1〜のようだ。 ''問題点'' -Windows2000では、起動時のハンドシェークでやりとりがうまく行かず、ハングする。 -WindowsXPではUSB挿入直後だけハンドシェークをミスるが、一応無視して継続する。 -転送速度は約1kB/秒なので、ATmega644では1分弱掛かり実用的でない。 --ATtiny2313では4秒程度なので問題なし。 ''改善策(案)'' -まず、HID Reportの転送単位を変更する(32バイト程度にすると効果あり) -HIDaspのusbHidReportDescriptorを[[AVR-Doper:http://www.obdev.at/products/avrusb/avrdoper.html]]ベースのものに差し替える。 -これは、HID Report ID 1〜5までが定義されていて、転送サイズ(REPORT_COUNT)はそれぞれ -(16-2),(32-2),(64-2),(128-2),(64-2) のようになっている。 -なぜ2のべき-2なのかというと、パケットの先頭にReport ID(1〜5のどれか)を入れる必要があるからだ。 -(でもそれは-1である理由にしかなってないんだけど) -実はキリの良い値でなければならないという理由はないがLowSpeed USBのパケット長上限は8バイトなので、総転送サイズが8の倍数になっているほうが効率が良い。 -最後のやつだけ数列から外れているが、これはデバッグパケットらしい。 ~ そして、HID Reportの転送には''HidD_GetFeature()/HidD_SetFeature()'' を使う。 -転送サイズはREPORT_COUNT+1を与え、バッファの先頭にはReport_IDを書き込んで使う。 ''今日やったこと'' -AVR-DoperのHidReportDescriptorを移植したAVR-USBのフレームワークを用意して、 32バイトパケットを単純にエコーバックするだけのファームを書く。 -そして、ホストPC側から、接続を試みる。 -(senshuさんのHIDspx-srcをありがたく使わせて頂いております) -31バイトのHID Reportを適当にでっちあげて Report_ID=2で送信し、そのエコーが戻ってくるのを確認。''<===今日はここまで'' とりあえず現状報告 avr-objcopy -j .text -j .data -O ihex main.elf main.hex bash checksize main.elf 8192 1024 ROM: 1968 bytes (data=4) RAM: 87 bytes -一応isp_commandまで入れた。 -AVRmonitは入れていない。 明日以降の予定 -AVRmonitをHIDベースにして、デバイスドライバ不要のやつを作ってみる。 -ベンチマーク機能があるので、ベンチマークしてみる。 -予想では4kB/s程度。根拠は32バイトまとめて送るので。 -%%コードサイズが余れば瓶詰さんのプロトコルを乗せてみる。%%すでに入っているつもり ~ ~ ~ ~ ~ ~ ~ ----- 下記の記述はHIDクラスの制約を無視した考察ですので、多分に間違いを含んでおります。 (libusbを使用する場合はOKかもしれません。) 現在再検討中です。 ----- 千秋さんのサイトでの話題 -http://www-ice.yamagata-cit.ac.jp/ken/senshu/sitedev/index.php?AVR%2Fnews25#l06c25ea 可能性を探ってみた。 -まず、LowSpeedの転送速度は、理論値1.5Mbpsあるように見えるけれどこれは''気の迷い''。 -基本、コントロール転送を使うと仮定。 -USBでは1フレーム(1mS)に8バイトのパケットが1回送れる(あるいは受け取れる)だけなのだ。 -じゃあ8kB/秒かというと微妙なところで、コントロール転送を用いて8バイトのベンダーコマンドを送り、デバイスから8バイトのリターンを返してもらうという1回のトランザクションの[[時間を計測してみる>今後の目標#l07b1d63]]と、 -OHCIでは1mSで完結するがUHCIでは4mS掛かる。 -つまり、OHCIでは1秒に8kB送って8kBのリターンが得られるが、 -UHCIではその1/4の速度(2kB/秒)まで落ちる。 -もうひとつやっかいなのがコントロール転送では8バイトの内容のうち、先頭1バイトがbmRequestTypeであり、お尻の2バイトがwLength(後続データのサイズ指定子)となっていて自由に使えない。 -つまり送出できる正味データ量は8kB/Sではなく5kB/Sになってしまうわけだ。(UHCIではさらにその1/4) --HIDaspに限った話をすると、5バイトのうち最初の1バイトがコマンドバイトとして使われていて、正味のSPIデータ送出は4バイト/フレームである。 --但し、AVR書き込みターゲットに対するページリードがサポートされていて、4バイトのファームウェアデータを1トランザクションで転送しているようなので、書き込み速度としては4バイト/4mS=毎秒1kBとなる。 -これを打破する手としては、1トランザクションに後続データを16〜32バイト付加してやって、1回のコントロール転送で16〜32バイト分のファームウェアデータを送りつけてやる方法だ。 -仮に32バイト送るとするとUHCIでは4+4=8フレームでおそらく完結するので、 -32バイト/8mS=4kB/秒になる計算だ。 -問題はそれらの処理を含めて2kBに入るかどうかなんだな。 -かなり難しいと思う。GCC4ではバイナリコードが肥大化する傾向があるのでGCC3ベースのWinAVRを使うしかないかも。 -むしろ、千秋さんのサイトで指摘されているとおり、tiny2313に固執するのをやめて、ATmega88あたりでゆったりとコードを組んだほうが正解なのかもしれない。 -でも、当サイトでは無理やりコードを縮めて2313に詰め込む方向にむしろ快感を感じるので、mega88は使わないだろうと思う。(嘘。手持ちのmega88が少なくて、2313ばかりが余っているので、2313を使い切る方向で考えている。) ----
タイムスタンプを変更しない
From:[[2008-09]] From:[[HIDasp]] ''このページは、瓶詰堂さんのHIDaspで実装されているHID Reportの転送速度向上について考察したものです'' -時間軸が逆になっていて、上の情報のほうが新しいです。 -最新版アーカイブと、制作に関する説明は、[[HIDasp]]のページをご覧ください。 ---- *HIDasp速度比較 [#x38a5e09] -[[HIDasp速度比較]]のページをご覧ください。 #contents ---- *AVRUSB FLOW_CONTROLの追加 [#x7c77c66] AMDマザーで計測.(SiSではこれより遅いです.) |8kB | -d0 | read | 1.453 sec (5.637kB/s) | |8kB | -d0 | write & verify | 3.157 sec (2.594kB/s) | bash-3.2$ time ./hidspx.exe -ph -d0 8kB.hex Detected device is ATmega88. Erase Flash memory. Write Flash: 8192/8192 B Verify Flash: 8192/8192 B Passed. real 0m3.157s user 0m0.015s sys 0m0.015s bash-3.2$ time ./hidspx.exe -ph -d0 -rp >rom.hex Detected device is ATmega88. Read Flash: 8192/8192 B Passed. real 0m1.453s user 0m0.047s sys 0m0.000s ---- *HID Report送信の遅延評価 [#c2b871b8] -HID Reportのパケットを受け取った後、isp書き込み時間がどの程度許されるのかを評価してみた。 -[[ソースアーカイブ:hidmon-test-1007.zip:http://psp.dip.jp/web/upload.cgi/hidmon-test-1007.zip]] -結果 -bench2コマンドは第一引数が試行回数、第二引数が遅延係数(単位は10μ秒) -HIDパケットサイズは39バイト固定。送信(ホストからデバイス宛)のみ。 -Low Speed USBパケットを8バイト受け取る毎に待ちループを呼び出している。 X:UHCI(intel i815e)>hidmon -i script AVR> bench2 100 1 hid delay write start hid delay write end, 3900 bytes/801 ms, 4868 bytes/s AVR> bench2 100 2 hid delay write start hid delay write end, 3900 bytes/791 ms, 4930 bytes/s AVR> bench2 100 3 hid delay write start hid delay write end, 3900 bytes/801 ms, 4868 bytes/s AVR> bench2 100 4 hid delay write start hid delay write end, 3900 bytes/811 ms, 4808 bytes/s AVR> bench2 100 5 hid delay write start hid delay write end, 3900 bytes/801 ms, 4868 bytes/s AVR> bench2 100 6 hid delay write start hid delay write end, 3900 bytes/801 ms, 4868 bytes/s AVR> bench2 100 7 hid delay write start hid delay write end, 3900 bytes/801 ms, 4868 bytes/s AVR> bench2 100 8 hid delay write start hid delay write end, 3900 bytes/801 ms, 4868 bytes/s AVR> bench2 100 9 hid delay write start hid delay write end, 3900 bytes/791 ms, 4930 bytes/s AVR> bench2 100 10 hid delay write start hid delay write end, 3900 bytes/802 ms, 4862 bytes/s AVR> bench2 100 20 hid delay write start hid delay write end, 3900 bytes/801 ms, 4868 bytes/s AVR> bench2 100 30 hid delay write start hid delay write end, 3900 bytes/801 ms, 4868 bytes/s AVR> bench2 100 40 hid delay write start hid delay write end, 3900 bytes/801 ms, 4868 bytes/s AVR> bench2 100 50 hid delay write start hid delay write end, 3900 bytes/801 ms, 4868 bytes/s AVR> bench2 100 60 hid delay write start hid delay write end, 3900 bytes/801 ms, 4868 bytes/s AVR> bench2 100 70 hid delay write start hid delay write end, 3900 bytes/802 ms, 4862 bytes/s AVR> bench2 100 80 hid delay write start hid delay write end, 3900 bytes/801 ms, 4868 bytes/s AVR> bench2 100 90 hid delay write start hid delay write end, 3900 bytes/1302 ms, 2995 bytes/s AVR> bench2 100 110 hid delay write start hid delay write end, 3900 bytes/1302 ms, 2995 bytes/s AVR> bench2 100 120 hid delay write start hid delay write end, 3900 bytes/1301 ms, 2997 bytes/s AVR> bench2 100 130 hid delay write start hid delay write end, 3900 bytes/1301 ms, 2997 bytes/s AVR> bench2 100 140 hid delay write start hid delay write end, 3900 bytes/1302 ms, 2995 bytes/s AVR> bench2 100 150 hid delay write start hid delay write end, 3900 bytes/1292 ms, 3018 bytes/s AVR> bench2 100 160 hid delay write start hid delay write end, 3900 bytes/1402 ms, 2781 bytes/s AVR> bench2 100 170 hid delay write start hid delay write end, 3900 bytes/1803 ms, 2163 bytes/s AVR> bench2 100 180 hid delay write start hid delay write end, 3900 bytes/1792 ms, 2176 bytes/s AVR> bench2 100 190 hid delay write start hid delay write end, 3900 bytes/1803 ms, 2163 bytes/s AVR> q Bye. X:OHCI(SiS M671T)>hidmon -i script AVR> bench2 100 1 hid delay write start hid delay write end, 3900 bytes/203 ms, 19211 bytes/s AVR> bench2 100 2 hid delay write start hid delay write end, 3900 bytes/297 ms, 13131 bytes/s AVR> bench2 100 3 hid delay write start hid delay write end, 3900 bytes/296 ms, 13175 bytes/s AVR> bench2 100 4 hid delay write start hid delay write end, 3900 bytes/329 ms, 11854 bytes/s AVR> bench2 100 5 hid delay write start hid delay write end, 3900 bytes/391 ms, 9974 bytes/s AVR> bench2 100 6 hid delay write start hid delay write end, 3900 bytes/406 ms, 9605 bytes/s AVR> bench2 100 7 hid delay write start hid delay write end, 3900 bytes/453 ms, 8609 bytes/s AVR> bench2 100 8 hid delay write start hid delay write end, 3900 bytes/485 ms, 8041 bytes/s AVR> bench2 100 9 hid delay write start hid delay write end, 3900 bytes/500 ms, 7800 bytes/s AVR> bench2 100 10 hid delay write start hid delay write end, 3900 bytes/500 ms, 7800 bytes/s AVR> bench2 100 20 hid delay write start hid delay write end, 3900 bytes/797 ms, 4893 bytes/s AVR> bench2 100 30 hid delay write start hid delay write end, 3900 bytes/1188 ms, 3282 bytes/s AVR> bench2 100 40 hid delay write start hid delay write end, 3900 bytes/1563 ms, 2495 bytes/s AVR> bench2 100 50 hid delay write start hid delay write end, 3900 bytes/1828 ms, 2133 bytes/s AVR> bench2 100 60 hid delay write start hid delay write end, 3900 bytes/2203 ms, 1770 bytes/s AVR> bench2 100 70 hid delay write start hid delay write end, 3900 bytes/2515 ms, 1550 bytes/s AVR> bench2 100 80 hid delay write start hid delay write end, 3900 bytes/2844 ms, 1371 bytes/s AVR> bench2 100 90 hid delay write start hid delay write end, 3900 bytes/3203 ms, 1217 bytes/s AVR> bench2 100 110 hid delay write start hid delay write end, 3900 bytes/3875 ms, 1006 bytes/s AVR> bench2 100 120 hid delay write start hid delay write end, 3900 bytes/4172 ms, 934 bytes/s AVR> bench2 100 130 hid delay write start hid delay write end, 3900 bytes/4500 ms, 866 bytes/s AVR> bench2 100 140 hid delay write start hid delay write end, 3900 bytes/4796 ms, 813 bytes/s AVR> bench2 100 150 hid delay write start hid delay write end, 3900 bytes/5188 ms, 751 bytes/s AVR> bench2 100 160 hid delay write start hid delay write end, 3900 bytes/5562 ms, 701 bytes/s AVR> bench2 100 170 hid delay write start hid delay write end, 3900 bytes/5828 ms, 669 bytes/s AVR> bench2 100 180 hid delay write start hid delay write end, 3900 bytes/6188 ms, 630 bytes/s AVR> bench2 100 190 hid delay write start hid delay write end, 3900 bytes/6531 ms, 597 bytes/s AVR> q Bye. -結果、なんと''UHCIでは1パケット毎に直後800μ秒のISPコマンド処理時間があったとしても、コンスタントに4.8kB/秒の転送速度を保っている!'' -つまり、HIDでもインターリーブの効果はあるということだ。 -逆に、OHCIでは800μ秒のISPコマンド処理時間があった場合、1.3kB/秒にまで転送速度が落ちている。 -これは謎だ。 ちなみに '-d3'オプションを指定した場合のSCLKは375kHzなので、 -8ビットのSPIを送るのに必要な時間は21.33μ秒。 -8バイトのファームウェアをページバッファにセットアップする時間はその32倍の683μ秒あれば良い。 --(SPIコマンドは常に4バイト単位になっていて、1コマンドで正味データ1バイト分しか転送できない) ---- *ファームウェアの容量削減 [#kd61a76d] -senshuさんにより取り纏め頂いたhidspx-0928b.zipに対して、firmware容量の削減を 行いました。 -機能やコンフィギュレーションは同一です。 -[[ソースアーカイブ:hidspx-0928c.zip:http://psp.dip.jp/web/upload.cgi/hidspx-0928c.zip]] avr-objcopy -j .text -j .data -O ihex main.elf main.hex avr-size --mcu=attiny2313 main.elf text data bss dec hex filename 2014 4 88 2106 83a main.elf -1988バイトは気の迷いでした。(とあるコーディングミスで最適化され機能削除されていました。) -WinAVRのバージョンは2006-0421でビルドしていますので、最新のWinAVRではサイズが変わる(増える)かもしれません。 おまけソフト -[[HIDmon:hidmon-0929.zip:http://psp.dip.jp/web/upload.cgi/hidmon-0929.zip]] ---- *SCK、MOSIのHi−Z化改良 [#z551790c] -senshuさんにより取り纏め頂いたhidspx-0928.zipに対して、SCK、MOSIのHi−Z化を 行いました。 -ライターが書き込み動作を行っていないときはSCK、MOSIをHi−Zにします。 -[[ソースアーカイブ:hidspx-0928a.zip:http://psp.dip.jp/web/upload.cgi/hidspx-0928a.zip]] ---- *高速化改良その6 [#p7941a5a] - address_set , page_write , isp_command を全部含んだ融合コマンドを実装しました。 - tiny2313では、かなり有効かと思われます。 - それに伴って命令セット体系に少し変更が生じました。 - %%ソースは現在整理中です。乞うご期待。%% ''任務完了!'' -[[ソースアーカイブ:hidspx-0927a.zip:http://psp.dip.jp/web/upload.cgi/hidspx-0927a.zip]] おまけソフト -[[HIDmon:hidmon-0927a.zip:http://psp.dip.jp/web/upload.cgi/hidmon-0927a.zip]] 注意 -%%HIDmonを使用される場合は命令Fusionが使えませんので、%% --使えるようにしました。 #define INCLUDE_FUSION 0 #define INCLUDE_MONITOR_CMD 1 %%でファームを作成しなおしてください。%% -ポートの方向初期値を適切に設定してあげてください。 たぶん、ここらで打ち止めです。 -残りはHIDmonの若干の機能強化と、汎用USB I/O DLLもどきの作成。 ---- *高速化改良その5 [#cf9dee00] ''変更内容''(わりと堅実路線) - '-d<delay>' オプションのクロックをUSBaspに近づけるように努力しました。 -- 詳細は firmware/main.c にあります。 - hidasp.c を少しリライトしました。 -- デバッグ文が多くて見づらかったためです。 - メモリーを減らしました。 -- -d<delay> で思いのほかメモリー使用量が増えたので、ダイエットです。 - タイマー0によるUSIクロック生成は諦めました。 -- うまくいく方法が見つかったらこっそり教えてください。 -[[ソースアーカイブ:hidspx-src-0925.zip:http://psp.dip.jp/web/upload.cgi/hidspx-src-0925.zip]] ---- *高速化改良その4 [#pb2d0ff9] -紆余曲折の末、8バイト単位でのインターリーブ転送を実施することに決定しました。 -つまり、図で書くとこんな感じ 時間軸 0mS 1mS 2mS +--------------------------+-----------------------------+------------------ ... |USB転送| |USB転送| |USB転送| +--------------------------+-----------------------------+------------------ ... |<=ISP書き込み===>| |<=ISP書き込み======>| |<=ISP書き込み -目標では5kB/S(但しSCLK1MHz弱程度を想定) -SCLKはタイマー0で与える。 -タイマー0のプリスケーラと分周比のペアを専用のコマンドで与える。 -ディレイオプション -d<delay> からペア値への変換表はホストPC側が担当する。 さて、うまくいきますやら・・・ ''結論'' -駄目でした。(テストマシンはintel UHCI) |8kB | -d0 | read | 1.862 sec (4.4kB/s) | |8kB | -d0 | write & verify | 5.368 sec (1.5kB/s) | ちなみにfirmのサイズは2048きっかりでした。 -LED,MONITORの両方削除 -アンロール削除 -vendor,productIDを1字に。 -HID Reportディスクリプタは最小限の3個(6,38,70) そもそも5kB/Sは読みか書きのどちらかの速度です。 -転送ベンチが5kだったので、書き&ベリファイで5kも出るわけないです。 -あと、現在の実装は書き込みパケットにかなり無駄があります。(page_writeの前後の2パケットは内包可能) コードエリアが足りません。(これは深刻・・・) avr-size --mcu=attiny2313 main.elf text data bss dec hex filename 2034 4 59 2097 831 main.elf -100mSのディレイが残っていたので、差し引くと1.762 sec -書き込み時には無駄パケットが少し多いので、パケットをうまく統合するとreadの倍の3.6 sec 程度まで行くかもしれません。 -でも、どう頑張っても5Kの半分(2.5k/s)よりは出ないでしょう。 -だったら、今の最速(W&Vで2K弱)をキープして、コード保守するほうが堅実なのかもしれません。 実計測結果~ [[テストアーカイブ:hidspx-test-0925.zip:http://psp.dip.jp/web/upload.cgi/hidspx-test-0925.zip]] -マシン=Athlon64 USBホスト=VIAチップPCIカード(UHCI) -delayループ取り払い状態(1.5MHz SCLK) -ATmega88へ8192バイトのHEXを書き込み&ベリファイ bash-3.2$ time ./hidspx.exe -ph -d0 xx.hex Detected device is ATmega88. Erase Flash memory. Write Flash: 8192/8192 B Verify Flash: 8192/8192 B Passed. real 0m3.859s user 0m0.031s sys 0m0.015s -ATmega88から8192バイトのHEXを読み込み bash-3.2$ time ./hidspx.exe -ph -d0 -rp >a.hex Detected device is ATmega88. Read Flash: 8192/8192 B Passed. real 0m1.438s user 0m0.015s sys 0m0.000s bash-3.2$ -まとめ(テストマシンはAMD + UHCI) -delay()ループ完全取り払い(SCLK=1.5MHz) |8kB | -d0 | read | 1.438 sec (5.696kB/s) | |8kB | -d0 | write & verify | 3.859 sec (2.122kB/s) | -書き込みパケット数を減量(統合)すれば、write & verifyはもうすこし速くなりますので、2.5kB/sも夢ではないかもしれませんが、そのまえにコードサイズのスリム化が必要です。(どなたか挑戦しませんか、アーカイブは上記のhidspx-test-0925.zipです) とりあえず、いい夢を見させてくれました。ありがとう>USBasp ---- *AVRbench [#baa8c2ec] usbFunctionWrite()の性能テスト. -usbFunctionWrite()内に遅延関数の呼び出しを入れる。 -どのくらい遅延すると、ホスト側の速度に影響するかのテスト. -0060 番地が遅延係数で 1 増えるごとに100uS -使い方は win32/ で term -iscript [[テストアーカイブ:AVRbench.zip:http://psp.dip.jp/web/upload.cgi/AVRbench.zip]] ---- *高速化改良その3 [#ke5da781] -たいした変更ではありませんので、ここに差分を書きます。 static uint8_t usi_trans(uint8_t data){ USIDR=data; USISR=(1<<USIOIF); + if(wait==0) { + uchar CR0=(1<<USIWM0)|(1<<USICS1)|(1<<USITC); + uchar CR1=(1<<USIWM0)|(1<<USICS1)|(1<<USITC)|(1<<USICLK); + { + USICR=CR0; asm("nop"); USICR=CR1; asm("nop"); + USICR=CR0; asm("nop"); USICR=CR1; asm("nop"); + USICR=CR0; asm("nop"); USICR=CR1; asm("nop"); + USICR=CR0; asm("nop"); USICR=CR1; asm("nop"); + USICR=CR0; asm("nop"); USICR=CR1; asm("nop"); + USICR=CR0; asm("nop"); USICR=CR1; asm("nop"); + USICR=CR0; asm("nop"); USICR=CR1; asm("nop"); + USICR=CR0; asm("nop"); USICR=CR1; asm("nop"); + } + return USIDR; + }else{ do{ delay(wait); USICR=(1<<USIWM0)|(1<<USICS1)|(1<<USICLK)|(1<<USITC); } while(!(USISR&(1<<USIOIF))); + } return USIDR; } bash-2.02$ time ./hidspx.exe -rp >1 Detected device is ATmega88. Read Flash: 8192/8192 B Passed. real 0m1.915s user 0m0.015s sys 0m0.000s bash-2.02$ time ./hidspx.exe 8K.hex Detected device is ATmega88. Erase Flash memory. Write Flash: 8192/8192 B Verify Flash: 8192/8192 B Passed. real 0m4.247s user 0m0.015s sys 0m0.000s ---- *高速化改良(案のみ) [#ybae0820] -書き込みのみですが、32バイトのHID Reportを送りつけられている間もSPI転送するような ソリューションが考えられます。 -具体的には、usbFunctionWrite()で全部貯めてからSPI書き込みではなくて、8バイト貯まったHEXをそのつどSPIで送るといった方法です。 -読み出しは今のところAVRUSB側にポインタと長さを渡してそれっきり、という方法でやってますのでこれも、usbFunctionReadに引っ掛けて、ちまちま読み出す、というところでしょうか。 -ただし、delayオプションが長い場合はUSB転送の足を思いっきり引っ張るような気もしています。 -readに対してだけ実際に試してみましたが、8Kのreadに1.4秒が限界でした. ---- *高速化改良その2 [#ke5da781] -たいした変更ではありませんので、ここに差分を書きます。 static uint8_t usi_trans(uint8_t data){ USIDR=data; USISR=(1<<USIOIF); + if(wait==0) { + do{ + USICR=(1<<USIWM0)|(1<<USICS1)|(1<<USICLK)|(1<<USITC); + } while(!(USISR&(1<<USIOIF))); + return USIDR; + }else{ do{ delay(wait); USICR=(1<<USIWM0)|(1<<USICS1)|(1<<USICLK)|(1<<USITC); } while(!(USISR&(1<<USIOIF))); + } return USIDR; } avr-objcopy -j .text -j .data -O ihex main.elf main.hex bash checksize main.elf 2048 128 ROM: 2010 bytes (data=4) RAM: 93 bytes 残りあと38バイトとなりました。 **6KB書き込み&ベリファイ時間計測 [#b82fcd7c] HIDspx -ph -d<Delay> test.hex |Delay|Time| | -d0 | 4秒 | | -d1 | 5秒 | | -d4 | 8秒 | -計測に使用したマザーボードはSiS製です。 -マザーとHIDaspの間にはELECOM製のUSB1.1ハブが挟まっています。 ToDo: -時間計測コマンド(unixのtime相当)をちゃんと作る。 --今使っているのは自作ツールで 16bit MSDOSのコード。 1993/07/09 02:33 11,682 WATCH.EXE -そろそろATmega88では限界なのでATmega644のボードを(''書き込み時間計測のためだけに'')制作する。 -Snoopy−Proを使ってUSB転送の様子を観察し、パケット送信間隔等を評価する。 なんかこう、''AVRに高速に書き込むこと''が目的化してしまいました。笑っちゃいます。 ---- *高速化改良その1 [#vf296265] ''内容'' -パケットサイズのバリエーションをさらに増やしてみました。 -usbHidReportDescriptorを6種類用意して、サイズをそれぞれ、6,14,22,30,38,46 にしました。 -但し、読み込みパケットサイズは38に留めています。(現在のところ固定) -waitのループを瓶詰堂さんのオリジナルに戻しています(nopを消してしまいました:実は書き込み速度向上にはこれ+オプション「-d0」が一番効きます。) -さらに速くするには、-d0のときはdelay()を外したusi_trans()を用意するか、あるいはHIDaspを20MHz動作させる等が考えられますが、ターゲットデバイスが遅い場合は意味がありません。 [[ダウンロードはこちらです:hidspx-src-0920.zip:http://psp.dip.jp/web/upload.cgi/hidspx-src-0920.zip]] -書き込み速度の実測値ですが、ATmega88に6kBの書き込み&ベリファイで約5秒に短縮しました。 -CMD_PEEKとCMD_POKEを追加してあります。(未デバッグ) -また、サイズは以下の通りです。 avr-objcopy -j .text -j .data -O ihex main.elf main.hex bash checksize main.elf 2048 128 ROM: 1992 bytes (data=4) RAM: 93 bytes 追加: -HIDsphの '-d4'オプションのほうが、こちらの '-d0'書き込みより速いのではないか疑惑 --上記調査中です。 ---- *HIDasp高速化完了 [#l2b87bfc] [[千秋様のHPへのリンク:http://www-ice.yamagata-cit.ac.jp/ken/senshu/sitedev/index.php?AVR%2FHIDasp]] [[瓶詰堂さんのHPへのリンク:http://www.binzume.net/library/avr_hidasp.html]] senshu様から頂いたソースと、瓶詰堂さんのHIDaspソースをもとに 作成しました。 ディレクトリ構成 | hidspx-src/ HIDspx.exe とそのソースです。 | firmware/ AVR側のファームウェアHEXとそのソースです。 変更内容: -HID Reportの転送をHidD_GetFeature()/HidD_SetFeature()で行うようにしました。 -usbHidReportDescriptorを4種類用意して、サイズをそれぞれ、6,14,22,30にしました。 -変更点はたったそれだけです。 -上位プロトコルは瓶詰堂さんのHIDaspと同じままです。 -配線はUSBのD+,D-だけを PORTD,3,2 に変えて、他は瓶詰堂さんのHIDaspと同じです。 -usbHidReportDescriptorが異なりますので、上記exeとファームはペアでないと動作しません。 [[ダウンロードはこちらです:hidspx-src-0919.zip:http://psp.dip.jp/web/upload.cgi/hidspx-src-0919.zip]] -期待したほど速くはなりませんでした。 --ATmega88に6KBのHEXを書き込み&ベリファイにて、所要時間6秒(AMDマザーボード) --(後でPentium4マシンで追試しましたところ9秒でしたので、実は遅くなっただけかも・・・) -USBの挿抜に対しては安定です。 -コードサイズは以下のとおりです。特に縮める作業はやっていません。 avr-objcopy -j .text -j .data -O ihex main.elf main.hex bash checksize main.elf 8192 1024 ROM: 1962 bytes (data=4) RAM: 86 bytes *考察 [#g58ea4f9] -HID Report30バイトの書き込みと読み出しを交互に1000回実行してみます。 -実行方法は、hidasp.cのソースにて、最初に4回testパケットを送る部分を改造して、30バイトのHID Reportを送るようにします。 -ループ回数を1000に増やします。 - hidspx.exe -ph -r を実行します。(書き込みデバイスは無くてよい) -OHCIのUSB付きマザーで試したところ、1000回の試行に6秒掛かりましたが、UHCIではその倍の12秒でした。 -すなわち、30バイトのHID Reportを送るのに3フレーム(OHCI)もしくは6フレーム(UHCI)掛かる計算になります。 -より正確な時間の推移を知りたい場合はSnoopy-proというWindows上のUSBスニッファーを入れて、パケットをキャプチャーすると良いです。 -30バイト単位でただひたすら読むだけなら、10kB/s もしくは 5kB/s くらいの速度が出るはずなのに、実際にSPI転送が入るとその1/10あるいは1/5になるのは、なにか要因があるのだと思いますが、まだ追求できていません。 ~ ~ ~ ~ *落穂拾い [#f285f099] -配線は森芳電子さんの方法が洗練されているので、それに合わせたい。 --クロック出力をターゲットに与えることが可能になっている。 --LEDをPB2,PB3に移してあるので、TxD,RxDを使用可能になっている。(実際tiny2313ではコードを入れる空きがないけれど、同じ基板を別の用途に転用しやすい) --但し、D+,D-の配置がさらに変わるので、usbdrv/以下のいくつかのソースにまで手を入れなければならない。 --さらに、INT0がINT1に変わるので、最小限必要な割り込みベクタが2バイト増加する。 -AVRmonitの一部の機能(RAMやI/Oに対するPEEK/POKE命令)を組み込んで、代わりにLED制御はそっちでやる。 --すると、余ったポートにPWMを設定して昇圧回路をドライブするとか、変な付加機能をPC側から好きなように実装できる。 --AVRを焼かないときでも汎用IO代わりに流用できるようになる。 --AVRを焼いた直後にターゲットをリセット起動させたり、ターゲットとSPIクロス接続になっているので通信(printfデバッグ)したり出来るようになる(かも) -高速化したいけれど・・・。(無理かなぁ) --すzさんの考察されているように、HIDデバイスに見せかけておいて、libusb経由でバルク転送とか。 --ファーム容量的に無理っぽいのと、けっきょくそうういったことは別のAVRライターでやり尽くされているような気もする --自分はATtiny2313しか知らないので、そんな世界も知らない。でも見てみたいかも。 ''こうやって、AVRライターの種類だけが増えていく''のは、なんだかむなしいなぁ *HIDasp高速化検討中 [#ab6a2305] 光が見えてきたので、作業記録を書いてみる。 ''現状'' -HIDaspはWindowsAPIのReadFile()/WriteFile()によってHID Reportを転送している。 -HID Reportというのは、たとえばマウスならボタン情報、座標などを含む、固定サイズのデータだ。 -そのReportの1パケットは8バイトになっている。ReadFile()/WriteFile()に与える転送長は+1した9を与える。 -Report_IDは0になっている。ReadFile()/WriteFile()のバッファ先頭にReport_IDを置く。 -他の例(AVR-DoperやHIDsph)を見るとReportIDは1〜のようだ。 ''問題点'' -Windows2000では、起動時のハンドシェークでやりとりがうまく行かず、ハングする。 -WindowsXPではUSB挿入直後だけハンドシェークをミスるが、一応無視して継続する。 -転送速度は約1kB/秒なので、ATmega644では1分弱掛かり実用的でない。 --ATtiny2313では4秒程度なので問題なし。 ''改善策(案)'' -まず、HID Reportの転送単位を変更する(32バイト程度にすると効果あり) -HIDaspのusbHidReportDescriptorを[[AVR-Doper:http://www.obdev.at/products/avrusb/avrdoper.html]]ベースのものに差し替える。 -これは、HID Report ID 1〜5までが定義されていて、転送サイズ(REPORT_COUNT)はそれぞれ -(16-2),(32-2),(64-2),(128-2),(64-2) のようになっている。 -なぜ2のべき-2なのかというと、パケットの先頭にReport ID(1〜5のどれか)を入れる必要があるからだ。 -(でもそれは-1である理由にしかなってないんだけど) -実はキリの良い値でなければならないという理由はないがLowSpeed USBのパケット長上限は8バイトなので、総転送サイズが8の倍数になっているほうが効率が良い。 -最後のやつだけ数列から外れているが、これはデバッグパケットらしい。 ~ そして、HID Reportの転送には''HidD_GetFeature()/HidD_SetFeature()'' を使う。 -転送サイズはREPORT_COUNT+1を与え、バッファの先頭にはReport_IDを書き込んで使う。 ''今日やったこと'' -AVR-DoperのHidReportDescriptorを移植したAVR-USBのフレームワークを用意して、 32バイトパケットを単純にエコーバックするだけのファームを書く。 -そして、ホストPC側から、接続を試みる。 -(senshuさんのHIDspx-srcをありがたく使わせて頂いております) -31バイトのHID Reportを適当にでっちあげて Report_ID=2で送信し、そのエコーが戻ってくるのを確認。''<===今日はここまで'' とりあえず現状報告 avr-objcopy -j .text -j .data -O ihex main.elf main.hex bash checksize main.elf 8192 1024 ROM: 1968 bytes (data=4) RAM: 87 bytes -一応isp_commandまで入れた。 -AVRmonitは入れていない。 明日以降の予定 -AVRmonitをHIDベースにして、デバイスドライバ不要のやつを作ってみる。 -ベンチマーク機能があるので、ベンチマークしてみる。 -予想では4kB/s程度。根拠は32バイトまとめて送るので。 -%%コードサイズが余れば瓶詰さんのプロトコルを乗せてみる。%%すでに入っているつもり ~ ~ ~ ~ ~ ~ ~ ----- 下記の記述はHIDクラスの制約を無視した考察ですので、多分に間違いを含んでおります。 (libusbを使用する場合はOKかもしれません。) 現在再検討中です。 ----- 千秋さんのサイトでの話題 -http://www-ice.yamagata-cit.ac.jp/ken/senshu/sitedev/index.php?AVR%2Fnews25#l06c25ea 可能性を探ってみた。 -まず、LowSpeedの転送速度は、理論値1.5Mbpsあるように見えるけれどこれは''気の迷い''。 -基本、コントロール転送を使うと仮定。 -USBでは1フレーム(1mS)に8バイトのパケットが1回送れる(あるいは受け取れる)だけなのだ。 -じゃあ8kB/秒かというと微妙なところで、コントロール転送を用いて8バイトのベンダーコマンドを送り、デバイスから8バイトのリターンを返してもらうという1回のトランザクションの[[時間を計測してみる>今後の目標#l07b1d63]]と、 -OHCIでは1mSで完結するがUHCIでは4mS掛かる。 -つまり、OHCIでは1秒に8kB送って8kBのリターンが得られるが、 -UHCIではその1/4の速度(2kB/秒)まで落ちる。 -もうひとつやっかいなのがコントロール転送では8バイトの内容のうち、先頭1バイトがbmRequestTypeであり、お尻の2バイトがwLength(後続データのサイズ指定子)となっていて自由に使えない。 -つまり送出できる正味データ量は8kB/Sではなく5kB/Sになってしまうわけだ。(UHCIではさらにその1/4) --HIDaspに限った話をすると、5バイトのうち最初の1バイトがコマンドバイトとして使われていて、正味のSPIデータ送出は4バイト/フレームである。 --但し、AVR書き込みターゲットに対するページリードがサポートされていて、4バイトのファームウェアデータを1トランザクションで転送しているようなので、書き込み速度としては4バイト/4mS=毎秒1kBとなる。 -これを打破する手としては、1トランザクションに後続データを16〜32バイト付加してやって、1回のコントロール転送で16〜32バイト分のファームウェアデータを送りつけてやる方法だ。 -仮に32バイト送るとするとUHCIでは4+4=8フレームでおそらく完結するので、 -32バイト/8mS=4kB/秒になる計算だ。 -問題はそれらの処理を含めて2kBに入るかどうかなんだな。 -かなり難しいと思う。GCC4ではバイナリコードが肥大化する傾向があるのでGCC3ベースのWinAVRを使うしかないかも。 -むしろ、千秋さんのサイトで指摘されているとおり、tiny2313に固執するのをやめて、ATmega88あたりでゆったりとコードを組んだほうが正解なのかもしれない。 -でも、当サイトでは無理やりコードを縮めて2313に詰め込む方向にむしろ快感を感じるので、mega88は使わないだろうと思う。(嘘。手持ちのmega88が少なくて、2313ばかりが余っているので、2313を使い切る方向で考えている。) ----
テキスト整形のルールを表示する
ログインまたはアカウント作成