STM32F446 Synopsys OTG EP0 IN endpoint sending only zero length packets
Hi,
I'm trying to get the infamous Synopsys OTG module to work. I'm not using the STM32Cube libraries, instead I'm rolling my own HAL based on the reference manual, which, as some have noted elsewhere in this forum, is pretty bad.
Currently I'm stuck because the core is transmitting zero length packets in response to IN transfers on endpoint 0, no matter what I put in the FIFO or program in DIEPCTL0 and DIEPTSIZ0. Here's my code:
static void
_ep0_write(struct usb_module *module, size_t ep, const uint8_t *data, size_t length)
{
assert(module != NULL);
assert(data != NULL || length == 0);
assert((_OTG_DTXFSTS(module->base, ep) & _OTG_DTXFSTS_INEPTFSAV_MASK) * 4 >= length);
_OTG_DIEPTSIZ0(module->base) = _OTG_DIEPTSIZ0_PKTCNT_VALUE(1)
| _OTG_DIEPTSIZ0_XFRSIZ_VALUE(length);
_OTG_DIEPCTL0(module->base) |= _OTG_DIEPCTL0_EPENA_MASK
| _OTG_DIEPCTL0_CNAK_MASK;
size_t word_count = (length + 3) / 4;
for (size_t w = 0; w < word_count; w++) {
// Yes we're probably reading memory outside of the provided buffer
// if the length is not a whole number of words.
// That's fine for now.
uint32_t word = (uint32_t)data[(w * 4) + 0] << 0
| (uint32_t)data[(w * 4) + 1] << 8
| (uint32_t)data[(w * 4) + 2] << 16
| (uint32_t)data[(w * 4) + 3] << 24;
_OTG_DFIFO(module->base, ep) = word;
}
}
For instance, when trying to transmit the 18 bytes of the device descriptor, this function call seems to work fine. After writing to the FIFO, DIEPTSIZ0 reads 0x80000 as expected. But then the core proceeds to transmitting a ZLP as if I didn't push anything in the FIFO and set XFRSIZ to 0 ..
In case that matters, the TX0 FIFO is configured with a size of 0x200 words, the maximum allowed and the initial value.
One abnormal thing though: when the host asks again for the device descriptor (because of course it's not satisfied with the zero length packet we responded with), and this function is called again, we end up hitting the assert on line 6. I'm not sure what's up with that, maybe this indicates the core messed up something ..
I'm this close to scrapping the whole board and finding another MCU with a not totally insane USB implementation ..
Any ideas? The rest of the code is available here : https://git.sr.ht/~toun/keyboard/tree/trunk/item/src/hal/usb.c
