Skip to content

Commit

Permalink
stm32: Fix usbfs spurious USB packet transmit on startup
Browse files Browse the repository at this point in the history
Commit cd8d57c added USB double buffering mode on transmits.
However, when enabling double buffering mode, the hardware seems to
always send at least two packets.  Spurious transmissions could cause
the Linux gs_usb driver to get confused, which could lead to the can0
device becoming unavailable on restarts.  Fix by waiting for two USB
packets to be available before enabling the endpoint.

Signed-off-by: Kevin O'Connor <[email protected]>
  • Loading branch information
KevinOConnor committed Oct 5, 2023
1 parent 615db72 commit 043f18d
Showing 1 changed file with 16 additions and 6 deletions.
22 changes: 16 additions & 6 deletions src/stm32/usbfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,8 @@ usb_read_bulk_out(void *data, uint_fast8_t max_len)
return count;
}

static uint32_t bulk_in_push_count, bulk_in_pop_flag;
static uint32_t bulk_in_push_pos, bulk_in_pop_flag;
#define BI_START 2

int_fast8_t
usb_send_bulk_in(void *data, uint_fast8_t len)
Expand All @@ -245,16 +246,26 @@ usb_send_bulk_in(void *data, uint_fast8_t len)
// No buffer space available
return -1;
uint32_t ep = USB_CDC_EP_BULK_IN;
int bufnum = bulk_in_push_count & 1;
bulk_in_push_count++;
uint32_t bipp = bulk_in_push_pos, bufnum = bipp & 1;
bulk_in_push_pos = bipp ^ 1;
btable_write_packet(ep, bufnum, data, len);
writel(&bulk_in_pop_flag, USB_EP_DTOG_RX);

// Check if hardware needs to be notified
uint32_t epr = USB_EPR[ep];
if (epr_is_dbuf_blocking(epr) && readl(&bulk_in_pop_flag)) {
writel(&bulk_in_pop_flag, 0);
USB_EPR[ep] = calc_epr_bits(epr, 0, 0) | USB_EP_DTOG_RX;
if (bipp & BI_START) {
// Two packets are always sent when starting in double
// buffering mode, so wait for second packet before starting.
if (bipp == (BI_START | 1)) {
bulk_in_push_pos = 0;
USB_EPR[ep] = calc_epr_bits(epr, USB_EPTX_STAT
, USB_EP_TX_VALID);
}
} else {
USB_EPR[ep] = calc_epr_bits(epr, 0, 0) | USB_EP_DTOG_RX;
}
}

return len;
Expand Down Expand Up @@ -319,9 +330,8 @@ usb_set_configure(void)
USB_EPR[ep] = calc_epr_bits(USB_EPR[ep], USB_EPRX_STAT, USB_EP_RX_VALID);

ep = USB_CDC_EP_BULK_IN;
bulk_in_push_count = 0;
bulk_in_push_pos = BI_START;
writel(&bulk_in_pop_flag, 0);
USB_EPR[ep] = calc_epr_bits(USB_EPR[ep], USB_EPTX_STAT, USB_EP_TX_VALID);
}


Expand Down

0 comments on commit 043f18d

Please sign in to comment.