2019-07-18 11:31 PM
program EP0 for an simple IN transmit
epIn->DIEPINT = -1; //clear ints
epIn->DIEPTSIZ &=~ (USB_OTG_DIEPTSIZ_PKTCNT_Msk | USB_OTG_DIEPTSIZ_XFRSIZ_Msk);
epIn->DIEPTSIZ |= (numPackets << USB_OTG_DIEPTSIZ_PKTCNT_Pos) | (len << USB_OTG_DIEPTSIZ_XFRSIZ_Pos);
//set pointer to data (in ram, 4 byte aligned)
epIn->DIEPDMA = (uintptr_t)data;
//go (i have tried EVERY POSSIBLE BIT COMBINTATION HERE, not just these two)
epIn->DIEPCTL |= USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA;
yes, data is 4-byte aligned
length is 18
packet count is 1
then you wait for interrupt..it comes, and what do we see?
chip sent a zero sized packet instead, and claimed fifo undrran. all the while it had DMA pointer set, and could have slurped up all the data it wanted!
what gives?
in interrupt for EP0 in, i see this
out0.DIEPCTL = 0x00008000
out0.DIEPINT = 0x000020D2
out0.DIEPTSIZ = 0x00080012
out0.DIEPDMA = 0x20000004
out0.DTXFSTS = 0x00000020
I've spent *A WEEK* trying every which way to get this thing to send a reply to GET_DESCRIPTOR **USING DMA**, no luck. all i can get it to do is send a ZLP
i even tried writing to fifo (so i can send PIO, RX via DMA since RX path works)
no go
yes yes yes i know: i can use the st library, but that is not an option, and the docs SHOULD be good enough to actually use them to make the thing work, no?
complete code attached
Solved! Go to Solution.
2019-07-19 12:23 AM
Of course just as i wrote the angry poist, i figured it out
(turns out that the synopsys controller is utter crap and it is VERY VERY EASY to wedge it into a weird state)
for example, try to set EPDIS twice in a row. until you power cycle the controller, that EP will never again work!
2019-07-18 11:34 PM
.
2019-07-18 11:41 PM
it looks like DMA never sent my data to the FIFO
except .. .WTF??? how can DMA mess up that badly? and how can the controller?
and yes i reliaze that
out0.DIEPCTL = 0x00008000
loks supicious, but it ALWAYS Reads that way. somehow for EP0, MPSIZ field always reads as zero, no matter what was written there (i wrote 64)
2019-07-19 12:23 AM
Of course just as i wrote the angry poist, i figured it out
(turns out that the synopsys controller is utter crap and it is VERY VERY EASY to wedge it into a weird state)
for example, try to set EPDIS twice in a row. until you power cycle the controller, that EP will never again work!
2019-07-19 01:28 AM
@dmitrygr
Can you please tell us what exactly was the cause for the problem you described? Was it the mentioned EPDIS being set twice, or something else?
Thanks,
JW
2019-07-19 09:48 AM
yes, in a convoluted way. basically, it is NEVER safe to do this to disable an EP
epIn->DIEPCTL |= USB_OTG_DIEPCTL_EPDIS
you should instead use this
if (epIn->DIEPCTL & USB_OTG_DIEPCTL_EPENA) {
epIn->DIEPCTL |= USB_OTG_DIEPCTL_EPDIS;
while (epIn->DIEPCTL & USB_OTG_DIEPCTL_EPDIS);
}
because if EP is not enabled (as per the core's weird ideas of when that is), disabling it will wedge the EP forever
2019-07-20 04:43 AM
Thanks for sharing this piece of information, fills in part of the puzzle.
Yes, the Synopsys OTG is huge, laden with various, obviously historically-given and often badly designed, gotchas, resulting in very fragile handling; and all this accompanied by grossly inadequate (to be polite) documentation.
EPDIS was puzzling me for a long time, as its handling changes throughout various versions of the drivers (in various incarnations, including the linux "gadget" driver), throughout various settings of the IP (e.g. DMA/non-DMA; but also different for - what's not available in STM32 due to settings when the IP was "instantiated" into silicon - scatter-gather DMA), and also various versions of the IP as given in the - by ST undocumented - GSNPSID register (offset 0x40). For example, in the newer-than-in-'F4 version of Synopsys OTG in the 'L4, the procedure recommended by the respective RM to disable the EP is to simply set DIEPCTL to 0.
I don't use DMA and after lots of investigation I came to the conclusion that in that case it's safe to ignore it.
JW