HIDasp高速化 の変更点
#author("2022-07-25T21:56:43+09:00","","")
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回のトランザクションの[[時間を計測してみる>http:/~iruka/v/?%BA%A3%B8%E5%A4%CE%CC%DC%C9%B8#l07b1d63]]と、
-じゃあ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を使い切る方向で考えている。)
----