Skip to content

Commit a86d054

Browse files
committed
Implement LPC1768 USB abort function
Implement the USB abort function so interrupts wont fire for a transfer that has been aborted. The transfer may still take place but the buffer passed into endpoint_write or endpoint_read will not be used.
1 parent 2ad05b2 commit a86d054

File tree

1 file changed

+56
-30
lines changed

1 file changed

+56
-30
lines changed

usb/device/targets/TARGET_NXP/USBHAL_LPC17.cpp

Lines changed: 56 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@
120120

121121
static USBPhyHw *instance;
122122

123-
static volatile int epComplete;
123+
static uint32_t opStarted;
124124

125125
static void SIECommand(uint32_t command)
126126
{
@@ -250,16 +250,24 @@ static uint8_t selectEndpointClearInterrupt(uint8_t endpoint)
250250

251251
static void enableEndpointEvent(uint8_t endpoint)
252252
{
253-
// Enable an endpoint interrupt
253+
// Route endpoint events to USBEpIntSt so they trigger an interrupt
254254
LPC_USB->USBEpIntEn |= EP(endpoint);
255255
}
256256

257+
// Do not use disableEndpointEvent. If an endpoint's event is disabled
258+
// and a transfer occurs on that endpoint then that endpoint will enter
259+
// a bad state. Future transfers on that endpoint will not trigger an
260+
// interrupt even if the endpoint event is enabled again or the
261+
// endpoint is reinitialized
262+
/*
257263
static void disableEndpointEvent(uint8_t endpoint) __attribute__((unused));
258264
static void disableEndpointEvent(uint8_t endpoint)
259265
{
260-
// Disable an endpoint interrupt
266+
// Don't set endpoint interrupt to pending in USBEpIntSt when an event occurs.
267+
// Instead route them to USBDMARSt so they can be ignored.
261268
LPC_USB->USBEpIntEn &= ~EP(endpoint);
262269
}
270+
*/
263271

264272

265273
static uint32_t endpointReadcore(uint8_t endpoint, uint8_t *buffer, uint32_t size)
@@ -392,10 +400,18 @@ void USBPhyHw::init(USBPhyEvents *events)
392400
// Connect must be low for at least 2.5uS
393401
wait(0.3);
394402

403+
// Disable control endpoints
404+
SIEsetEndpointStatus(EP0IN, SIE_SES_DA);
405+
SIEsetEndpointStatus(EP0OUT, SIE_SES_DA);
406+
395407
// Set the maximum packet size for the control endpoints
396408
endpoint_add(EP0IN, MAX_PACKET_SIZE_EP0, USB_EP_TYPE_CTRL);
397409
endpoint_add(EP0OUT, MAX_PACKET_SIZE_EP0, USB_EP_TYPE_CTRL);
398410

411+
// Map interrupts to USBEpIntSt
412+
enableEndpointEvent(EP0IN);
413+
enableEndpointEvent(EP0OUT);
414+
399415
// Attach IRQ
400416
instance = this;
401417
NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr);
@@ -413,6 +429,7 @@ void USBPhyHw::deinit()
413429
// Disable USB interrupts
414430
NVIC_DisableIRQ(USB_IRQn);
415431
events = NULL;
432+
opStarted = 0;
416433
}
417434

418435
bool USBPhyHw::powered()
@@ -422,17 +439,19 @@ bool USBPhyHw::powered()
422439

423440
void USBPhyHw::connect(void)
424441
{
425-
enableEndpointEvent(EP0IN);
426-
enableEndpointEvent(EP0OUT);
442+
// Enable control endpoints
443+
SIEsetEndpointStatus(EP0IN, 0);
444+
SIEsetEndpointStatus(EP0OUT, 0);
427445

428446
// Connect USB device
429447
SIEconnect();
430448
}
431449

432450
void USBPhyHw::disconnect(void)
433451
{
434-
disableEndpointEvent(EP0IN);
435-
disableEndpointEvent(EP0OUT);
452+
// Disable control endpoints
453+
SIEsetEndpointStatus(EP0IN, SIE_SES_DA);
454+
SIEsetEndpointStatus(EP0OUT, SIE_SES_DA);
436455

437456
if (LPC_USB->USBEpIntSt & EP(EP0IN)) {
438457
selectEndpointClearInterrupt(EP0IN);
@@ -512,9 +531,9 @@ void USBPhyHw::ep0_stall(void)
512531

513532
bool USBPhyHw::endpoint_read(usb_ep_t endpoint, uint8_t *data, uint32_t size)
514533
{
534+
opStarted |= EP(endpoint);
515535
read_buffers[endpoint] = data;
516536
read_sizes[endpoint] = size;
517-
enableEndpointEvent(endpoint);
518537
uint8_t status = SIEselectEndpoint(endpoint);
519538
if (status & ((1 << 5) | (1 << 6))) {
520539
// If any buffer has data then set the interrupt flag
@@ -525,13 +544,7 @@ bool USBPhyHw::endpoint_read(usb_ep_t endpoint, uint8_t *data, uint32_t size)
525544

526545
uint32_t USBPhyHw::endpoint_read_result(usb_ep_t endpoint)
527546
{
528-
529-
//for isochronous endpoint, we don't wait an interrupt
530-
if ((DESC_TO_PHY(endpoint) >> 1) % 3 || (DESC_TO_PHY(endpoint) >> 1) == 0) {
531-
if (!(epComplete & EP(endpoint))) {
532-
return 0;
533-
}
534-
}
547+
opStarted &= ~EP(endpoint);
535548

536549
uint32_t bytesRead = endpointReadcore(endpoint, read_buffers[endpoint], read_sizes[endpoint]);
537550
read_buffers[endpoint] = NULL;
@@ -543,21 +556,26 @@ uint32_t USBPhyHw::endpoint_read_result(usb_ep_t endpoint)
543556
SIEclearBuffer();
544557
}
545558

546-
epComplete &= ~EP(endpoint);
547559
return bytesRead;
548560
}
549561

550562
bool USBPhyHw::endpoint_write(usb_ep_t endpoint, uint8_t *data, uint32_t size)
551563
{
552-
epComplete &= ~EP(endpoint);
564+
opStarted |= EP(endpoint);
553565

554566
endpointWritecore(endpoint, data, size);
555567
return true;
556568
}
557569

558570
void USBPhyHw::endpoint_abort(usb_ep_t endpoint)
559571
{
560-
//TODO - needs to be implemented
572+
opStarted &= ~EP(endpoint);
573+
574+
// Clear out transfer buffers since the transfer has been aborted
575+
if (OUT_EP(endpoint)) {
576+
read_buffers[endpoint] = NULL;
577+
read_sizes[endpoint] = 0;
578+
}
561579
}
562580

563581
bool USBPhyHw::endpoint_add(usb_ep_t endpoint, uint32_t maxPacket, usb_ep_type_t type)
@@ -571,20 +589,28 @@ bool USBPhyHw::endpoint_add(usb_ep_t endpoint, uint32_t maxPacket, usb_ep_type_t
571589
while (!(LPC_USB->USBDevIntSt & EP_RLZED));
572590
LPC_USB->USBDevIntClr = EP_RLZED;
573591

574-
if (IN_EP(endpoint)) {
575-
enableEndpointEvent(endpoint);
576-
}
592+
// Map interrupts to USBEpIntSt
593+
enableEndpointEvent(endpoint);
594+
595+
// Enable this endpoint
596+
SIEsetEndpointStatus(endpoint, 0);
597+
577598
return true;
578599
}
579600

580601
void USBPhyHw::endpoint_remove(usb_ep_t endpoint)
581602
{
582603
// Unrealise an endpoint
583604

584-
disableEndpointEvent(endpoint);
605+
opStarted &= ~EP(endpoint);
585606

586-
// reset this endpoint, including data toggle
587-
SIEsetEndpointStatus(endpoint, 0);
607+
// Disable this endpoint
608+
SIEsetEndpointStatus(endpoint, SIE_SES_DA);
609+
610+
// Clear the given interrupt bit in USBEpIntSt if it is set
611+
if (LPC_USB->USBEpIntSt & EP(endpoint)) {
612+
selectEndpointClearInterrupt(endpoint);
613+
}
588614

589615
LPC_USB->USBDevIntClr = EP_RLZED;
590616
LPC_USB->USBReEp &= ~EP(endpoint);
@@ -731,12 +757,12 @@ void USBPhyHw::process(void)
731757
uint8_t endpoint = PHY_TO_DESC(num);
732758
if (LPC_USB->USBEpIntSt & EP(endpoint)) {
733759
selectEndpointClearInterrupt(endpoint);
734-
epComplete |= EP(endpoint);
735-
if (IN_EP(endpoint)) {
736-
events->in(endpoint);
737-
} else {
738-
disableEndpointEvent(endpoint);
739-
events->out(endpoint);
760+
if (opStarted & EP(endpoint)) {
761+
if (IN_EP(endpoint)) {
762+
events->in(endpoint);
763+
} else {
764+
events->out(endpoint);
765+
}
740766
}
741767
}
742768
}

0 commit comments

Comments
 (0)