LPC17xx packet over-written bit?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPC17xx packet over-written bit?

704 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by doogul on Wed Jul 08 18:53:30 MST 2015
Hi there,

I've been working on my own USB device stack for the LPC1768. I'm making good progress on implementing all of the control transfers for EP0 (my device enumerates successfully on Windows), but one place in the register documentation has me confused.

In UM10360, section 11.12.13, there is an interesting comment in the "Clear Buffer" SIE command description about the returned data byte from the command:


Quote:
When bit 0 of the optional data byte is 1, the previously received packet was over-written by a SETUP packet. The Packet over-written bit is used only in control transfers. According to the USB specification, a SETUP packet should be accepted irrespective of the buffer status. The software should always check the status of the PO bit after reading the SETUP data. If it is set then it should discard the previously read data, clear the PO bit by issuing a Select Endpoint/Clear Interrupt command, read the new SETUP data and again check the status of the PO bit.



This appears to be for handling a minor edge case where an existing control transfer is canceled because a new SETUP packet for a new control transfer arrived before I was finished with the first one.

My USB EP_SLOW interrupt handler always writes a 1 to the corresponding USBEpIntClr bit before it even starts reading the received packet data. It seems like if the PO bit had been set, it would already be cleared before I even did the clear buffer command that would read it out. During normal operation, am I supposed to be waiting until after I read the endpoint data and clear the buffer before I clear the endpoint interrupt? If I see the PO bit in the "clear buffer" result byte, am I supposed to write a 1 to the corresponding USBEpIntClr bit *again*, and then immediately try to read the SETUP packet data from the endpoint again without waiting for the EP_SLOW interrupt to fire again, or should I just exit and hope that another EP_SLOW interrupt comes in for the "replacement" setup packet?

The instructions in the datasheet don't provide a lot of clarity about the exact sequence of events. I don't understand exactly what I'm supposed to do when this happens. It's hard to test because I'm not sure I can get my computer to send such a sequence of packets. None of the example USB stacks for the LPC1768 that I've inspected look at the PO bit at all. I've done a ton of Googling and it appears that nobody ever talks about what to do in this case. Does anyone have any better details on exactly what I'm supposed to do, and/or how to test this particular sequence of packets?

Thanks for any insight!
Labels (1)
0 Kudos
1 Reply

666 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by doogul on Sat Jul 11 12:33:43 MST 2015
Well, I did some more testing this morning and I think I can answer my own question. In case this helps anyone else in the future:

The overwrite bit gets set if I don't read the OUT data from EP0 in time before a new SETUP packet comes in. When I finally get around to reading what I thought was EP0 OUT data, it actually contains the new SETUP packet's data. Now I understand why the PO bit is there -- it's telling me that the EP0 OUT data I just read is invalid, and to abort the current control transfer because a new one is beginning. I was able to test it by adding an artificial delay before reading OUT packets in my LPC1768 program, and writing a program on my host computer with libusb to do a couple of control transfers (with the first control transfer having a timeout shorter than the artificial delay in my LPC1768 program).

Here's what my code does now with the PO bit:

[list]
  [*]EP_SLOW interrupt comes in.
  [*]Check each endpoint in the USBEpIntSt register. If its bit is set, write a 1 to the corresponding bit in the USBEpIntClr register. Read the status byte back after the USBEpIntClr write to determine the difference between SETUP/OUT.
  [*]If it's an OUT or SETUP packet, read the packet, and read the status byte from the "clear buffer" command when I'm done.
  [*]If the PO bit is set in the status byte, it means the OUT or SETUP data I just read is garbage, so throw it out and abort the current control transfer (if any).
  [*]Don't do anything special at this point. A new EP_SLOW interrupt for the new SETUP packet will come in, and these steps can repeat. The write to USBEpIntClr in the next interrupt will clear the PO bit before I try to read it again.
[/list]

I have seen the bit get set in STATUS OUT reads when connected to a Mac OS X host machine, but I don't think there's anything special to do in that case -- it just means that a new setup packet came in immediately after the STATUS OUT reply, and I didn't read the zero-length STATUS OUT reply in time (no big deal, I think).

BTW, with this scheme, you should *not* immediately write to USBEpIntClr as the datasheet advises; this causes the interrupt for the new SETUP packet to be cleared, so you don't get notified about it. If you *do* write immediately to USBEpIntClr to clear the PO bit, then you also need to immediately act as though a new packet has arrived and read it out, as implied by the datasheet. My software wasn't organized in a way to make that particular sequence easy to implement, so I left it for the next interrupt to handle instead. Seems to work OK in my testing.
0 Kudos