@@ -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