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を使い切る方向で考えている。)

----