cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F446 Synopsys OTG EP0 IN endpoint sending only zero length packets

TDani.2
Associate II

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

1 ACCEPTED SOLUTION

Accepted Solutions
TDani.2
Associate II

Turns out I forgot to clean up some remains from the USB driver I was porting this from. After writing to the TX FIFO, my program tried to clear the NAK bit of the IN endpoint (setting CNAK of DIEPCTL0). Now the module successfuly sends the packet with the correct length.

I also made sure to flush all TX and RX FIFOs on reset. I don't think that's related but this seems to fix the TX FIFO overflowing despite DIEPTSIZ reporting that all data was consumed.

View solution in original post

5 REPLIES 5
Issamos
Lead II

Hello @TDani.2 

To make your question clearer. I suggest you to attach the HAL and reference Manuel that you are using on your application.

Best regards.

II

Sure thing, I've added a link to my repo in the question.

Hello again and thank you for your feedback.

I think that the UM1021 can give you some help.

Best regards.

II

Thanks for your suggestion. I might have been a bit unclear by saying I'm rolling my own HAL though: I ditched the whole STM32Cube code, and am not using the standard interface documented in UM1021 either. It's all custom and project specific. So unfortunately this does not help me diagnose what's wrong with the low level driver code in this case.

TDani.2
Associate II

Turns out I forgot to clean up some remains from the USB driver I was porting this from. After writing to the TX FIFO, my program tried to clear the NAK bit of the IN endpoint (setting CNAK of DIEPCTL0). Now the module successfuly sends the packet with the correct length.

I also made sure to flush all TX and RX FIFOs on reset. I don't think that's related but this seems to fix the TX FIFO overflowing despite DIEPTSIZ reporting that all data was consumed.