I am learning to build USB device mode driver on stm32f407 which has a USB_OTG_FS core on it.
When the setup packet was received, "RXFLVL" (RxFIFO not empty) interrupt was invoked and to my understand, this is the place where the device should handle the setup request and reply to host.
Looking at the standard USB library code from ST I found ST's library instead waits for "OEPINT" (out endpoint itnerrupt) and process the setup request there. This makes sense because the "STUP" bit should be set in the OTG_FS_DOEPINT register indicating that setup phase is done.
However in my situation the out endpoint interrupt was never invoked after I got rx-queue level interrupt. What am I missing here?
Thanks in advance.
I wrote my own usb device driver which should do the same thing as what ST's usb lib does.
The Synopsys OTG USB module used in STM32 is a complex machine and is picky about the sequencing of user's events in program. This is because its internal state machine is advanced in some states by events from the USB bus and in others by access from the program. Its complexity is given by historical development of this module, and also by the module's ability to be configured (when instantiated into silicon by the mcu manufacturer) with either of two types of DMA or without DMA at all.
In other words, you have to follow exactly the (quite poorly worded) description in the Operational model subchapter of OTG USB chapter in RM. In this particular case, you have to handle both the RXFLVL and OEPINT interrupts accordingly. In RXFLVL interrupt, you have to recognize the various status indicating reason for the interrupt (and in case of SETUP packet pattern read out the setup packet from FIFO; in case of SETUP stage done pattern just reading OTG_FS_GRXSTSP which in turn throws the OEPINT interrupt (* )), and then in the OEPINT interrupt you process the received SETUP packet. Alternatively, you can ignore the OEPINT interrupt and process the SETUP packet in (*), but the former method provides a uniform handling for both SETUP and generic OUT data, and also for both DMA and non-DMA operation.