Hi,
I'm trying to send some data from my usb device to the host by a virtual com port CDC. Is it the only solution to write these data to the endpoint(in) in the SOF ISR? Sending data to the usb device from the host is working.
#if USB_SOF_EVENT void USB_SOF_Event (void) { USB_WriteEP( USB_ENDPOINT_IN(2), &TestData[0], 64 ); // send 64 bytes data }
Has someone a small example (using two CDCs)? With the code above, the SOF interrupts occurs only 4x times after enabling the com port on the host. After that no further SOF will be generated. Using Readfile() returns true - but there's definitely no traffic on the usb bus.
best regards Jan
Make sure that you send back data to the host via "void CDC_BulkIn(void)" - your device is still the slave. This function is the handler for cases when the host asks for data ("void CDC_BulkOut(void)" handles data coming from the host). You don't need to split the data. Be aware of your stack space - 512 bytes might be too big and could crash your program. Use a static/global/dynamically allocated buffer instead.
I've just checked in my own software - it seems that I have made sure that not more than 64 bytes are sent back. It might depend on the maximum size of your USB hardware buffer!
thanks for your reply:
if you send only 64Byte data packets - how is it possible to see if the host has already read the data from the endpoint(in) so that I can add the second 64byte data pkt?
it seems that the FE bit will be the right one to use, but my programm hangs (waiting for the CDFULL_INT bit) on the while loop...
uint32_t RdCmdDat (uint32_t cmd) { LPC_USB->USBDevIntClr = CCEMTY_INT | CDFULL_INT; LPC_USB->USBCmdCode = cmd; while ((LPC_USB->USBDevIntSt & CDFULL_INT) == 0); //<- the programm hang return (LPC_USB->USBCmdData); } void CDC_BulkIn(void) { RdCmdDat( CMD_SEL_EP(EPAdr(0x82)) ); if ( CMD_DATA & EP_SEL_F == 0 ) return; USB_WriteEP(); }
ok, it seems to work, using Readfile.
I transmit 8x 64byte packets and a ZLP packet - using a usb traffic programm, I can see that the 512bytes will be transmitted to the host 4x times.... not only one time????
If I use the Readfile command a few times, there will be only one 512byte tx pkt seen in the usb traffic prog.... Do you have any explanation for this behaviour?
> using a usb traffic programm, I can see that the 512bytes will be transmitted to the host 4x times.... > not only one time????
You are monitoring USB traffic on a software sniffer, not on a hardware analyzer. Then, it's usual. Software sniffer displays a log line, - when a request is passed to a lower-driver on the driver stack, - and when the request complets, reply comes back. Also, it displays these log lines for each driver on the stack. In this way, you'll see multiple lines for single transfer.
> it seems that the FE bit will be the right one to use
You don't need to poll FE bit. Use endpoint interrupt (USB Endpoint Event Callback, usbuser.c, in Keil term) for the second and later packets, instead.
Tsuneo
alright thanks for your explanation. In my routine I've figured out one problem: only every second pkt will be transmitted to the host... Has it something to do with using double buffers? Also the time between two 512byte packet transfers is too large - round about 60ms. The refresh-rate is 40ms from the incoming data packets (usart).
I've installed a ring buffer, consisting of seven buffers and these buffers will contain every value from 1 to 100.
Usually, your firmware doesn't need to be aware of the double buffer on the endpoint.
However, if you want to use the double buffer more effectively, fill the EP buffer using USB_WriteEP() until FE bit (Select Endpoint command) raises, at the start of block transfer. In this way, two packets are put to the double buffer, sequentially. Third and later packets are filled in the Endpoint Callback, USB_EndPointN(), usbuser.c, one packet by one.
512 bytes transfer on CDC bulk IN EP should be terminated by ZLP (Zero-Length Packet). CDC bulk IN transfer requires ZLP termination when the transfer size is just the multiple of wMaxPacketSize of the EP (64 bytes). On the PC side, host controller doesn't pass received data to the class driver, until it sees short packet (including ZLP).
If your PC application uses SerialPort class - DataReceived event, or MSCOMM - OnComm event, you may see significant delay on the PC class driver (usbser.sys). An extra ZLP after each transfer may speed up the process on the class driver.