2010-08-23 12:46 AM
Testing STM32 FS USB Library Performance
2011-05-17 05:03 AM
IIRC bulk endpoints can send up to 1024 bytes per transaction.
2011-05-17 05:03 AM
With your test as it stands, you are testing the latency of Windows USB transfers, not the performance of the library.
On the other hand, if you application is only ever sending and receiving 64 bytes at a time then your results are approximately what you will achieve. You might want to send/receive 64k bytes at a time to get a better indication of performance.2011-05-17 05:03 AM
Perhaps you are thinking of isoch.
Full speed bulk is 8,16,32,64 bytes High speed (N/A for STM32) is 512 bytes Full speed isoch 1023 High speed iscoh 10242011-05-17 05:03 AM
Hi,
Using Bulk transfers, you can reach the maximum of the USB specs of 2.0 Full speed transfers on STM32F102/3 i-e ( above 1Mbytes/s), you will be limited of course by the Windows Driver transactions. my recommendation is to use the largest buffer on windows API : 64Kbytes is a best fit. However if you have a loop-back example, for sure the OUT and IN endpoints will share the total of 1Mbytes/s therefore we will be able to have 512Kbytes on each endpoint in parallel. You can send me a private e-mail to moderator . I will send you an example. Cheers, STOne-2011-05-17 05:03 AM
OK, I am out of ideas now... I cant seem to get data to transfer device to PC fast!
It seems that the IN endpoint callback functions are never hit (bulk or interrupt). I read that the host should initiate IN transfers, so I call winUSBs readpipe(), but the IN endpoint callback is never hit... How do I know when to put data in the tx buffer???
I am astounded that ST thought it was acceptable to provide so little documentation on this library and how to use it (there is 4 lines on bulk endpoints!). The examples are good but I think incomplete as far as use of IN endpoints.
Can someone please please please tell me exactly how to do this:
Send data to the PC at a rate of at least 100 kb/s. I want to be able to send all frames on the CAN bus to the PC. Thats all!!!
2011-05-17 05:03 AM
So, the other night I changed my OUT endpoint to double buffered and made it so that data is read and discarded (so no delays processing data). I then changed my writes to various sizes and recorded the number of possible writes over a ten second period. Here is the results I got:
// Tested on USB 1 and USB 3
// write size (bytes) = data rate
// 16384 = 547 kb/s
// 8192 = 512 kb/s
// 4096 = 456 kb/s
// 2048 = 409 kb/s
// 1024 = 340 kb/s - < 500 writes per second
// 512 = 256 kb/s - 500 writes per second
// 256 = 127 kb/s
// 128 = 64 kb/s
// 64 = 32 kb/s
// 32 = 16 kb/s
// 16 = 8 kb/s
// 8 = 4 kb/s
// 4 = 2 kb/s
// 2 = 1 kb/s
// 1 = 0.5 kb/s
I found that it is not possible to achieve more than 500 writes per second using the WinUSB WritePipe() function. I achieved a maximum of 547 kb/s and probably could have got more if I went up to 32k or 64k packets but the performance seemed to be tapering off. I need around 100kb/s + some safety room so I will try go for 1kb writes.
Now I need to work out how to increase the performance of the IN endpoint. I want to achieve over 100 kb/s in that direction too. So, I can easily buffer up to 1kb of data in the micro, but I am unsure how to send it so that it goes out as lots of consecutive frames rather than individual 6f b frames.
This is what I will try: Make the IN endpoint double buffered too. Buffer 1k of test data in the micro, then send it repeatedly on the in endpoint. I will call WinUSBs ReadPipe() asking to read 1k and then see what happens.
But, I am not sure if I need an interrupt pipe or wether a normal bulk IN pipe will do. My device should send data without being asked for it so I guess a 2ms interrupt endpoint would be OK???
Any help appreciated...
2011-05-17 05:03 AM
OK, so I am making some progress...
By putting the following code in my main loop, I am able to obtain the data rates of 570 k to device using 64k writepipe() calls and 819.2k from device using 64k readpipe() calls.
So, I can easily get the data rates that I want. So, now I just need a bit of help with making sure I am using the TX and RX double buffering effectively. I have the funny feeling that the code below only ever actually fills one buffer repeatedly...
while (1)
{
if(pInformation->Current_Configuration != 0)
{
uint16_t status = GetEPTxStatus(ENDP1);
if(status == EP_TX_NAK)
{
if(GetENDPOINT(ENDP1) & EP_DTOG_RX) // Use EP_DTOG_RX flas as is actually SW_BUF flag. Refer ref manual page 589-590
{
UserToPMABufferCopy(crap, ENDP1_TXADDR1, 64);
SetEPDblBuf1Count(ENDP1, EP_DBUF_IN, 64);
FreeUserBuffer(ENDP1, EP_DBUF_IN); // Toggle SW_BUF (ie toggle DTOG_RX for IN endpoint)
}
else
{
UserToPMABufferCopy(crap, ENDP1_TXADDR0, 64);
SetEPDblBuf0Count(ENDP1, EP_DBUF_IN, 64);
FreeUserBuffer(ENDP1, EP_DBUF_IN);
}
SetEPTxValid(ENDP1);
}
}
2011-05-17 05:03 AM
Sorry to keep posting!!!
So, I am slowly making progress. I have the following code. I am struggling a little with initiating a PC read. If I only have the endpoint callback code then the pc readpipe blocks forever. If I get the transfer started in the main function, then the endpoint callback starts to work and the readpipe function returns. But, the data is abcdefg... I thought the first 64 bytes of data should be 012345.... then abcdef after the first 64 bytes. the first buffer was filled by main with numbers! This is frustrating and confusing but I am slowly getting there!!!
uint8_t Transmit_Buffer[64] = ''abcdefghijklmnopqrstuvwxyz/0aabbccddeeffgghhiijjkkllmmnnooppqqrr'';
void EP1_IN_Callback(void)
{
if(GetENDPOINT(ENDP1) & EP_DTOG_RX) // Use EP_DTOG_RX flas as is actually SW_BUF flag. Refer ref manual page 589-590
{
UserToPMABufferCopy(Transmit_Buffer, ENDP1_TXADDR1, 64);
SetEPDblBuf1Count(ENDP1, EP_DBUF_IN, 64);
FreeUserBuffer(ENDP1, EP_DBUF_IN); // Toggle SW_BUF (ie toggle DTOG_RX for IN endpoint)
}
else
{
UserToPMABufferCopy(Transmit_Buffer, ENDP1_TXADDR0, 64);
SetEPDblBuf0Count(ENDP1, EP_DBUF_IN, 64);
FreeUserBuffer(ENDP1, EP_DBUF_IN);
}
SetEPTxValid(ENDP1);
}
int main(void)
{
int started = 0;
Set_System();
// Init USB
USB_Interrupts_Config();
Set_USBClock();
USB_Init();
for(int i = 0; i < 64; i++)
{
crap[i] = i;
}
while (1)
{
if(pInformation->Current_Configuration != 0 && !started)
{
uint16_t status = GetEPTxStatus(ENDP1);
if(status == EP_TX_NAK)
{
if(GetENDPOINT(ENDP1) & EP_DTOG_RX) // Use EP_DTOG_RX flas as is actually SW_BUF flag. Refer ref manual page 589-590
{
UserToPMABufferCopy(crap, ENDP1_TXADDR1, 64);
SetEPDblBuf1Count(ENDP1, EP_DBUF_IN, 64);
FreeUserBuffer(ENDP1, EP_DBUF_IN); // Toggle SW_BUF (ie toggle DTOG_RX for IN endpoint)
}
else
{
// UserToPMABufferCopy(crap, ENDP1_TXADDR0, 64);
// SetEPDblBuf0Count(ENDP1, EP_DBUF_IN, 64);
// FreeUserBuffer(ENDP1, EP_DBUF_IN);
}
SetEPTxValid(ENDP1);
started = 1;
}
}
else
{
int fuck = 5;
}
}
2011-05-17 05:03 AM
Hi all,
I'm facing the same problem. Transfer rate from the HOST PC to the SDCard is very low! For the moment I'm using the Mass Storage project provided for the STM3210E-EVAL available with the USB library. Do you have a working example using at least the bulk double buffer? thanks