Hi all, I am using LPC2148 microcontroller. Bulk driver for usb2.0 full speed is written. Currently only 64 bytes of data is written to the endpoint. So the speed achieved is less. I have read in the books that maximum 19 packets of 64 byte length can be transmitted in 1ms frame. How can i increase the speed of bulk transfer.
When you have large data on a buffer, more than 64 bytes, you may see greater transfer speed.
The firmware declares these global variables, - a transfer buffer - data size on the buffer - index on the buffer - a occupied flag
data size, index and flag are initialized in Set_Configuration request handler
In the ISR of the bulk IN EP, 1) If occupied flag drops, return 2) Call Select Endpoint command of the protocol engine, and get F/E bit of the bulk IN EP 3) If F/E bit is 0 (next buffer is empty), - pass next packet from the index on the buffer to the IN endpoint - The packet size is the smaller one, data size or 64 bytes else return 4) Increase index by this packet size, decrease data size by this packet size 5) If data size is 0, drop occupied flag and return else back to 2)
Outside of the ISR, firmware starts transfer, when occupied flag drops. 1) Fill data to the buffer, set data size 2) Clear the index and raise the occupied flag 3) Force bulk EP interrupt by USBEpIntSet register
In this way, your firmware uses the double buffer effectively, and gets top speed.
Tsuneo
My present code for writing to the endpoint is as follows. This is called in the ISR routine Maximum packet size is 64. So v_Count_u32r = 64
static U32 USB_WriteEP (U32 EPNum, U8 *P_PointerToData_U8R, U32 v_Count_u32r) { U32 v_Temp_u32r; U32 v_NumberOfPacks_u32r = ((v_Count_u32r + 3) >>2); USBCtrl = ((EPNum & 0x0F) << 2) | C_USBCntrlWREnbl_U32X; USBTxPLen = v_Count_u32r; for (v_Temp_u32r = 0; v_Temp_u32r < v_NumberOfPacks_u32r; v_Temp_u32r++) { USBTxData = *((__packed U32 *)P_PointerToData_U8R); P_PointerToData_U8R += 4; } USBCtrl = 0; USB_WriteCmnd(Z_CmndSelEP(USB_EPAddr(EPNum))); USB_WriteCmnd(C_CmndValidBuff_U32X); return (v_Count_u32r); }
Only 64 bytes is transmitted in one interrupt cycle. Suppose i need to sent 128 bytes i read in the LPC2148 data sheet that <bold>then the software submits 64 bytes packet twice</bold>. I modified my code as follows. Values are hard coded and only for testing purpose.
static U32 USB_WriteEP (U32 EPNum, U8 *P_PointerToData_U8R, U32 v_Count_u32r) { U32 v_Temp_u32r,i; U32 v_NumberOfPacks_u32r; if(v_Count_u32r > 64) { for(i=0;i<2;i++) { USBCtrl = ((EPNum & 0x0F) << 2) | C_USBCntrlWREnbl_U32X; v_NumberOfPacks_u32r = ((64 + 3) >>2); USBTxPLen = 64; for (v_Temp_u32r = 0; v_Temp_u32r < v_NumberOfPacks_u32r; v_Temp_u32r++) { USBTxData = *((__packed U32 *)P_PointerToData_U8R); P_PointerToData_U8R += 4; } USBCtrl = 0; USB_WriteCmnd(Z_CmndSelEP(USB_EPAddr(EPNum))); USB_WriteCmnd(C_CmndValidBuff_U32X); while ((USBDevIntSt & C_TxEndPktInt_U32X) == C_Zero_U8X); } } else { USBCtrl = ((EPNum & 0x0F) << 2) | C_USBCntrlWREnbl_U32X; v_NumberOfPacks_u32r = ((v_Count_u32r + 3) >>2); USBTxPLen = v_Count_u32r; for (v_Temp_u32r = 0; v_Temp_u32r < v_NumberOfPacks_u32r; v_Temp_u32r++) { USBTxData = *((__packed U32 *)P_PointerToData_U8R); P_PointerToData_U8R += 4; } } USBCtrl = 0; USB_WriteCmnd(Z_CmndSelEP(USB_EPAddr(EPNum))); USB_WriteCmnd(C_CmndValidBuff_U32X); return (v_Count_u32r); }
I could find that the first 64 bytes of data over written by last 64 bytes. If the EP buffer size is sufficient i dont think this will happen. I could write only maximum packet size to USBTxPLen.I have read that 19 packet of 64 byte length can be transmitted. Can u suggest me some improvement in this regards to write more data?
> I could find that the first 64 bytes of data over written by last 64 bytes.
In this line, you are waiting for the end of Validate command, before writing next packet.
while ((USBDevIntSt & C_TxEndPktInt_U32X) == C_Zero_U8X);
What is the value of C_TxEndPktInt_U32X and C_Zero_U8X? Are they CCEMPTY bit (0x10) and 0?
Clear CCEMPTY bit before putting Validate command.
Otherwise, this bit is kept in 1 by the Select Endpoint command, just before the Validate command. And then, your while loop will be passed through immediately.
Ah, I remember. USBDevIntSt is read-only. To clear USBDevIntSt, write to USBDevIntClr. Troublesome SIE :-)
USBDevIntSt register bit "TxENDPKT" will be set if The number of data bytes transferred to the FIFO equals the number of bytes programmed in the TxPacket length register.That was what i was checking. Is it a proper way to send multiple packets in a single frame of 1ms? Or else please suggest me the procedure to sent multiple packets in a frame in bulk transfer so that i can utilize full bandwidth?
USBDevIntSt.TxENDPKT is available while the packet is passed to USBTxData register, after USBTxPLen register is set. I'm not sure this bit is still available after SelectEndpoint / Validate commands are issued. Even if this bit would be available, it could be nothing after Validate command.
Rewrite your code as I suggested.
Hi Tsueno, Now the problem is solved. We where using jungo driver in the host side. With that speed of 32kbytes/s was only achieved.We evaluated the same firmware in the device side with Thesycon host driver. We could achieve a speed of 720kbytes/s.
> We could achieve a speed of 720kbytes/s.
Not enough. You may saturates the bus, if no other device hooks on the bus. 19 full-size packets/frame = 1,216,000 bytes/s
a) How many bytes do you request for read/write call on the host side? In both directions, transfer speed is proportional to the size of single read/write call, until bus bandwidth saturates. Test it at least a couple of 10KBytes. Even MegaBytes will do.
b) On the device side, did you implement double buffer scheme on my first post?
> Thesycon
Surely, Thesycon supplies easy DLL for their driver. But, isn't WinUSB enough?
Hello Tsuneo Can u suggest me some tool to check the USB throughput.?
To evaluate firmware performance, I observe device response on a hardware bus analyzer. When any IN-NAK or OUT-DATA-NAK transaction appears in large data transfer, tuning on the bulk endpoint routine may improve the performance.
Recent quad-core PCs can drive the bus with 19 full-size packets per frame. But on dual-core generation, 18 packets, at most.
How often the host sends IN token to the device in the case of bulk transfer. In interrupt transfer it will be the interval mentioned in the endpoint descriptor. But for bulk its not clear for me. can u help me in this regards.