We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hi there,
let's have a slow memory which is interfaced to the USB (as a MSC) via an ARM7 (LPC23xx). If I understood the MSC correctly, then:
1) when the host issues CBW to "out" the desired data block - the device must get the data from the bulk endpoint, - write it to the memory - respond with the CSW
2) when the host issues CBW to "in" the desired data block - the device must read the data from the memory, - write it to the bulk enpoint - respond with the CSW
So whole transactions are blocking. Unfortunately our memory is slow, so we can't dare to wait for read/write completion in the endpoint's interrupt service and have to split the operation somehow:
For the "in" operation, the device automagically NACKs the host's repeated "in" requests until the endpoint is filled with (part of) requested data (upon slow memory read completion). After all block data is subsequently put to the endpoint, the device can finally send the CSW.
For the "out" operation, the device subsequently reads the (parts of) data block to be written. When data block is complete the slow memory write is started. After the write is completed the device can finally send the CSW.
Does this make sense? Would it work if we consider the slow memory is quick enough to fit within the USB timeouts?
Thanks for opinions.
Regards Pavel
> For the "out" operation, the device subsequently reads the (parts of) data block to be written. When data block is complete the slow memory write is started.
The firmware can be NAKing the bulk OUT endpoint, too. To read out a packet from the bulk endpoint, USB_ReadEP() is used. After reading out the endpoint buffer, USB_ReadEP() clears the buffer using these protocol engine commands.
WrCmd(CMD_SEL_EP(EPAdr(EPNum))); // select endpoint WrCmd(CMD_CLR_BUF); // clear buffer
Don't clear the endpoint buffer, until the firmware finishes to write the packet contents to the slow memory. While the buffer is occupied by the last packet, the endpoint returns NAK to the host OUT transactions. Actually, the double buffer takes one more packet, but this simplified explanation works as you intend.
Tsuneo
Tsuneo,
thanks for info.
Looks like it works as expected. Some sort of buffering seems like the "must feature". The memory (together with the driver SW) takes 7-15 NAKs to read and 12-40 ones to write 512 bytes (on 2.0 full speed). I expected the low performance, but not so much ;)
I would like to ask you - as the skilled USB expert - for more details about following thing:
I have added some buffering stuff, so the host gets some NAKs only at the very beginning of the SCSI READ(10) command. Then each further IN token is serviced immediately as it arrives.
Being very optimistic I would believe the design could perform faster (currently the read speed is about 670kB/sec), but seems like the host is the slow side now. It sends the IN tokens approximately every 100 us (and I can provide maximally 64 Bytes of data).
Is there any well known method the host (OS? => WinXP) determines/chooses the interval? Can I alter it in any way? Didn't I catch anything important? I would rather see some NAKs indicating the design is overloaded than "lazy IN tokening" from the host side;)
Thank for any info.