@@ -741,16 +741,19 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
741741//--------------------------------------------------------------------+
742742void dcd_int_handler (uint8_t rhport )
743743{
744- uint32_t is = U1IR ;
745- uint32_t msk = U1IE ;
744+ uint32_t is , msk ;
745+
746+ // Part 1 - "USB interrupts"
747+ is = U1IR ;
748+ msk = U1IE ;
746749
747750 U1IR = is & ~msk ;
748751 is &= msk ;
749752
750753 if (is & _U1IR_UERRIF_MASK ) {
751754 uint32_t es = U1EIR ;
752755 U1EIR = es ;
753- U1IR = is ; /* discard any pending events */
756+ U1IR = is ; /* discard any pending events */
754757 }
755758
756759 if (is & _U1IR_URSTIF_MASK ) {
@@ -761,29 +764,66 @@ void dcd_int_handler(uint8_t rhport)
761764 if (is & _U1IR_IDLEIF_MASK ) {
762765 // Note Host usually has extra delay after bus reset (without SOF), which could falsely
763766 // detected as Sleep event. Though usbd has debouncing logic so we are good
767+
768+ /*
769+ * NOTE: Do not clear U1OTGIRbits.ACTVIF here!
770+ * Reason:
771+ * ACTVIF is only generated once an IDLEIF has been generated.
772+ * This is a 1:1 ratio interrupt generation.
773+ * For every IDLEIF, there will be only one ACTVIF regardless of
774+ * the number of subsequent bus transitions.
775+ *
776+ * If the ACTIF is cleared here, a problem could occur when:
777+ * [ IDLE ][bus activity ->
778+ * <--- 3 ms -----> ^
779+ * ^ ACTVIF=1
780+ * IDLEIF=1
781+ * # # # # (#=Program polling flags)
782+ * ^
783+ * This polling loop will see both
784+ * IDLEIF=1 and ACTVIF=1.
785+ * However, the program services IDLEIF first
786+ * because ACTIVIE=0.
787+ * If this routine clears the only ACTIVIF,
788+ * then it can never get out of the suspend
789+ * mode.
790+ */
791+ U1OTGIESET = _U1OTGIE_ACTVIE_MASK ;
764792 U1IR = _U1IR_IDLEIF_MASK ;
765793 process_bus_sleep (rhport );
766794 }
767795
768- if (is & _U1IR_RESUMEIF_MASK ) {
769- U1IR = _U1IR_RESUMEIF_MASK ;
770- process_bus_resume (rhport );
771- }
772-
773796 if (is & _U1IR_SOFIF_MASK ) {
774797 U1IR = _U1IR_SOFIF_MASK ;
775798 dcd_event_bus_signal (rhport , DCD_EVENT_SOF , true);
776799 }
777800
778801 if (is & _U1IR_STALLIF_MASK ) {
779- U1IR = _U1IR_STALLIF_MASK ;
780802 process_stall (rhport );
803+ U1IR = _U1IR_STALLIF_MASK ;
781804 }
782805
783806 if (is & _U1IR_TRNIF_MASK ) {
784807 process_tokdne (rhport );
785808 }
786809
810+ // Part 2 - "USB OTG interrupts"
811+ is = U1OTGIR ;
812+ msk = U1OTGIE ;
813+
814+ U1OTGIR = is & ~msk ;
815+ is &= msk ;
816+
817+ if (is & _U1OTGIR_ACTVIF_MASK ) {
818+ #if TU_PIC_INT_SIZE == 4
819+ U1OTGIECLR = _U1OTGIE_ACTVIE_MASK ;
820+ #else
821+ U1OTGIE &= ~_U1OTGIE_ACTVIE_MASK ;
822+ #endif
823+ U1OTGIR = _U1OTGIR_ACTVIF_MASK ;
824+ process_bus_resume (rhport );
825+ }
826+
787827 intr_clear (rhport );
788828}
789829
0 commit comments