@@ -85,7 +85,7 @@ static struct
8585 // Number of pending DMA that is started but not handled yet by dcd_int_handler().
8686 // Since nRF can only carry one DMA can run at a time, this value is normally be either 0 or 1.
8787 // 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.
8989 volatile uint8_t dma_pending ;
9090}_dcd ;
9191
@@ -277,14 +277,8 @@ void dcd_remote_wakeup(uint8_t rhport)
277277 (void ) rhport ;
278278
279279 // Bring controller out of low power mode
280+ // will start wakeup when USBWUALLOWED is set
280281 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
288282}
289283
290284// 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)
339333 {
340334 // SPLIT ISO buffer when ISO IN endpoint is already opened.
341335 if (_dcd .xfer [EP_ISO_NUM ][TUSB_DIR_IN ].mps ) NRF_USBD -> ISOSPLIT = USBD_ISOSPLIT_SPLIT_HalfIN ;
336+
342337 // Clear old events
343338 NRF_USBD -> EVENTS_ENDISOOUT = 0 ;
339+
344340 // Clear SOF event in case interrupt was not enabled yet.
345341 if ((NRF_USBD -> INTEN & USBD_INTEN_SOF_Msk ) == 0 ) NRF_USBD -> EVENTS_SOF = 0 ;
342+
346343 // Enable SOF and ISOOUT interrupts, and ISOOUT endpoint.
347344 NRF_USBD -> INTENSET = USBD_INTENSET_ENDISOOUT_Msk | USBD_INTENSET_SOF_Msk ;
348345 NRF_USBD -> EPOUTEN |= USBD_EPOUTEN_ISOOUT_Msk ;
349346 }
350347 else
351348 {
352349 NRF_USBD -> EVENTS_ENDISOIN = 0 ;
350+
353351 // SPLIT ISO buffer when ISO OUT endpoint is already opened.
354352 if (_dcd .xfer [EP_ISO_NUM ][TUSB_DIR_OUT ].mps ) NRF_USBD -> ISOSPLIT = USBD_ISOSPLIT_SPLIT_HalfIN ;
353+
355354 // Clear SOF event in case interrupt was not enabled yet.
356355 if ((NRF_USBD -> INTEN & USBD_INTEN_SOF_Msk ) == 0 ) NRF_USBD -> EVENTS_SOF = 0 ;
356+
357357 // Enable SOF and ISOIN interrupts, and ISOIN endpoint.
358358 NRF_USBD -> INTENSET = USBD_INTENSET_ENDISOIN_Msk | USBD_INTENSET_SOF_Msk ;
359359 NRF_USBD -> EPINEN |= USBD_EPINEN_ISOIN_Msk ;
@@ -507,6 +507,8 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
507507 *------------------------------------------------------------------*/
508508void bus_reset (void )
509509{
510+ // 6.35.6 USB controller automatically disabled all endpoints (except control)
511+ // i.e EPOUTEN and EPINEN and reset USBADDR to 0
510512 for (int i = 0 ; i < 8 ; i ++ )
511513 {
512514 NRF_USBD -> TASKS_STARTEPIN [i ] = 0 ;
@@ -516,6 +518,15 @@ void bus_reset(void)
516518 NRF_USBD -> TASKS_STARTISOIN = 0 ;
517519 NRF_USBD -> TASKS_STARTISOOUT = 0 ;
518520
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+
519530 tu_varclr (& _dcd );
520531 _dcd .xfer [0 ][TUSB_DIR_IN ].mps = MAX_PACKET_SIZE ;
521532 _dcd .xfer [0 ][TUSB_DIR_OUT ].mps = MAX_PACKET_SIZE ;
@@ -561,39 +572,71 @@ void dcd_int_handler(uint8_t rhport)
561572
562573 if ( int_status & USBD_INTEN_SOF_Msk )
563574 {
575+ bool iso_enabled = false;
576+
564577 // ISOOUT: Transfer data gathered in previous frame from buffer to RAM
565578 if (NRF_USBD -> EPOUTEN & USBD_EPOUTEN_ISOOUT_Msk )
566579 {
580+ iso_enabled = true;
567581 xact_out_dma (EP_ISO_NUM );
568582 }
583+
569584 // 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 )
572586 {
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+ }
575595 }
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+
576604 dcd_event_bus_signal (0 , DCD_EVENT_SOF , true);
577605 }
578606
579607 if ( int_status & USBD_INTEN_USBEVENT_Msk )
580608 {
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 ;
582613 NRF_USBD -> EVENTCAUSE = evt_cause ; // clear interrupt
583614
584615 if ( evt_cause & USBD_EVENTCAUSE_SUSPEND_Msk )
585616 {
586- dcd_event_bus_signal (0 , DCD_EVENT_SUSPEND , true);
587-
588617 // Put controller into low power mode
618+ // Leave HFXO disable to application, since it may be used by other peripherals
589619 NRF_USBD -> LOWPOWER = 1 ;
590620
591- // Leave HFXO disable to application, since it may be used by other
621+ dcd_event_bus_signal ( 0 , DCD_EVENT_SUSPEND , true);
592622 }
593623
594- if ( evt_cause & USBD_EVENTCAUSE_RESUME_Msk )
624+ if ( evt_cause & USBD_EVENTCAUSE_USBWUALLOWED_Msk )
595625 {
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);
597640 }
598641 }
599642
@@ -845,18 +888,22 @@ void tusb_hal_nrf_power_event (uint32_t event)
845888 USB_EVT_READY = 2
846889 };
847890
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+
848896 switch ( event )
849897 {
850898 case USB_EVT_DETECTED :
851- TU_LOG2 ("Power USB Detect\r\n" );
852-
853899 if ( !NRF_USBD -> ENABLE )
854900 {
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 ;
856903 NRF_USBD -> EVENTCAUSE = USBD_EVENTCAUSE_READY_Msk ;
857904 __ISB (); __DSB (); // for sync
858905
859- #ifdef NRF52_SERIES
906+ #ifdef NRF52_SERIES // NRF53 does not need this errata
860907 // ERRATA 171, 187, 166
861908 if ( nrfx_usbd_errata_187 () )
862909 {
@@ -891,7 +938,7 @@ void tusb_hal_nrf_power_event (uint32_t event)
891938 }
892939#endif
893940
894- /* Enable the peripheral */
941+ // Enable the peripheral (will cause Ready event)
895942 NRF_USBD -> ENABLE = 1 ;
896943 __ISB (); __DSB (); // for sync
897944
@@ -901,13 +948,11 @@ void tusb_hal_nrf_power_event (uint32_t event)
901948 break ;
902949
903950 case USB_EVT_READY :
904- TU_LOG2 ("Power USB Ready\r\n" );
905-
906951 // Skip if pull-up is enabled and HCLK is already running.
907952 // Application probably call this more than necessary.
908953 if ( NRF_USBD -> USBPULLUP && hfclk_running () ) break ;
909954
910- /* Waiting for USBD peripheral enabled */
955+ // Waiting for USBD peripheral enabled
911956 while ( !(USBD_EVENTCAUSE_READY_Msk & NRF_USBD -> EVENTCAUSE ) ) { }
912957
913958 NRF_USBD -> EVENTCAUSE = USBD_EVENTCAUSE_READY_Msk ;
@@ -959,9 +1004,8 @@ void tusb_hal_nrf_power_event (uint32_t event)
9591004 // ISO buffer Lower half for IN, upper half for OUT
9601005 NRF_USBD -> ISOSPLIT = USBD_ISOSPLIT_SPLIT_HalfIN ;
9611006
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 ;
9651009
9661010 // Enable interrupt, priorities should be set by application
9671011 NVIC_ClearPendingIRQ (USBD_IRQn );
@@ -976,7 +1020,6 @@ void tusb_hal_nrf_power_event (uint32_t event)
9761020 break ;
9771021
9781022 case USB_EVT_REMOVED :
979- TU_LOG2 ("Power USB Removed\r\n" );
9801023 if ( NRF_USBD -> ENABLE )
9811024 {
9821025 // Abort all transfers
0 commit comments