Skip to content

Commit 506e936

Browse files
committed
pbio/drv/usb/usb_ev3.c: Defer setting USB_CSRL0_RXRDYC
This may cause spurious failures in handling control transfers, which can result in a SET_ADDRESS being abandoned instead of completing.
1 parent 22f135e commit 506e936

File tree

1 file changed

+21
-4
lines changed

1 file changed

+21
-4
lines changed

lib/pbio/drv/usb/usb_ev3.c

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,6 @@ static void usb_device_intr(void) {
540540

541541
setup_pkt.u[0] = HWREG(USB0_BASE + USB_O_FIFO0);
542542
setup_pkt.u[1] = HWREG(USB0_BASE + USB_O_FIFO0);
543-
HWREGH(USB0_BASE + USB_O_CSRL0) = USB_CSRL0_RXRDYC;
544543

545544
switch (setup_pkt.s.bmRequestType & BM_REQ_TYPE_MASK) {
546545
case BM_REQ_TYPE_STANDARD:
@@ -681,11 +680,29 @@ static void usb_device_intr(void) {
681680
}
682681
}
683682

683+
// Note regarding the setting of the USB_CSRL0_RXRDYC bit:
684+
// The Linux kernel has a comment saying
685+
// > For zero-data requests we want to delay the STATUS stage to avoid SETUPEND errors.
686+
// but also that
687+
// > If we write data, the controller acts happier if we enable the TX FIFO right away
688+
// We implement something similar but not identical. In general, we wait until
689+
// we have completely processed the request and decided what we're going to do
690+
// before we indicate that we are ready to progress to the next phase.
691+
// We do not support any requests that require receiving data from the host,
692+
// only zero-data requests or those that require sending data to the host.
693+
// For errors or zero-data requests, we set USB_CSRL0_RXRDYC and USB_CSRL0_DATAEND
694+
// at the same time so that we don't get spurious SETUPEND errors
695+
// (which we treat as a command failure). For requests that require sending data,
696+
// we set USB_CSRL0_RXRDYC while we get ready to copy data into the FIFO.
697+
684698
if (!handled) {
685-
// send stall
686-
HWREGH(USB0_BASE + USB_O_CSRL0) = USB_CSRL0_STALL;
699+
// Indicate we read the packet, but also send stall
700+
HWREGH(USB0_BASE + USB_O_CSRL0) = USB_CSRL0_RXRDYC | USB_CSRL0_STALL;
687701
} else {
688702
if (pbdrv_usb_setup_data_to_send) {
703+
// Indicate we read the packet
704+
HWREGH(USB0_BASE + USB_O_CSRL0) = USB_CSRL0_RXRDYC;
705+
689706
// Clamp by host request size
690707
if (setup_pkt.s.wLength < pbdrv_usb_setup_data_to_send_sz) {
691708
pbdrv_usb_setup_data_to_send_sz = setup_pkt.s.wLength;
@@ -701,7 +718,7 @@ static void usb_device_intr(void) {
701718
}
702719
} else {
703720
// Just get ready to send ACK, no data
704-
HWREGH(USB0_BASE + USB_O_CSRL0) = USB_CSRL0_DATAEND;
721+
HWREGH(USB0_BASE + USB_O_CSRL0) = USB_CSRL0_RXRDYC | USB_CSRL0_DATAEND;
705722
}
706723
}
707724
} else if (pbdrv_usb_setup_data_to_send) {

0 commit comments

Comments
 (0)