After the stm32 USB program changes bulk EP to a dual-buffer mechanism, the speed of receiving out data is increased from kb/s.
When I tested my own USB driver the day before yesterday, I found that the out transmission rate from the host to the stm32 (from the host to the device) was only kb/s, and it was truly dizzy. After research, we found that it is the relationship between the pipe maxtransfersize parameter set in the driver. Originally, we set 64 to only 65535 kb/s, and set it to according to the driver values of other USB devices, test the USB out speed, reaching kb/s, and finally solved the bottleneck of the driver. However, the communication rate of USB 2.0 at full speed is 12 Mb/s. How can we eliminate the CRC, Token, Sof, and other overhead by more than kb/s. After checking on the Internet, it should basically be kb/s ~ At a speed above kb/s, I should be able to greatly improve my current speed.
Look at the program and find
Void ep3_out_callback (void) // calls the callback function of EP3 out when EP3 receives data.
{
Count_out = geteprxcount (endp3); // obtain the length of received data
Pmatouserbuffercopy (buffer_out, endp3_rxaddr, count_out); // copy data from the buffer zone of USB EP3 RX to the array specified by the user.
Seteprxvalid (endp3); // The valid status after the copy is completed, so that EP3 can send the ACK Host to send the next packet
}
Try to comment out the pmatouserbuffercopy sentence (so that the stm32 will not process the received data) and then test the speed, surprised to find that the speed has reached kb/s! After thinking carefully at night, the data must be used. The time consumed during the data copying process is always indispensable. Generally, the bulk data receiving process of the USB device is as follows: after receiving the data, set Nak to copy the buffer data to the user zone (User processing process) to send an ACK notification to the host to complete the reception and send the next one, according to the above steps, USB reception is performed step by step. As long as stm32 does not complete data processing, the status will always be Nak, and the host will continuously send this data packet, wasting bandwidth, so it will make it difficult for me to increase the maximum speed by kb/s! Unwilling to do so ~~
Last night, I carefully studied the USB content in the stm32 Technical Reference Manual, which mentioned that bulk can use the dual BUFFER MECHANISM (Ping-Pong) for processing, which can solve the problem above. The principle of the dual-buffer mechanism is to allocate two receiving buffers. The user processing of stm32 and the USB interface can use two buffers alternately. When the USB endpoint receives data and writes one of the buffers, the user's application can process another buffer at the same time, so that the buffer is exchanged in turn, as long as the user's processing program completes processing within the time segment received by the USB endpoint, the USB communication speed will not be affected at all!
Program modification
1. Modify the settings of ep3_out,
// Zyp: Change EP3 to the bulk dual-buffer mode -------------------------
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 );
//------------------------------------------------------
Ii. Modify the ep3_out callback function
Void ep3_out_callback (void)
{
// Zyp: The following is the processing function modified to EP3 Double Buffer out.
If (getendpoint (endp3) & ep_dtog_tx) // first determine the buffer zone in which the received data is stored.
{
Freeuserbuffer (endp3, ep_dbuf_out); // first releases the user's possession of the buffer. In this way, the next USB receiving process can be performed immediately, and the user performs the following processing in parallel.
Count_out = getepdblbuf0count (endp3); // read the number of received bytes
Pmatouserbuffercopy (buffer_out, endp3_buf0addr, count_out );
}
Else
{
Freeuserbuffer (endp3, ep_dbuf_out );
Count_out = getepdblbuf1count (endp3 );
Pmatouserbuffercopy (buffer_out, endp3_buf1addr, count_out );
}
}
After the above modification, the system finally solved the host waiting problem caused by stm32 processing the received data, and tested it with the bus hound software.
Haha, this is finally a great deal.
Ourdev_200932.gif (35 KB)
PS: freeuserbuffer (endp3, ep_dbuf_out) above; the upper and lower positions of this sentence are the key. If it is placed behind the function, the host will still wait for the stm32 to process data, the speed is still 500kb/s!
If we put this sentence before the copy function, we will actually use the dual-buffer ping-pong mechanism. Calculate pmatouserbuffercopy (buffer_out, endp3_buf1addr, count_out). In this case, when count_out is the maximum value of 64, 302 cycles are required for stm32 execution. In 72 MHz, the execution time is about 4.2 microseconds, USB transmission transmits 64 bytes of data at a speed of 12 Mb/s at least 40 microseconds. Therefore, as long as the pmatouserbuffercopy time does not exceed 40 microseconds, it will not lead to competition in the buffer zone.
This article from the csdn blog, reproduced please indicate the source: http://blog.csdn.net/xjmeng001/archive/2010/03/16/5385304.aspx