AnsweredAssumed Answered

[stm32f4 - discovery] USB OTG FS in device mode - initialization

Question asked by dzikowski.bartlomiej on Jul 30, 2013
I set all registers as shown in Reference Manual.  When I preview OTG_FS_GRXSTS register (value: 0x004c0080) I know that the host sent SETUP packet to my discovery board. The first SETUP packet should contain GET DESCRIPTOR request. When I try to read data as my last line of code shows, value of variable named 'a' don't indicates GET DESCRIPTOR request. I think I have trouble reading data of RxFIFO, any idea?

    RCC_AHB1ENR_GPIOAEN_BB = SET;
    GPIO_Port_Cfg(GPIOA, GPIO_Pin_8 | GPIO_Pin_11 | GPIO_Pin_12, GPIO_Mode_AF, GPIO_Type_PP, GPIO_Speed_100MHz, GPIO_Pull_None);
    GPIO_Port_Cfg(GPIOA, GPIO_Pin_9, GPIO_Mode_AF, GPIO_Type_OD, GPIO_Speed_100MHz, GPIO_Pull_None);
    GPIO_Port_Cfg(GPIOA, GPIO_Pin_10, GPIO_Mode_AF, GPIO_Type_OD, GPIO_Speed_100MHz, GPIO_Pull_Up);
    GPIO_Port_AF_Cfg(GPIOA, GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12, GPIO_AF_OTG_FS);
   
    RCC_AHB2ENR_OTGFSEN_BB = SET;
   
    /*----------- CORE INIT ----------*/
   
    USB_FS_GAHBCFG GAHBCFG;
    USB_FS_GUSBCFG GUSBCFG;
    USB_FS_GINTMSK GINTMSK;
   
    /*
    Program the following fields in the OTG_FS_GAHBCFG register:
    - Global interrupt mask bit GINTMSK = 1
    - RxFIFO non-empty (RXFLVL bit in OTG_FS_GINTSTS)
    - Periodic TxFIFO empty level
    */
    GAHBCFG.reg_val = USB_OTG_FS->GLOBAL.GAHBCFG;
    GAHBCFG.bits.GINTMSK = 1;
    GAHBCFG.bits.TXFELVL = 0;
    USB_OTG_FS->GLOBAL.GAHBCFG = GAHBCFG.reg_val;
   
    /*
    Program the following fields in the OTG_FS_GUSBCFG register:
    - HNP capable bit
    - SRP capable bit
    - FS timeout calibration field
    - USB turnaround time field
    */
    GUSBCFG.reg_val = USB_OTG_FS->GLOBAL.GUSBCFG;
    GUSBCFG.bits.TOCAL = 5;
    GUSBCFG.bits.SRPCAP = 0;
    GUSBCFG.bits.HNPCAP = 0;
    GUSBCFG.bits.TRDT = 15;
    USB_OTG_FS->GLOBAL.GUSBCFG = GUSBCFG.reg_val;
   
    /*
    Unmask the following bits in the OTG_FS_GINTMSK register:
    - OTG interrupt mask
    - Mode mismatch interrupt mask
    */
    GINTMSK.reg_val = USB_OTG_FS->GLOBAL.GINTMSK;
    GINTMSK.bits.MMISM = 1;
    GINTMSK.bits.OTGINT = 1;
    USB_OTG_FS->GLOBAL.GINTMSK = GINTMSK.reg_val;
   
    if( ((USB_FS_GINTSTS)USB_OTG_FS->GLOBAL.GINTSTS).bits.CMOD != 0)
    {
        GUSBCFG.reg_val = USB_OTG_FS->GLOBAL.GUSBCFG;
        GUSBCFG.bits.FDMOD = 1;
        USB_OTG_FS->GLOBAL.GUSBCFG = GUSBCFG.reg_val;
   
        while( ((USB_FS_GUSBCFG)USB_OTG_FS->GLOBAL.GUSBCFG).bits.FDMOD == 1);
    }
   
    /*----------- CORE INIT END ----------*/
   
    /*----------- DEVICE INIT ----------*/
   
    USB_FS_DCFG DCFG;
    USB_FS_GCCFG GCCFG;
   
    /*
    Program the following fields in the OTG_FS_DCFG register:
    - Device speed
    - Non-zero-length status OUT handshake
    */
    DCFG.reg_val = USB_OTG_FS->DEVICE.DCFG;
    DCFG.bits.DSPD = 3;
    DCFG.bits.NZLSOHSK = 1;
    USB_OTG_FS->DEVICE.DCFG = DCFG.reg_val;
   
    /*
    Program the OTG_FS_GINTMSK register to unmask the following interrupts:
    - USB reset
    - Enumeration done
    - Early suspend
    - USB suspend
    - SOF
    */
    GINTMSK.reg_val = USB_OTG_FS->GLOBAL.GINTMSK;
    GINTMSK.bits.SOFM = 1;
    GINTMSK.bits.RXFLVLM = 1;
    GINTMSK.bits.ESUSPM = 1;
    GINTMSK.bits.USBSUSPM = 1;
    GINTMSK.bits.USBRST = 1;
    GINTMSK.bits.ENUMDNEM = 1;
    USB_OTG_FS->GLOBAL.GINTMSK = GINTMSK.reg_val;
   
    /*
    Program the VBUSBSEN bit in the OTG_FS_GCCFG register to enable VBUS sensing
    in B-device mode and supply the 5 volts across the pull-up resistor on the DP line.
     */
    GCCFG.reg_val = USB_OTG_FS->GLOBAL.GCCFG;
    GCCFG.bits.VBUSBSEN = 1;
    GCCFG.bits.PWRDWN = 1;
    USB_OTG_FS->GLOBAL.GCCFG = GCCFG.reg_val;
   
    /*
    Wait for the USBRST interrupt in OTG_FS_GINTSTS. It indicates that a reset has been
    detected on the USB that lasts for about 10 ms on receiving this interrupt.
    */
    while( ((USB_FS_GINTSTS)USB_OTG_FS->GLOBAL.GINTSTS).bits.USBRST != 1);
   
    /*------- Endpoint initialization on USB reset ------*/
   
    USB_FS_DOEPCTL DOEPCTL;
    USB_FS_DAINTMSK DAINTMSK;
    USB_FS_DIEPMSK DIEPMSK;
    USB_FS_DOEPMSK DOEPMSK;
    USB_FS_GRXFSIZ GRXFSIZ;
    USB_FS_HNPTXFSIZ_DIEPTXF0 HNPTXFSIZ_DIEPTXF0;
    USB_FS_DOEPTSIZ DOEPTSIZ;
   
    /*
    Set the NAK bit for all OUT endpoints
    - SNAK = 1 in OTG_FS_DOEPCTLx (for all OUT endpoints)
    */
    DOEPCTL.reg_val = USB_OTG_FS->DEVICE.DOEP[0].DOEPCTL;
    DOEPCTL.bits.SNAK = 1;
    USB_OTG_FS->DEVICE.DOEP[0].DOEPCTL = DOEPCTL.reg_val;
   
    DOEPCTL.reg_val = USB_OTG_FS->DEVICE.DOEP[1].DOEPCTL;
    DOEPCTL.bits.SNAK = 1;
    USB_OTG_FS->DEVICE.DOEP[1].DOEPCTL = DOEPCTL.reg_val;
   
    DOEPCTL.reg_val = USB_OTG_FS->DEVICE.DOEP[2].DOEPCTL;
    DOEPCTL.bits.SNAK = 1;
    USB_OTG_FS->DEVICE.DOEP[2].DOEPCTL = DOEPCTL.reg_val;
   
    DOEPCTL.reg_val = USB_OTG_FS->DEVICE.DOEP[3].DOEPCTL;
    DOEPCTL.bits.SNAK = 1;
    USB_OTG_FS->DEVICE.DOEP[3].DOEPCTL = DOEPCTL.reg_val;
   
    /*
Unmask the following interrupt bits
    - INEP0 = 1 in OTG_FS_DAINTMSK (control 0 IN endpoint)
    - OUTEP0 = 1 in OTG_FS_DAINTMSK (control 0 OUT endpoint)
    - STUP=1 in DOEPMSK
    - XFRC = 1 in DOEPMSK
    - XFRC = 1 in DIEPMSK
    - TOC = 1 in DIEPMSK
    */
    DAINTMSK.reg_val = USB_OTG_FS->DEVICE.DAINTMSK;
    DAINTMSK.bits.IEPM = 1;
    DAINTMSK.bits.OEPM = 1;
    USB_OTG_FS->DEVICE.DAINTMSK = DAINTMSK.reg_val;
   
    DIEPMSK.reg_val = USB_OTG_FS->DEVICE.DIEPMSK;
    DIEPMSK.bits.XFRCM = 1;
    DIEPMSK.bits.TOM = 1;
    USB_OTG_FS->DEVICE.DIEPMSK = DIEPMSK.reg_val;
   
    DOEPMSK.reg_val = USB_OTG_FS->DEVICE.DOEPMSK;
    DOEPMSK.bits.XFRCM = 1;
    DOEPMSK.bits.STUPM = 1;
    USB_OTG_FS->DEVICE.DOEPMSK = DOEPMSK.reg_val;
   
    /*
    Set up the Data FIFO RAM for each of the FIFOs
    - Program the OTG_FS_GRXFSIZ register, to be able to receive control OUT data
    and setup data. If thresholding is not enabled, at a minimum, this must be equal to
    1 max packet size of control endpoint 0 + 2 Words (for the status of the control
    OUT data packet) + 10 Words (for setup packets).
    - Program the OTG_FS_TX0FSIZ register (depending on the FIFO number chosen)
    to be able to transmit control IN data. At a minimum, this must be equal to 1 max
    packet size of control endpoint 0.
    */
    GRXFSIZ.bits.RXFD = 128;
    USB_OTG_FS->GLOBAL.GRXFSIZ = GRXFSIZ.reg_val;
   
    HNPTXFSIZ_DIEPTXF0.bits.NPTXFSA_TX0FSA = 128;
    HNPTXFSIZ_DIEPTXF0.bits.NPTXFD_TX0FD = 64;
    USB_OTG_FS->GLOBAL.HNPTXFSIZ_DIEPTXF0 = HNPTXFSIZ_DIEPTXF0.reg_val;
   
    /*
    Program the following fields in the endpoint-specific registers for control OUT endpoint
    0 to receive a SETUP packet
    - STUPCNT = 3 in OTG_FS_DOEPTSIZ0 (to receive up to 3 back-to-back SETUP
    packets)
    */
    DOEPTSIZ.bits.XFRSIZ = 30;
    DOEPTSIZ.bits.PKTCNT = 1;
    DOEPTSIZ.bits.RXDPID_STUPCNT = 3;
    USB_OTG_FS->DEVICE.DOEP[0].DOEPTSIZ = DOEPTSIZ.reg_val;
   
    while( ((USB_FS_GINTSTS)USB_OTG_FS->GLOBAL.GINTSTS).bits.ENUMDNE != 1);
   
    /*------- Endpoint initialization on USB reset END ------*/
   
    /*------ Endpoint initialization on enumeration completion -------*/
   
    /*------ Endpoint activation -------*/
   
    USB_FS_DIEPCTL DIEPCTL;
   
    /*
    Program the MPSIZ field in OTG_FS_DIEPCTL0 to set the maximum packet size. This
    step configures control endpoint 0. The maximum packet size for a control endpoint
    depends on the enumeration speed.
    */
    DIEPCTL.reg_val = USB_OTG_FS->DEVICE.DIEP[0].DIEPCTL;
    DIEPCTL.bits.MPSIZ = 0;
    DIEPCTL.bits.EPENA = 1;
    USB_OTG_FS->DEVICE.DIEP[0].DIEPCTL = DIEPCTL.reg_val;
   
    DOEPCTL.reg_val = USB_OTG_FS->DEVICE.DOEP[0].DOEPCTL;
    DOEPCTL.bits.MPSIZ = 0;
    DIEPCTL.bits.EPENA = 1;
    USB_OTG_FS->DEVICE.DOEP[0].DOEPCTL = DOEPCTL.reg_val;
   
    /*------ Endpoint initialization on enumeration completion END -------*/
   
    /*------ Endpoint activation END -------*/
   
    while( ((USB_FS_GINTSTS)USB_OTG_FS->GLOBAL.GINTSTS).bits.RXFLVL != 1);
   
    uint32_t a = *((uint32_t*)(0x50001000));

Outcomes