As it turns out this routine doesn't need to know, and that is interesting in itself. There are two calls to this routine in driver/usb_dcd_int.c both from DCD_HandleRxStatusQueueLevel_ISR ().
Both of these routines are involved in taking data from the unified Rx FIFO. The handler routine has an instructive comment telling us that it "gets the Status from the top of the FIFO". This 32 bit word describes data on the fifo which follows. It contains the endpoint number, a byte count, and some bits that describe what follows. The two cases that result in a call to USB_OTG_ReadPacket() are:
STS_DATA_UPDT STS_SETUP_UPDTOther cases are just ignored (presumably there is no associated data to be read and the status works describes whatever event might be of interest.
uint32_t *fifo = pdev->regs.DFIFO[0]; dest = USB_OTG_READ_REG32(fifo)32 bit words are read from the FIFO (so the FIFO must pad/align as needed)
The macro to read the device register is nothing mysterious:
#define USB_OTG_READ_REG32(reg) (*(__IO uint32_t *)(reg))The structure indicated by "regs" is interesting. It is in driver/usb_regs.h. It holds pointers to subsections of the USB hardware
typedef struct USB_OTG_core_regs //000h { USB_OTG_GREGS *GREGS; USB_OTG_DREGS *DREGS; USB_OTG_HREGS *HREGS; USB_OTG_INEPREGS *INEP_REGS[USB_OTG_MAX_TX_FIFOS]; USB_OTG_OUTEPREGS *OUTEP_REGS[USB_OTG_MAX_TX_FIFOS]; USB_OTG_HC_REGS *HC_REGS[USB_OTG_MAX_TX_FIFOS]; __IO uint32_t *HPRT0; __IO uint32_t *DFIFO[USB_OTG_MAX_TX_FIFOS]; __IO uint32_t *PCGCCTL; };So we have serveral fifos in an array given by DFIFO. This is initialized in driver/usb_core.c in USB_OTG_SelectCore() as follows:
#define USB_OTG_DATA_FIFO_OFFSET 0x1000 #define USB_OTG_DATA_FIFO_SIZE 0x1000 for (i = 0; i < pdev->cfg.host_channels; i++) { pdev->regs.DFIFO[i] = (uint32_t *)(baseAddress + USB_OTG_DATA_FIFO_OFFSET +\ (i * USB_OTG_DATA_FIFO_SIZE)); }It is funny that a variable "host_channels" gives the count for a device, but that is OK. Indeed, the TRM shows that each endpoint has a FIFO, with endpoint 0 being at offset 0x1000
This same routine -- USB_OTG_SelectCore() -- also sets up the other pointers in this structure, like this:
#define USB_OTG_CORE_GLOBAL_REGS_OFFSET 0x000 #define USB_OTG_DEV_GLOBAL_REG_OFFSET 0x800 #define USB_OTG_DEV_IN_EP_REG_OFFSET 0x900 pdev->regs.GREGS = (USB_OTG_GREGS *) (baseAddress + USB_OTG_CORE_GLOBAL_REGS_OFFSET); pdev->regs.DREGS = (USB_OTG_DREGS *) (baseAddress + USB_OTG_DEV_GLOBAL_REG_OFFSET);
status.d32 = USB_OTG_READ_REG32( &pdev->regs.GREGS->GRXSTSP );This is one of the chip global registers. It is at offset 0x20 and is described as "read and pop receive status". There is a register right next to it that reads the status, but does not pop it.
Tom's Computer Info / tom@mmto.org