2011年3月4日 星期五

USB Deep Trace Down

在做有關 burning 的問題的時候,發現速度並不夠快。
於是深入追蹤 在usbdrv.cpp 中發現在 GetInterface() 的上面有一段詳細說明


 *        The USB (OHCI) hardware assumes a host page size of 4K bytes.  Under Windows CE, many
 *        supported processors do not necessarily follow this assumption (1K page size is common).
 *        The issue here is that the underlying hardware can use scatter/gather DMA, but
 *        can handle at most 1 page transition per transfer.  However, client buffers on systems
 *        with smaller page sizes may be scattered across several physically disjoint pages.
 *
 *        In order to make this restriction transparent to client drivers, OHCD.DLL allocates
 *        a buffer from the system which is known to be contiguous within 4K sections.
 *        Then, DMA is done to the private buffers, and copied to the client buffer
 *        once the transfer is complete.  For some client drivers, this extra copy may
 *        impose an unacceptable performance hit, however.  So, the Windows CE transfer functions
 *        allow the client to pass in an optional physical memory address which is used directly
 *        for the DMA to/from the HC hardware.  Because the HC accesses this buffer directly,
 *        the following two restrictions must be rigidly adhered to:
 *
 *        1) Physical buffer must be contiguous within 4K segments.   How the client allocates
 *           this memory is beyond the scope of this document (e.g. may be through a platform
 *           specific call). The LockPages() call can be used to get physical page information.
 *
 *        2) Client must not access or free the buffer before the transfer has completed.

意思就是說 USB Transfer 的時候,OHCD (or EHCD) 會 allocate 一個private的 4K buffer.
給 DMA 用,然後DMA完成時,再用memcpy 到 client buffer。
但是這會帶來 performance 的衝擊。


也就是 LPISSUE_BULK_TRANSFER (7個參數)  的最後一個參數 Physical Address 假如不為
NULL, Host Controller 會直接 DMA到這個 Physical Address.


以bot transfer 為例
BOT_DataTransfer (usbmsc.c)   ....BulkTransfer::SendAnotherTransfer  --> lpIssueBulkTransfer
http://support.microsoft.com/kb/937755/en-us
上面文章有用
三種加速的方法,Disable Cache, PacketsPerTransfer 0x80, IntThresCtrl = 1

[HKEY_LOCAL_MACHINE\Drivers\USB\ClientDrivers\Mass_Storage_Class] 
"DisableBuffering"=0 時會用 DMA   =1 時 不用DMA(也就是不指定Physical address)


但是 = 0 時用DMA 也是另外 AllocPhysMem (in BulkTransfer::BulkTransfer() ) 然後再 memcpy ( 2個 in BulkTrans.cpp )


所以要真正加速而減少 memcpy 的話,必須要rewrite usbmsc bot部份


FILE_FLAG_WRITE_THROUGH & FILE_FLAG_NO_BUFFERING 沒用
http://support.microsoft.com/kb/99794/en-us

最後結果
能提昇USB速度有用的是 IntThresCtrl = 1
在Au1200 BSP中 修改registry 並沒有用
it is hard wired in Platform\DB1200\Drivers\USB20\EHCI\CHW.CPP
in CHW::EnterOperationalState()
set usbcmd.bit.IntThreshCtrl = 1 // original 8 microframe

EnableCache=0 + PacketsPerTransfer=80 in common.reg also improve

沒有留言: