EP0 IN transfer times out
For learning (and suffering) purposes I am trying to write my own USB Driver in device mode. Right now I am just trying to successfully enumerate the device. So far I am able to read SETUP packets but when writing to EP0 (IN transfer) the requests seem to timeout at 5 seconds (seeing this through Wireshark). I am using a STM32F401CCU6 chip.
For example, this is what happens when a GET_DESCRIPTOR request is made:
USB URB
[Source: host]
[Destination: 3.0.0]
URB id: 0xffff9d142a6f8900
URB type: URB_SUBMIT ('S')
URB transfer type: URB_CONTROL (0x02)
Endpoint: 0x80, Direction: IN
Device: 0
URB bus id: 3
Device setup request: relevant ('\0')
Data: not present ('<')
URB sec: 1688842172
URB usec: 857980
URB status: Operation now in progress (-EINPROGRESS) (-115)
URB length [bytes]: 64
Data length [bytes]: 0
[Response in: 58]
Interval: 0
Start frame: 0
Copy of Transfer Flags: 0x00000200, Dir IN
Number of ISO descriptors: 0
Setup Data
bmRequestType: 0x80
bRequest: GET DESCRIPTOR (6)
Descriptor Index: 0x00
bDescriptorType: DEVICE (0x01)
Language Id: no language specified (0x0000)
wLength: 64
And the answer generated by my MCU (and code):
USB URB
[Source: 3.0.0]
[Destination: host]
URB id: 0xffff9d142a6f8900
URB type: URB_COMPLETE ('C')
URB transfer type: URB_CONTROL (0x02)
Endpoint: 0x80, Direction: IN
Device: 0
URB bus id: 3
Device setup request: not relevant ('-')
Data: present ('\0')
URB sec: 1688842178
URB usec: 31400
URB status: No such file or directory (-ENOENT) (-2)
URB length [bytes]: 64
Data length [bytes]: 64
[Request in: 57]
[Time from request: 5.173420000 seconds]
Unused Setup Header
Interval: 0
Start frame: 0
Copy of Transfer Flags: 0x00000200, Dir IN
Number of ISO descriptors: 0
DEVICE DESCRIPTOR
bLength: 18
bDescriptorType: 0x01 (DEVICE)
bcdUSB: 0x0200
bDeviceClass: Communications and CDC Control (0x02)
bDeviceSubClass: 2
bDeviceProtocol: 0
bMaxPacketSize0: 64
idVendor: STMicroelectronics (0x0483)
idProduct: Virtual COM Port (0x5740)
bcdDevice: 0x0100
iManufacturer: 0
iProduct: 0
iSerialNumber: 0
bNumConfigurations: 1
Leftover Capture Data: 000000000000000000000000000000000000000000000000000000000000000000000000…
I don't have a hardware analyzer but it seems like the write request is timing out and is not properly being ended after transmitting the 18 bytes of the device descriptor, therefore the host just fills everything with zeroes until it times outs.
This is how I write to the endpoint:
void usbWrite(uint8_t ep, void* data, uint8_t len) {
USB_OTG_INEndpointTypeDef* endpoint = usbEpin(ep);
volatile uint32_t* fifo = usbEpFifo(ep);
uint16_t wordLen = (len + 3) >> 2;
if (wordLen > endpoint->DTXFSTS) {
return;
}
if ((ep != 0) && (endpoint->DIEPCTL & USB_OTG_DIEPCTL_EPENA)) {
return;
}
endpoint->DIEPTSIZ = (1 << USB_OTG_DIEPTSIZ_PKTCNT_Pos) | len;
endpoint->DIEPCTL &= ~USB_OTG_DIEPCTL_STALL;
endpoint->DIEPCTL |= USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK;
usbRawWrite(fifo, data, len);
}
void usbRawWrite(volatile uint32_t* fifo, void* data, uint8_t len) {
uint32_t fifoWord;
uint32_t* buffer = (uint32_t*)data;
uint8_t remains = len;
for (uint8_t idx = 0; idx < len; idx += 4, remains -= 4, buffer++) {
switch (remains) {
case 0:
break;
case 1:
fifoWord = *buffer & 0xFF;
*fifo = fifoWord;
break;
case 2:
fifoWord = *buffer & 0xFFFF;
*fifo = fifoWord;
break;
case 3:
fifoWord = *buffer & 0xFFFFFF;
*fifo = fifoWord;
break;
default:
*fifo = *buffer;
break;
}
}
And here is how I am setting up the control endpoints and FIFOS:
#define USB_FIFO_EP0_SZ 0x20
#define MPSIZ_64B 0x00
OTG->GRXFSIZ = USB_FIFO_EP0_SZ;
OTG->DIEPTXF0_HNPTXFSIZ = (USB_FIFO_EP0_SZ << 16) | USB_FIFO_EP0_SZ;
USB_OTG_INEndpointTypeDef* in0 = usbEpin(0);
in0->DIEPCTL |= MPSIZ_64B | USB_OTG_DIEPCTL_SNAK;
USB_OTG_OUTEndpointTypeDef* out0 = usbEpout(0);
out0->DOEPTSIZ = (1 << USB_OTG_DOEPTSIZ_STUPCNT_Pos) | (1 << USB_OTG_DOEPTSIZ_PKTCNT_Pos) | 64;
out0->DOEPCTL |= MPSIZ_64B | USB_OTG_DOEPCTL_CNAK | USB_OTG_DOEPCTL_EPENA;
Any idea as to what I am doing wrong? It is not a board issue as Cube auto generated code works (at least it enumerates)
