Skip to content

Commit c7cb445

Browse files
committed
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.
1 parent 16c8e5b commit c7cb445

File tree

1 file changed

+34
-2
lines changed

1 file changed

+34
-2
lines changed

usb/device/targets/TARGET_NXP/USBHAL_LPC17.cpp

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
// Convert physical endpoint number to register bit
3030
#define EP(endpoint) (1UL<<DESC_TO_PHY(endpoint))
3131

32+
// Check if this is an isochronous endpoint
33+
#define ISO_EP(endpoint) ((((endpoint) & 0xF) == 3) || (((endpoint) & 0xF) == 6) || (((endpoint) & 0xF) == 9) || (((endpoint) & 0xF) == 12))
34+
3235
#define DESC_TO_PHY(endpoint) ((((endpoint)&0x0F)<<1) | (((endpoint) & 0x80) ? 1:0))
3336
#define PHY_TO_DESC(endpoint) (((endpoint)>>1)|(((endpoint)&1)?0x80:0))
3437

@@ -122,6 +125,13 @@ static USBPhyHw *instance;
122125

123126
static uint32_t opStarted;
124127

128+
static const usb_ep_t ISO_EPS[] = {
129+
0x03, 0x83,
130+
0x06, 0x86,
131+
0x09, 0x89,
132+
0x0C, 0x8C
133+
};
134+
125135
static void SIECommand(uint32_t command)
126136
{
127137
// The command phase of a SIE transaction
@@ -465,6 +475,9 @@ void USBPhyHw::disconnect(void)
465475

466476
// Disconnect USB device
467477
SIEdisconnect();
478+
479+
// Reset all started operations
480+
opStarted = 0;
468481
}
469482

470483
void USBPhyHw::configure(void)
@@ -551,7 +564,7 @@ uint32_t USBPhyHw::endpoint_read_result(usb_ep_t endpoint)
551564
read_sizes[endpoint] = 0;
552565

553566
// Don't clear isochronous endpoints
554-
if ((DESC_TO_PHY(endpoint) >> 1) % 3 || (DESC_TO_PHY(endpoint) >> 1) == 0) {
567+
if (!ISO_EP(endpoint)) {
555568
SIEselectEndpoint(endpoint);
556569
SIEclearBuffer();
557570
}
@@ -692,6 +705,20 @@ void USBPhyHw::process(void)
692705
events->sof(SIEgetFrameNumber());
693706
// Clear interrupt status flag
694707
LPC_USB->USBDevIntClr = FRAME;
708+
709+
// There is no ISO interrupt, instead a packet is transferred every SOF
710+
for (uint32_t i = 0; i < sizeof(ISO_EPS) / sizeof(ISO_EPS[0]); i++) {
711+
uint8_t endpoint = ISO_EPS[i];
712+
if (opStarted & EP(endpoint)) {
713+
opStarted &= ~EP(endpoint);
714+
if (IN_EP(endpoint)) {
715+
events->in(endpoint);
716+
} else {
717+
events->out(endpoint);
718+
}
719+
}
720+
}
721+
695722
}
696723

697724
if (LPC_USB->USBDevIntSt & DEV_STAT) {
@@ -717,6 +744,7 @@ void USBPhyHw::process(void)
717744
}
718745
memset(read_buffers, 0, sizeof(read_buffers));
719746
memset(read_sizes, 0, sizeof(read_sizes));
747+
opStarted = 0;
720748
events->reset();
721749
}
722750
}
@@ -752,12 +780,16 @@ void USBPhyHw::process(void)
752780
}
753781
}
754782

755-
//TODO - should probably process in the reverse order
756783
for (uint8_t num = 2; num < 16 * 2; num++) {
757784
uint8_t endpoint = PHY_TO_DESC(num);
758785
if (LPC_USB->USBEpIntSt & EP(endpoint)) {
759786
selectEndpointClearInterrupt(endpoint);
787+
if (ISO_EP(endpoint)) {
788+
// Processing for ISO endpoints done in FRAME handling
789+
continue;
790+
}
760791
if (opStarted & EP(endpoint)) {
792+
opStarted &= ~EP(endpoint);
761793
if (IN_EP(endpoint)) {
762794
events->in(endpoint);
763795
} else {

0 commit comments

Comments
 (0)