Hi Dave
Please could you try with the latest development USB driver here:
http://www.uTasker.com/software/V1.4/uTaskerUSB_Driver_24-3-2010.zipThe files
usb_drv.c and
usb.h can be replaced but you will in addition need to add these defines to
driver.h so that it compiles:
#define USB_ENDPOINT_TERMINATES 0x20
#define ENDPOINT_REQUEST_TYPE 3
#define ENDPOINT_CLEARED 4
#define TRANSPARENT_CALLBACK 7Furthermore, ensure that the USB and Ethernet interrupts have different interrupt level/priorities - as discussed here:
http://www.utasker.com/forum/index.php?topic=842.msg3690#msg3690Now to some explanations:
1) There are no know problems with the buffer operation itself but two cases have been identified where other interrupts can cause a buffer corruption to occur. See the two patches marked with
MJB_TEST_PROTECT_NEW_WRITE and
MJB_WAIT_UNTIL_ALL_BUFFERS_SENT.
A third define called
MJB_CATCH_ERROR catches this error by monitoring the buffer operation (this is not the actually input/output buffer used between driver and application but a ping-pong FIFO buffer used to ensure that the USB engine is fed with data to achieve decent throughput when sending). This should never occur (with the other defines set). An IN endpoint throughput of about 8MBits/s is typical.
I would hope that these resolve any transmission corruption possibilities (some intensive testing was done recently and, although not always detectable with the standard CDC operation, certain interrupts taking place in combination with burst type operation could result in some garbage transmission or the transmitter stopping further sending.
2) When data is sent via the output buffer it will be sent in packets equal to the maximum data token size until the final data block is sent. If this data block is less that the data token length (eg. 64 in most full-speed bulk cases) there is no possibility of problems. In this case the USB host recognises that the final token is the end of the 'message'. If however the final data token length happens to be equal to the maximum data token size it is not so clear - a terminal emulator will pass on the data to the terminal application and all is well, but other USB interfaces may wait for the termination of the 'message' before passing it on to the application on the PC. In the case, where the message length is equal to a multiple of the maximum data token size it can cause problems. For this reason there was a define
USB_TERMINATE_ONLY_CONTROL which could be used to define whether a zero frame is sent in this case or not (the zero frame allows the USB host to known that the complete message has been sent and so ensures that it doesn't continue waiting for more without letting the application know that data is ready). In some projects it was found to be necessary, in others it was found to be not allowed - depending on the exact USB host driver...
In this version it is possible to configure this on an IN endpoint basis. I have set it as default in the CDC configuration as follows:
{ // bulk in endpoint descriptor for the second interface
DESCRIPTOR_TYPE_ENDPOINT_LENGTH, // descriptor size in bytes (0x07)
DESCRIPTOR_TYPE_ENDPOINT, // end point descriptor (0x05)
(IN_ENDPOINT | 0x02), // direction and address of end point
(ENDPOINT_BULK | ENDPOINT_TERMINATE_TRANSMISSION), // {13} endpoint attributes (ENDPOINT_TERMINATE_TRANSMISSION is a pseudo parameter configuring the endpoint to send zero frame on transmission termination)
{LITTLE_SHORT_WORD_BYTES(64)}, // endpoint FIFO size (little-endian - 64 bytes)
0 // polling interval in ms - ignored for bulk
}This parameter is set here but is not actually sent out during enumeration, but rather used by the driver to know how it should react in the said case.
3) Note also that the output buffer is a ring buffer. This means that it doesn't actually guaranty that "messages" are sent out as groups of 64 bytes and terminated by a shorter data token (or zero terminator). If there is a wrap-around in the buffer it will result in two 'messages' being sent. This is because transmission is directly from the buffer using DMA and so the DMA setup results in two "messages" - one up to the end of the buffer and one at the start of the buffer (after the wrap-around).
This can cause problem for certain USB protocols. For example I am working on USB mass storage and this case is not acceptable since the USB host believes that the message is corrupt since it doesn't have the fixed length. In this case it is however not a reason to avoid buffered output since it is easy to manage by giving the buffer a size equal to the standard message length (or twice so that a follow-on message can be made ready for the next transmission - which is almost always 512 bytes for mass storage media). This allows multiple mass storage data blocks to be added since they are guarantied to be transmitted as single 512 byte messages.
In between message sequences (where other types are also transmitted) an
fnFlush(USBPortID_comms, FLUSH_TX); can be called to set the buffer back to the start.
Up to now I only found this to be necessary with the mass storage class operation, but, as I said, is easy to manage.
4) This version also allows
both callbacks and queues to be used for OUT bulk endpoints. This I found useful for 'peeking' at incoming commands (this occurs in the interrupt routine directly) and halting the bulk endpoint where necessary, or allowing the reception to be processed via the input queue (by the task which will be delayed slightly). Probably this is not of interest at the moment but I am playing with it during the mass storage development. What you certainly can't do with the present solution (needs also a slight modification in the HW driver, which I haven't done for Coldfire yet) is stall (halt) a bulk endpoint. This is something required by mass storage but not for the CDC - if you do find it necessary, the bulk endpoint call-back can return
STALL_ENDPOINT but you will need to request the HW level change from me, which I will try to test shortly.
Tell me if this solves your problem case.
Regards
Mark