summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/portable/wch/ch32_usbfs_reg.h4
-rw-r--r--src/portable/wch/dcd_ch32_usbfs.c7
2 files changed, 11 insertions, 0 deletions
diff --git a/src/portable/wch/ch32_usbfs_reg.h b/src/portable/wch/ch32_usbfs_reg.h
index 9c58c467f..90a477b79 100644
--- a/src/portable/wch/ch32_usbfs_reg.h
+++ b/src/portable/wch/ch32_usbfs_reg.h
@@ -233,6 +233,10 @@
#define USBFS_INT_FG_TOG_OK (1 << 6)
#define USBFS_INT_FG_IS_NAK (1 << 7)
+// MIS_ST: the SUSPEND interrupt fires on both suspend and resume; this bit (R8_USB_MIS_ST) is 1
+// while the bus is suspended and 0 once it has resumed, so it tells the two apart.
+#define USBFS_MIS_ST_SUSPEND (1 << 2)
+
// INT_ST
#define USBFS_INT_ST_MASK_UIS_ENDP(x) (((x) >> 0) & 0x0F)
#define USBFS_INT_ST_MASK_UIS_TOKEN(x) (((x) >> 4) & 0x03)
diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c
index 164b6f7bf..61c973062 100644
--- a/src/portable/wch/dcd_ch32_usbfs.c
+++ b/src/portable/wch/dcd_ch32_usbfs.c
@@ -391,7 +391,14 @@ void dcd_int_handler(uint8_t rhport) {
USBOTG_FS->INT_FG = USBFS_INT_FG_BUS_RST;
} else if (status & USBFS_INT_FG_SUSPEND) {
+#if CFG_TUSB_MCU == OPT_MCU_CH58X
+ // CH58x raises this single interrupt for both suspend and resume; MIS_ST's suspend bit tells
+ // them apart (set while suspended, clear once resumed) so tud_resume_cb() actually fires.
+ dcd_event_t event = {.rhport = rhport,
+ .event_id = (USBOTG_FS->MIS_ST & USBFS_MIS_ST_SUSPEND) ? DCD_EVENT_SUSPEND : DCD_EVENT_RESUME};
+#else
dcd_event_t event = {.rhport = rhport, .event_id = DCD_EVENT_SUSPEND};
+#endif
dcd_event_handler(&event, true);
USBOTG_FS->INT_FG = USBFS_INT_FG_SUSPEND;
}