120
120
121
121
static USBPhyHw *instance;
122
122
123
- static volatile int epComplete ;
123
+ static uint32_t opStarted ;
124
124
125
125
static void SIECommand (uint32_t command)
126
126
{
@@ -250,16 +250,24 @@ static uint8_t selectEndpointClearInterrupt(uint8_t endpoint)
250
250
251
251
static void enableEndpointEvent (uint8_t endpoint)
252
252
{
253
- // Enable an endpoint interrupt
253
+ // Route endpoint events to USBEpIntSt so they trigger an interrupt
254
254
LPC_USB->USBEpIntEn |= EP (endpoint);
255
255
}
256
256
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
+ /*
257
263
static void disableEndpointEvent(uint8_t endpoint) __attribute__((unused));
258
264
static void disableEndpointEvent(uint8_t endpoint)
259
265
{
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.
261
268
LPC_USB->USBEpIntEn &= ~EP(endpoint);
262
269
}
270
+ */
263
271
264
272
265
273
static uint32_t endpointReadcore (uint8_t endpoint, uint8_t *buffer, uint32_t size)
@@ -392,10 +400,18 @@ void USBPhyHw::init(USBPhyEvents *events)
392
400
// Connect must be low for at least 2.5uS
393
401
wait (0.3 );
394
402
403
+ // Disable control endpoints
404
+ SIEsetEndpointStatus (EP0IN, SIE_SES_DA);
405
+ SIEsetEndpointStatus (EP0OUT, SIE_SES_DA);
406
+
395
407
// Set the maximum packet size for the control endpoints
396
408
endpoint_add (EP0IN, MAX_PACKET_SIZE_EP0, USB_EP_TYPE_CTRL);
397
409
endpoint_add (EP0OUT, MAX_PACKET_SIZE_EP0, USB_EP_TYPE_CTRL);
398
410
411
+ // Map interrupts to USBEpIntSt
412
+ enableEndpointEvent (EP0IN);
413
+ enableEndpointEvent (EP0OUT);
414
+
399
415
// Attach IRQ
400
416
instance = this ;
401
417
NVIC_SetVector (USB_IRQn, (uint32_t )&_usbisr);
@@ -413,6 +429,7 @@ void USBPhyHw::deinit()
413
429
// Disable USB interrupts
414
430
NVIC_DisableIRQ (USB_IRQn);
415
431
events = NULL ;
432
+ opStarted = 0 ;
416
433
}
417
434
418
435
bool USBPhyHw::powered ()
@@ -422,17 +439,19 @@ bool USBPhyHw::powered()
422
439
423
440
void USBPhyHw::connect (void )
424
441
{
425
- enableEndpointEvent (EP0IN);
426
- enableEndpointEvent (EP0OUT);
442
+ // Enable control endpoints
443
+ SIEsetEndpointStatus (EP0IN, 0 );
444
+ SIEsetEndpointStatus (EP0OUT, 0 );
427
445
428
446
// Connect USB device
429
447
SIEconnect ();
430
448
}
431
449
432
450
void USBPhyHw::disconnect (void )
433
451
{
434
- disableEndpointEvent (EP0IN);
435
- disableEndpointEvent (EP0OUT);
452
+ // Disable control endpoints
453
+ SIEsetEndpointStatus (EP0IN, SIE_SES_DA);
454
+ SIEsetEndpointStatus (EP0OUT, SIE_SES_DA);
436
455
437
456
if (LPC_USB->USBEpIntSt & EP (EP0IN)) {
438
457
selectEndpointClearInterrupt (EP0IN);
@@ -512,9 +531,9 @@ void USBPhyHw::ep0_stall(void)
512
531
513
532
bool USBPhyHw::endpoint_read (usb_ep_t endpoint, uint8_t *data, uint32_t size)
514
533
{
534
+ opStarted |= EP (endpoint);
515
535
read_buffers[endpoint] = data;
516
536
read_sizes[endpoint] = size;
517
- enableEndpointEvent (endpoint);
518
537
uint8_t status = SIEselectEndpoint (endpoint);
519
538
if (status & ((1 << 5 ) | (1 << 6 ))) {
520
539
// 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)
525
544
526
545
uint32_t USBPhyHw::endpoint_read_result (usb_ep_t endpoint)
527
546
{
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);
535
548
536
549
uint32_t bytesRead = endpointReadcore (endpoint, read_buffers[endpoint], read_sizes[endpoint]);
537
550
read_buffers[endpoint] = NULL ;
@@ -543,21 +556,26 @@ uint32_t USBPhyHw::endpoint_read_result(usb_ep_t endpoint)
543
556
SIEclearBuffer ();
544
557
}
545
558
546
- epComplete &= ~EP (endpoint);
547
559
return bytesRead;
548
560
}
549
561
550
562
bool USBPhyHw::endpoint_write (usb_ep_t endpoint, uint8_t *data, uint32_t size)
551
563
{
552
- epComplete &= ~ EP (endpoint);
564
+ opStarted |= EP (endpoint);
553
565
554
566
endpointWritecore (endpoint, data, size);
555
567
return true ;
556
568
}
557
569
558
570
void USBPhyHw::endpoint_abort (usb_ep_t endpoint)
559
571
{
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
+ }
561
579
}
562
580
563
581
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
571
589
while (!(LPC_USB->USBDevIntSt & EP_RLZED));
572
590
LPC_USB->USBDevIntClr = EP_RLZED;
573
591
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
+
577
598
return true ;
578
599
}
579
600
580
601
void USBPhyHw::endpoint_remove (usb_ep_t endpoint)
581
602
{
582
603
// Unrealise an endpoint
583
604
584
- disableEndpointEvent (endpoint);
605
+ opStarted &= ~EP (endpoint);
585
606
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
+ }
588
614
589
615
LPC_USB->USBDevIntClr = EP_RLZED;
590
616
LPC_USB->USBReEp &= ~EP (endpoint);
@@ -731,12 +757,12 @@ void USBPhyHw::process(void)
731
757
uint8_t endpoint = PHY_TO_DESC (num);
732
758
if (LPC_USB->USBEpIntSt & EP (endpoint)) {
733
759
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
+ }
740
766
}
741
767
}
742
768
}
0 commit comments