Fix isochronous endpoints on LPC1768

Perform isochronous endpoint processing from the frame interrupt
rather than the endpoint interrupt. Isochronous endpoints to not
generate interrupts normally and are intended to be handled from
the start of frame interrupt.
pull/9768/head
Russ Butler 2018-06-06 11:02:02 -05:00
parent 2fedc706e6
commit da77f3885b
1 changed files with 34 additions and 2 deletions

View File

@ -29,6 +29,9 @@
// Convert physical endpoint number to register bit
#define EP(endpoint) (1UL<<DESC_TO_PHY(endpoint))
// Check if this is an isochronous endpoint
#define ISO_EP(endpoint) ((((endpoint) & 0xF) == 3) || (((endpoint) & 0xF) == 6) || (((endpoint) & 0xF) == 9) || (((endpoint) & 0xF) == 12))
#define DESC_TO_PHY(endpoint) ((((endpoint)&0x0F)<<1) | (((endpoint) & 0x80) ? 1:0))
#define PHY_TO_DESC(endpoint) (((endpoint)>>1)|(((endpoint)&1)?0x80:0))
@ -122,6 +125,13 @@ static USBPhyHw *instance;
static uint32_t opStarted;
static const usb_ep_t ISO_EPS[] = {
0x03, 0x83,
0x06, 0x86,
0x09, 0x89,
0x0C, 0x8C
};
static void SIECommand(uint32_t command)
{
// The command phase of a SIE transaction
@ -465,6 +475,9 @@ void USBPhyHw::disconnect(void)
// Disconnect USB device
SIEdisconnect();
// Reset all started operations
opStarted = 0;
}
void USBPhyHw::configure(void)
@ -551,7 +564,7 @@ uint32_t USBPhyHw::endpoint_read_result(usb_ep_t endpoint)
read_sizes[endpoint] = 0;
// Don't clear isochronous endpoints
if ((DESC_TO_PHY(endpoint) >> 1) % 3 || (DESC_TO_PHY(endpoint) >> 1) == 0) {
if (!ISO_EP(endpoint)) {
SIEselectEndpoint(endpoint);
SIEclearBuffer();
}
@ -692,6 +705,20 @@ void USBPhyHw::process(void)
events->sof(SIEgetFrameNumber());
// Clear interrupt status flag
LPC_USB->USBDevIntClr = FRAME;
// There is no ISO interrupt, instead a packet is transferred every SOF
for (uint32_t i = 0; i < sizeof(ISO_EPS) / sizeof(ISO_EPS[0]); i++) {
uint8_t endpoint = ISO_EPS[i];
if (opStarted & EP(endpoint)) {
opStarted &= ~EP(endpoint);
if (IN_EP(endpoint)) {
events->in(endpoint);
} else {
events->out(endpoint);
}
}
}
}
if (LPC_USB->USBDevIntSt & DEV_STAT) {
@ -717,6 +744,7 @@ void USBPhyHw::process(void)
}
memset(read_buffers, 0, sizeof(read_buffers));
memset(read_sizes, 0, sizeof(read_sizes));
opStarted = 0;
events->reset();
}
}
@ -752,12 +780,16 @@ void USBPhyHw::process(void)
}
}
//TODO - should probably process in the reverse order
for (uint8_t num = 2; num < 16 * 2; num++) {
uint8_t endpoint = PHY_TO_DESC(num);
if (LPC_USB->USBEpIntSt & EP(endpoint)) {
selectEndpointClearInterrupt(endpoint);
if (ISO_EP(endpoint)) {
// Processing for ISO endpoints done in FRAME handling
continue;
}
if (opStarted & EP(endpoint)) {
opStarted &= ~EP(endpoint);
if (IN_EP(endpoint)) {
events->in(endpoint);
} else {