詳情:http://bbs.21ic.com/forum.php?mod=viewthread&tid=109584
USB 1.0的最高12Mbps.
USB 2.0的高速模式480Mbps,全速模式12Mbps,低速模式1.5Mbps
USB 2.0的高速模式480Mbps,全速模式12Mbps,低速模式1.5Mbps
而是設置STM32端的USART的波特率。PC與STM32傳輸速度是以USB1.1的理論速度傳輸的,是不能設置的。
接收到數據,置NAK->將緩沖區數據拷貝到用戶區(用戶處理過程)->發ACK通知主機完成了完整的接收可以發送下一個->主機發送下一個,
.
前天測試自己編寫的USB驅動程序時候發現從主機到STM32的OUT傳輸(主機到設備)速率竟然只有最高33KB/S,實在是暈死了。經過研究后發現是
驅動程序中設置的PIPE MaxTransferSize參數的關系,原先設置64只能33KB/S,后參考其他USB設備驅動程序的值,設置成了65535,再測試USB OUT的速度,達到了500KB/S,終於解決了驅動程序的瓶頸。不過算下USB 2.0全速的通訊速率是12Mb/S,排除掉CRC、令牌、SOF等等開銷怎么也應該不止最大500KB/S啊。到網上看了看,基本上應該能達到 600KB/S~700KB/S以上,我現在的速度應該還有很大的提升才是。
看看程序,發現
void EP3_OUT_Callback(void)//EP3 OUT的回調函數,當EP3接收到數據時候中斷調用該函數
{
count_out = GetEPRxCount(ENDP3);//獲得接收到的數據長度
PMAToUserBufferCopy(buffer_out, ENDP3_RXADDR, count_out);//將數據從USB EP3 RX的緩沖區拷貝到用戶指定的數組中
SetEPRxValid(ENDP3); //完成拷貝后置有效狀態,從而EP3發送ACK主機可以進行下一個數據包的發送
}
試着將PMAToUserBufferCopy這句注釋掉(這樣STM32就不處理接收到的數據了)后再測試速度,驚奇地發現速度竟然達到了 997KB/S!晚上仔細想了想,數據肯定是要使用的,這個數據拷貝的過程的時間消費總是少不了的;由於通常情況下USB設備BULK數據接收的步驟就 是:接收到數據, 置NAK->將緩沖區數據拷貝到用戶區(用戶處理過程)->發ACK通知主機完成了完整的接收可以發送下一個->主機 發送下一個,按照以上的步驟USB接收一步步的進行,只要STM32不完成數據處理,狀態就一直是NAK,主機就會不停地發送該數據包,浪費了帶寬,因此 就會導致我上面最大速度500KB/S難以再增加的情況!不甘心啊~~
昨天晚上又仔細研究了STM32的技術參考手冊的USB章節內容,里面提到BULK可以采用雙緩沖機制(PING-PONG)進行處理,正好可以解決上面 的情況。雙緩沖機制的原理就是分配2塊接收緩沖,STM32的用戶處理和USB接口可以分別交替占用2個緩沖區,當USB端點接收數據寫其中一個緩沖區的 時候,用戶的應用程序可以同時處理另一個緩沖區,這樣緩沖區依次交換占有者,只要用戶處理程序在USB端點接收的時間片段內完成處理,就能夠完全不影響 USB的通訊速度!
程序部分修改
一、EP3_OUT的設置修改,
//ZYP:修改EP3為BULK雙緩沖方式-------------------------
SetEPType(ENDP3, EP_BULK);
SetEPDoubleBuff(ENDP3);
SetEPDblBuffAddr(ENDP3, ENDP3_BUF0Addr, ENDP3_BUF1Addr);
SetEPDblBuffCount(ENDP3, EP_DBUF_OUT, VIRTUAL_COM_PORT_DATA_SIZE);
ClearDTOG_RX(ENDP3);
ClearDTOG_TX(ENDP3);
ToggleDTOG_TX(ENDP3);
SetEPRxStatus(ENDP3, EP_RX_VALID);
SetEPTxStatus(ENDP3, EP_TX_DIS);
//------------------------------------------------------
二、EP3_OUT回調函數的修改
void EP3_OUT_Callback(void)
{
//ZYP:以下是修改成EP3雙緩沖OUT后的處理函數
if (GetENDPOINT(ENDP3) & EP_DTOG_TX)//先判斷本次接收到的數據是放在哪塊緩沖區的
{
FreeUserBuffer(ENDP3, EP_DBUF_OUT); //先釋放用戶對緩沖區的占有,這樣的話USB的下一個接收過程可以立刻進行,用另一塊緩沖區,同時用戶並行進行下面處理,在另一塊接收完之前,處理完用戶數據就行,否則緩沖區競爭。
count_out = GetEPDblBuf0Count(ENDP3);//讀取接收到的字節數,
PMAToUserBufferCopy(buffer_out, ENDP3_BUF0Addr, count_out);
}
else
{
FreeUserBuffer(ENDP3, EP_DBUF_OUT);
count_out = GetEPDblBuf1Count(ENDP3);
PMAToUserBufferCopy(buffer_out, ENDP3_BUF1Addr, count_out);
}
}
經過上面的修改,終於解決了STM32在處理接收數據時導致主機等待的情況,用BUS HOUND軟件測試了下
看看程序,發現
void EP3_OUT_Callback(void)//EP3 OUT的回調函數,當EP3接收到數據時候中斷調用該函數
{
count_out = GetEPRxCount(ENDP3);//獲得接收到的數據長度
PMAToUserBufferCopy(buffer_out, ENDP3_RXADDR, count_out);//將數據從USB EP3 RX的緩沖區拷貝到用戶指定的數組中
SetEPRxValid(ENDP3); //完成拷貝后置有效狀態,從而EP3發送ACK主機可以進行下一個數據包的發送
}
試着將PMAToUserBufferCopy這句注釋掉(這樣STM32就不處理接收到的數據了)后再測試速度,驚奇地發現速度竟然達到了 997KB/S!晚上仔細想了想,數據肯定是要使用的,這個數據拷貝的過程的時間消費總是少不了的;由於通常情況下USB設備BULK數據接收的步驟就 是:接收到數據, 置NAK->將緩沖區數據拷貝到用戶區(用戶處理過程)->發ACK通知主機完成了完整的接收可以發送下一個->主機 發送下一個,按照以上的步驟USB接收一步步的進行,只要STM32不完成數據處理,狀態就一直是NAK,主機就會不停地發送該數據包,浪費了帶寬,因此 就會導致我上面最大速度500KB/S難以再增加的情況!不甘心啊~~
昨天晚上又仔細研究了STM32的技術參考手冊的USB章節內容,里面提到BULK可以采用雙緩沖機制(PING-PONG)進行處理,正好可以解決上面 的情況。雙緩沖機制的原理就是分配2塊接收緩沖,STM32的用戶處理和USB接口可以分別交替占用2個緩沖區,當USB端點接收數據寫其中一個緩沖區的 時候,用戶的應用程序可以同時處理另一個緩沖區,這樣緩沖區依次交換占有者,只要用戶處理程序在USB端點接收的時間片段內完成處理,就能夠完全不影響 USB的通訊速度!
程序部分修改
一、EP3_OUT的設置修改,
//ZYP:修改EP3為BULK雙緩沖方式-------------------------
SetEPType(ENDP3, EP_BULK);
SetEPDoubleBuff(ENDP3);
SetEPDblBuffAddr(ENDP3, ENDP3_BUF0Addr, ENDP3_BUF1Addr);
SetEPDblBuffCount(ENDP3, EP_DBUF_OUT, VIRTUAL_COM_PORT_DATA_SIZE);
ClearDTOG_RX(ENDP3);
ClearDTOG_TX(ENDP3);
ToggleDTOG_TX(ENDP3);
SetEPRxStatus(ENDP3, EP_RX_VALID);
SetEPTxStatus(ENDP3, EP_TX_DIS);
//------------------------------------------------------
二、EP3_OUT回調函數的修改
void EP3_OUT_Callback(void)
{
//ZYP:以下是修改成EP3雙緩沖OUT后的處理函數
if (GetENDPOINT(ENDP3) & EP_DTOG_TX)//先判斷本次接收到的數據是放在哪塊緩沖區的
{
FreeUserBuffer(ENDP3, EP_DBUF_OUT); //先釋放用戶對緩沖區的占有,這樣的話USB的下一個接收過程可以立刻進行,用另一塊緩沖區,同時用戶並行進行下面處理,在另一塊接收完之前,處理完用戶數據就行,否則緩沖區競爭。
count_out = GetEPDblBuf0Count(ENDP3);//讀取接收到的字節數,
PMAToUserBufferCopy(buffer_out, ENDP3_BUF0Addr, count_out);
}
else
{
FreeUserBuffer(ENDP3, EP_DBUF_OUT);
count_out = GetEPDblBuf1Count(ENDP3);
PMAToUserBufferCopy(buffer_out, ENDP3_BUF1Addr, count_out);
}
}
經過上面的修改,終於解決了STM32在處理接收數據時導致主機等待的情況,用BUS HOUND軟件測試了下
把這句話放在拷貝函數的前面的話就真正把雙緩沖PING-PONG機制用起來了。大致算了下 PMAToUserBufferCopy(buffer_out, ENDP3_BUF1Addr, count_out);這句話當count_out為最大值64的時候STM32執行需要302個周期,72MHZ情況下約4.2微秒執行時間,而USB 傳輸按照12Mb/s的線速度傳輸64字節的數據至少也得40微秒,因此只要PMAToUserBufferCopy的時間不超過40微秒,就不會導致緩 沖區競爭的情況。