diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/portable/wch/dcd_ch32_usbfs.c | 22 |
1 files changed, 17 insertions, 5 deletions
diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index 8f583510c..3ba6eee87 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -66,6 +66,13 @@ static struct { static void update_in(uint8_t rhport, uint8_t ep, bool force) { struct usb_xfer* xfer = &data.xfer[ep][TUSB_DIR_IN]; if (xfer->valid) { + // Set EP to NAK to avoid spurious tramsfer + if (ep == 0) { + EP_TX_CTRL(0) = USBFS_EP_T_RES_NAK | (data.ep0_tog ? USBFS_EP_T_TOG : 0); + } else if (!data.isochronous[ep]) { + EP_TX_CTRL(ep) = (EP_TX_CTRL(ep) & ~(USBFS_EP_T_RES_MASK)) | USBFS_EP_T_RES_NAK; + } + if (force || xfer->len) { size_t len = TU_MIN(xfer->max_size, xfer->len); if (ep == 0) { @@ -101,6 +108,13 @@ static void update_in(uint8_t rhport, uint8_t ep, bool force) { static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len) { struct usb_xfer* xfer = &data.xfer[ep][TUSB_DIR_OUT]; if (xfer->valid) { + // Set EP to NAK to avoid spurious tramsfer + if (ep == 0) { + EP_RX_CTRL(0) = USBFS_EP_R_RES_NAK; + } else if (!data.isochronous[ep]) { + EP_RX_CTRL(ep) = (EP_RX_CTRL(ep) & ~USBFS_EP_R_RES_MASK) | USBFS_EP_R_RES_NAK; + } + size_t len = TU_MIN(xfer->max_size, TU_MIN(xfer->len, rx_len)); if (ep == 3) { memcpy(xfer->buffer, data.ep3_buffer.out, len); @@ -116,9 +130,7 @@ static void update_out(uint8_t rhport, uint8_t ep, size_t rx_len) { dcd_event_xfer_complete(rhport, ep, xfer->processed_len, XFER_RESULT_SUCCESS, true); } - if (ep == 0) { - EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK; - } else { + if (ep != 0) { uint8_t rx_res = data.isochronous[ep] ? USBFS_EP_R_RES_NYET : (xfer->valid ? USBFS_EP_R_RES_ACK : USBFS_EP_R_RES_NAK); @@ -173,10 +185,11 @@ void dcd_int_handler(uint8_t rhport) { if (status & USBFS_INT_FG_TRANSFER) { uint8_t ep = USBFS_INT_ST_MASK_UIS_ENDP(USBOTG_FS->INT_ST); uint8_t token = USBFS_INT_ST_MASK_UIS_TOKEN(USBOTG_FS->INT_ST); + uint16_t rx_len = USBOTG_FS->RX_LEN; + USBOTG_FS->INT_FG = USBFS_INT_FG_TRANSFER; switch (token) { case PID_OUT: { - uint16_t rx_len = USBOTG_FS->RX_LEN; update_out(rhport, ep, rx_len); break; } @@ -198,7 +211,6 @@ void dcd_int_handler(uint8_t rhport) { break; } - USBOTG_FS->INT_FG = USBFS_INT_FG_TRANSFER; } else if (status & USBFS_INT_FG_BUS_RST) { data.ep0_tog = true; data.xfer[0][TUSB_DIR_OUT].max_size = 64; |
