summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHiFiPhile <[email protected]>2026-05-23 13:02:53 +0200
committerHiFiPhile <[email protected]>2026-05-23 13:02:53 +0200
commite14b0e8514ace0043472d9cb0779152fccade1ee (patch)
tree3f8f33a551caaef959ff8b0ff08d511f7a547e7d
parentb3141bb259dca3c1a3de81f4d8d0ef5249a6579a (diff)
dcd/ch32fs: set EP to NAK earlier to reduce spuroius transfer
Signed-off-by: HiFiPhile <[email protected]>
-rw-r--r--src/portable/wch/dcd_ch32_usbfs.c22
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;