@@ -85,7 +85,7 @@ static struct
85
85
// Number of pending DMA that is started but not handled yet by dcd_int_handler().
86
86
// Since nRF can only carry one DMA can run at a time, this value is normally be either 0 or 1.
87
87
// However, in critical section with interrupt disabled, the DMA can be finished and added up
88
- // until handled by dcd_init_handler () when exiting critical section.
88
+ // until handled by dcd_int_handler () when exiting critical section.
89
89
volatile uint8_t dma_pending ;
90
90
}_dcd ;
91
91
@@ -277,14 +277,8 @@ void dcd_remote_wakeup(uint8_t rhport)
277
277
(void ) rhport ;
278
278
279
279
// Bring controller out of low power mode
280
+ // will start wakeup when USBWUALLOWED is set
280
281
NRF_USBD -> LOWPOWER = 0 ;
281
-
282
- // Initiate RESUME signal
283
- NRF_USBD -> DPDMVALUE = USBD_DPDMVALUE_STATE_Resume ;
284
- NRF_USBD -> TASKS_DPDMDRIVE = 1 ;
285
-
286
- // TODO There is no USBEVENT Resume interrupt
287
- // We may manually raise DCD_EVENT_RESUME event here
288
282
}
289
283
290
284
// disconnect by disabling internal pull-up resistor on D+/D-
@@ -339,21 +333,27 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
339
333
{
340
334
// SPLIT ISO buffer when ISO IN endpoint is already opened.
341
335
if (_dcd .xfer [EP_ISO_NUM ][TUSB_DIR_IN ].mps ) NRF_USBD -> ISOSPLIT = USBD_ISOSPLIT_SPLIT_HalfIN ;
336
+
342
337
// Clear old events
343
338
NRF_USBD -> EVENTS_ENDISOOUT = 0 ;
339
+
344
340
// Clear SOF event in case interrupt was not enabled yet.
345
341
if ((NRF_USBD -> INTEN & USBD_INTEN_SOF_Msk ) == 0 ) NRF_USBD -> EVENTS_SOF = 0 ;
342
+
346
343
// Enable SOF and ISOOUT interrupts, and ISOOUT endpoint.
347
344
NRF_USBD -> INTENSET = USBD_INTENSET_ENDISOOUT_Msk | USBD_INTENSET_SOF_Msk ;
348
345
NRF_USBD -> EPOUTEN |= USBD_EPOUTEN_ISOOUT_Msk ;
349
346
}
350
347
else
351
348
{
352
349
NRF_USBD -> EVENTS_ENDISOIN = 0 ;
350
+
353
351
// SPLIT ISO buffer when ISO OUT endpoint is already opened.
354
352
if (_dcd .xfer [EP_ISO_NUM ][TUSB_DIR_OUT ].mps ) NRF_USBD -> ISOSPLIT = USBD_ISOSPLIT_SPLIT_HalfIN ;
353
+
355
354
// Clear SOF event in case interrupt was not enabled yet.
356
355
if ((NRF_USBD -> INTEN & USBD_INTEN_SOF_Msk ) == 0 ) NRF_USBD -> EVENTS_SOF = 0 ;
356
+
357
357
// Enable SOF and ISOIN interrupts, and ISOIN endpoint.
358
358
NRF_USBD -> INTENSET = USBD_INTENSET_ENDISOIN_Msk | USBD_INTENSET_SOF_Msk ;
359
359
NRF_USBD -> EPINEN |= USBD_EPINEN_ISOIN_Msk ;
@@ -507,6 +507,8 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
507
507
*------------------------------------------------------------------*/
508
508
void bus_reset (void )
509
509
{
510
+ // 6.35.6 USB controller automatically disabled all endpoints (except control)
511
+ // i.e EPOUTEN and EPINEN and reset USBADDR to 0
510
512
for (int i = 0 ; i < 8 ; i ++ )
511
513
{
512
514
NRF_USBD -> TASKS_STARTEPIN [i ] = 0 ;
@@ -516,6 +518,15 @@ void bus_reset(void)
516
518
NRF_USBD -> TASKS_STARTISOIN = 0 ;
517
519
NRF_USBD -> TASKS_STARTISOOUT = 0 ;
518
520
521
+ // Clear USB Event Interrupt
522
+ NRF_USBD -> EVENTS_USBEVENT = 0 ;
523
+ NRF_USBD -> EVENTCAUSE |= NRF_USBD -> EVENTCAUSE ;
524
+
525
+ // Reset interrupt
526
+ NRF_USBD -> INTENCLR = NRF_USBD -> INTEN ;
527
+ NRF_USBD -> INTENSET = USBD_INTEN_USBRESET_Msk | USBD_INTEN_USBEVENT_Msk | USBD_INTEN_EPDATA_Msk |
528
+ USBD_INTEN_EP0SETUP_Msk | USBD_INTEN_EP0DATADONE_Msk | USBD_INTEN_ENDEPIN0_Msk | USBD_INTEN_ENDEPOUT0_Msk ;
529
+
519
530
tu_varclr (& _dcd );
520
531
_dcd .xfer [0 ][TUSB_DIR_IN ].mps = MAX_PACKET_SIZE ;
521
532
_dcd .xfer [0 ][TUSB_DIR_OUT ].mps = MAX_PACKET_SIZE ;
@@ -561,39 +572,71 @@ void dcd_int_handler(uint8_t rhport)
561
572
562
573
if ( int_status & USBD_INTEN_SOF_Msk )
563
574
{
575
+ bool iso_enabled = false;
576
+
564
577
// ISOOUT: Transfer data gathered in previous frame from buffer to RAM
565
578
if (NRF_USBD -> EPOUTEN & USBD_EPOUTEN_ISOOUT_Msk )
566
579
{
580
+ iso_enabled = true;
567
581
xact_out_dma (EP_ISO_NUM );
568
582
}
583
+
569
584
// ISOIN: Notify client that data was transferred
570
- xfer_td_t * xfer = get_td (EP_ISO_NUM , TUSB_DIR_IN );
571
- if ( xfer -> iso_in_transfer_ready )
585
+ if (NRF_USBD -> EPINEN & USBD_EPINEN_ISOIN_Msk )
572
586
{
573
- xfer -> iso_in_transfer_ready = false;
574
- dcd_event_xfer_complete (0 , EP_ISO_NUM | TUSB_DIR_IN_MASK , xfer -> actual_len , XFER_RESULT_SUCCESS , true);
587
+ iso_enabled = true;
588
+
589
+ xfer_td_t * xfer = get_td (EP_ISO_NUM , TUSB_DIR_IN );
590
+ if ( xfer -> iso_in_transfer_ready )
591
+ {
592
+ xfer -> iso_in_transfer_ready = false;
593
+ dcd_event_xfer_complete (0 , EP_ISO_NUM | TUSB_DIR_IN_MASK , xfer -> actual_len , XFER_RESULT_SUCCESS , true);
594
+ }
575
595
}
596
+
597
+ if ( !iso_enabled )
598
+ {
599
+ // ISO endpoint is not used, SOF is only enabled one-time for remote wakeup
600
+ // so we disable it now
601
+ NRF_USBD -> INTENCLR = USBD_INTENSET_SOF_Msk ;
602
+ }
603
+
576
604
dcd_event_bus_signal (0 , DCD_EVENT_SOF , true);
577
605
}
578
606
579
607
if ( int_status & USBD_INTEN_USBEVENT_Msk )
580
608
{
581
- uint32_t const evt_cause = NRF_USBD -> EVENTCAUSE & (USBD_EVENTCAUSE_SUSPEND_Msk | USBD_EVENTCAUSE_RESUME_Msk );
609
+ TU_LOG (2 , "EVENTCAUSE = 0x%04lX\r\n" , NRF_USBD -> EVENTCAUSE );
610
+
611
+ enum { EVT_CAUSE_MASK = USBD_EVENTCAUSE_SUSPEND_Msk | USBD_EVENTCAUSE_RESUME_Msk | USBD_EVENTCAUSE_USBWUALLOWED_Msk };
612
+ uint32_t const evt_cause = NRF_USBD -> EVENTCAUSE & EVT_CAUSE_MASK ;
582
613
NRF_USBD -> EVENTCAUSE = evt_cause ; // clear interrupt
583
614
584
615
if ( evt_cause & USBD_EVENTCAUSE_SUSPEND_Msk )
585
616
{
586
- dcd_event_bus_signal (0 , DCD_EVENT_SUSPEND , true);
587
-
588
617
// Put controller into low power mode
618
+ // Leave HFXO disable to application, since it may be used by other peripherals
589
619
NRF_USBD -> LOWPOWER = 1 ;
590
620
591
- // Leave HFXO disable to application, since it may be used by other
621
+ dcd_event_bus_signal ( 0 , DCD_EVENT_SUSPEND , true);
592
622
}
593
623
594
- if ( evt_cause & USBD_EVENTCAUSE_RESUME_Msk )
624
+ if ( evt_cause & USBD_EVENTCAUSE_USBWUALLOWED_Msk )
595
625
{
596
- dcd_event_bus_signal (0 , DCD_EVENT_RESUME , true);
626
+ // USB is out of low power mode, and wakeup is allowed
627
+ // Initiate RESUME signal
628
+ NRF_USBD -> DPDMVALUE = USBD_DPDMVALUE_STATE_Resume ;
629
+ NRF_USBD -> TASKS_DPDMDRIVE = 1 ;
630
+
631
+ // There is no Resume interrupt for remote wakeup, enable SOF for to report bus ready state
632
+ // Clear SOF event in case interrupt was not enabled yet.
633
+ if ((NRF_USBD -> INTEN & USBD_INTEN_SOF_Msk ) == 0 ) NRF_USBD -> EVENTS_SOF = 0 ;
634
+ NRF_USBD -> INTENSET = USBD_INTENSET_SOF_Msk ;
635
+ }
636
+
637
+ if ( evt_cause & USBD_EVENTCAUSE_RESUME_Msk )
638
+ {
639
+ dcd_event_bus_signal (0 , DCD_EVENT_RESUME , true);
597
640
}
598
641
}
599
642
@@ -845,18 +888,22 @@ void tusb_hal_nrf_power_event (uint32_t event)
845
888
USB_EVT_READY = 2
846
889
};
847
890
891
+ #if CFG_TUSB_DEBUG >= 2
892
+ const char * const power_evt_str [] = { "Detected" , "Removed" , "Ready" };
893
+ TU_LOG (2 , "Power USB event: %s\r\n" , power_evt_str [event ]);
894
+ #endif
895
+
848
896
switch ( event )
849
897
{
850
898
case USB_EVT_DETECTED :
851
- TU_LOG2 ("Power USB Detect\r\n" );
852
-
853
899
if ( !NRF_USBD -> ENABLE )
854
900
{
855
- /* Prepare for READY event receiving */
901
+ // Prepare for receiving READY event: disable interrupt since we will blocking wait
902
+ NRF_USBD -> INTENCLR = USBD_INTEN_USBEVENT_Msk ;
856
903
NRF_USBD -> EVENTCAUSE = USBD_EVENTCAUSE_READY_Msk ;
857
904
__ISB (); __DSB (); // for sync
858
905
859
- #ifdef NRF52_SERIES
906
+ #ifdef NRF52_SERIES // NRF53 does not need this errata
860
907
// ERRATA 171, 187, 166
861
908
if ( nrfx_usbd_errata_187 () )
862
909
{
@@ -891,7 +938,7 @@ void tusb_hal_nrf_power_event (uint32_t event)
891
938
}
892
939
#endif
893
940
894
- /* Enable the peripheral */
941
+ // Enable the peripheral (will cause Ready event)
895
942
NRF_USBD -> ENABLE = 1 ;
896
943
__ISB (); __DSB (); // for sync
897
944
@@ -901,13 +948,11 @@ void tusb_hal_nrf_power_event (uint32_t event)
901
948
break ;
902
949
903
950
case USB_EVT_READY :
904
- TU_LOG2 ("Power USB Ready\r\n" );
905
-
906
951
// Skip if pull-up is enabled and HCLK is already running.
907
952
// Application probably call this more than necessary.
908
953
if ( NRF_USBD -> USBPULLUP && hfclk_running () ) break ;
909
954
910
- /* Waiting for USBD peripheral enabled */
955
+ // Waiting for USBD peripheral enabled
911
956
while ( !(USBD_EVENTCAUSE_READY_Msk & NRF_USBD -> EVENTCAUSE ) ) { }
912
957
913
958
NRF_USBD -> EVENTCAUSE = USBD_EVENTCAUSE_READY_Msk ;
@@ -959,9 +1004,8 @@ void tusb_hal_nrf_power_event (uint32_t event)
959
1004
// ISO buffer Lower half for IN, upper half for OUT
960
1005
NRF_USBD -> ISOSPLIT = USBD_ISOSPLIT_SPLIT_HalfIN ;
961
1006
962
- // Enable interrupt
963
- NRF_USBD -> INTENSET = USBD_INTEN_USBRESET_Msk | USBD_INTEN_EPDATA_Msk |
964
- USBD_INTEN_EP0SETUP_Msk | USBD_INTEN_EP0DATADONE_Msk | USBD_INTEN_ENDEPIN0_Msk | USBD_INTEN_ENDEPOUT0_Msk ;
1007
+ // Enable bus-reset interrupt
1008
+ NRF_USBD -> INTENSET = USBD_INTEN_USBRESET_Msk ;
965
1009
966
1010
// Enable interrupt, priorities should be set by application
967
1011
NVIC_ClearPendingIRQ (USBD_IRQn );
@@ -976,7 +1020,6 @@ void tusb_hal_nrf_power_event (uint32_t event)
976
1020
break ;
977
1021
978
1022
case USB_EVT_REMOVED :
979
- TU_LOG2 ("Power USB Removed\r\n" );
980
1023
if ( NRF_USBD -> ENABLE )
981
1024
{
982
1025
// Abort all transfers
0 commit comments