From da77f3885b60c4e2e7e763a55e9c4cbd5e7ac628 Mon Sep 17 00:00:00 2001 From: Russ Butler Date: Wed, 6 Jun 2018 11:02:02 -0500 Subject: [PATCH] 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. --- .../targets/TARGET_NXP/USBHAL_LPC17.cpp | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/usb/device/targets/TARGET_NXP/USBHAL_LPC17.cpp b/usb/device/targets/TARGET_NXP/USBHAL_LPC17.cpp index 58c264a5e4..6cfc629a51 100644 --- a/usb/device/targets/TARGET_NXP/USBHAL_LPC17.cpp +++ b/usb/device/targets/TARGET_NXP/USBHAL_LPC17.cpp @@ -29,6 +29,9 @@ // Convert physical endpoint number to register bit #define EP(endpoint) (1UL<>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 {