void Usb_t::Init() { // GPIO PinSetupAlterFunc(GPIOA, 11, omOpenDrain, pudNone, AF10); PinSetupAlterFunc(GPIOA, 12, omOpenDrain, pudNone, AF10); PinSetupIn(GPIOA, 9, pudPullDown); // OTG FS clock enable and reset rccEnableOTG_FS(FALSE); rccResetOTG_FS(); // Enable IRQ nvicEnableVector(STM32_OTG1_NUMBER, CORTEX_PRIORITY_MASK(IRQ_PRIO_LOW)); // Thread PThread = chThdCreateStatic(waUsbThd, sizeof(waUsbThd), LOWPRIO, UsbThread, NULL); // ==== OTG init ==== // Forced device mode, USB turn-around time = TRDT_VALUE, Full Speed 1.1 PHY, 0 tuning OTG_FS->GUSBCFG = GUSBCFG_FDMOD | GUSBCFG_TRDT(TRDT) | GUSBCFG_PHYSEL | 0; OTG_FS->DCFG = 0x02200000 | DCFG_NZLSOHSK | DCFG_DSPD_FS11; // Full-speed (other options are not available, though) OTG_FS->PCGCCTL = 0; // Nothing is stopped or gated OTG_FS->GCCFG = GCCFG_VBUSASEN | GCCFG_VBUSBSEN | GCCFG_PWRDWN /*| GCCFG_NOVBUSSENS*/; // Core reset and delay of at least 3 PHY cycles OTG_FS->GRSTCTL = GRSTCTL_CSRST; while((OTG_FS->GRSTCTL & GRSTCTL_CSRST) != 0); __NOP(); __NOP(); // Wait AHB idle condition while((OTG_FS->GRSTCTL & GRSTCTL_AHBIDL) == 0); __NOP(); __NOP(); OTG_FS->GAHBCFG = 0; // Interrupts on TXFIFOs half empty, mask interrupts // ==== Endpoints ==== for(uint8_t i=0; i<USB_EP_CNT; i++) Ep[i].SelfN = i; // Ep0 //OTG_FS->ie[0].DIEPCTL = 0x11; // size = 8 Ep[0].InMaxSz = EP0_SZ; Ep[0].OutMaxSz = EP0_SZ; // Clear all pending Device Interrupts, only the USB Reset interrupt is required initially OTG_FS->DIEPMSK = 0; OTG_FS->DOEPMSK = 0; OTG_FS->DAINTMSK = 0; OTG_FS->GINTMSK = GINTMSK_ENUMDNEM | GINTMSK_USBRSTM /*| GINTMSK_USBSUSPM | GINTMSK_ESUSPM |*/; OTG_FS->GINTSTS = 0xFFFFFFFF; // Clear all pending IRQs, if any OTG_FS->GAHBCFG |= GAHBCFG_GINTMSK; // Global interrupts enable }
/** * @brief Configures and activates the USB peripheral. * @note Starting the OTG cell can be a slow operation carried out with * interrupts disabled, perform it before starting time-critical * operations. * * @param[in] usbp pointer to the @p USBDriver object * * @notapi */ void usb_lld_start(USBDriver *usbp) { stm32_otg_t *otgp = usbp->otg; if (usbp->state == USB_STOP) { /* Clock activation.*/ #if STM32_USB_USE_OTG1 if (&USBD1 == usbp) { /* OTG FS clock enable and reset.*/ rccEnableOTG_FS(FALSE); rccResetOTG_FS(); /* Enables IRQ vector.*/ nvicEnableVector(STM32_OTG1_NUMBER, CORTEX_PRIORITY_MASK(STM32_USB_OTG1_IRQ_PRIORITY)); } #endif #if STM32_USB_USE_OTG2 if (&USBD2 == usbp) { /* OTG HS clock enable and reset.*/ rccEnableOTG_HS(FALSE); rccResetOTG_HS(); /* Workaround for the problem described here: http://forum.chibios.org/phpbb/viewtopic.php?f=16&t=1798 */ rccDisableOTG_HSULPI(TRUE); /* Enables IRQ vector.*/ nvicEnableVector(STM32_OTG2_NUMBER, CORTEX_PRIORITY_MASK(STM32_USB_OTG2_IRQ_PRIORITY)); } #endif /* Creates the data pump threads in a suspended state. Note, it is created only once, the first time @p usbStart() is invoked.*/ usbp->txpending = 0; if (usbp->thd_ptr == NULL) usbp->thd_ptr = usbp->thd_wait = chThdCreateI(usbp->wa_pump, sizeof usbp->wa_pump, STM32_USB_OTG_THREAD_PRIO, usb_lld_pump, usbp); /* - Forced device mode. - USB turn-around time = TRDT_VALUE. - Full Speed 1.1 PHY.*/ otgp->GUSBCFG = GUSBCFG_FDMOD | GUSBCFG_TRDT(TRDT_VALUE) | GUSBCFG_PHYSEL; /* 48MHz 1.1 PHY.*/ otgp->DCFG = 0x02200000 | DCFG_DSPD_FS11; /* PHY enabled.*/ otgp->PCGCCTL = 0; /* Internal FS PHY activation.*/ #if defined(BOARD_OTG_NOVBUSSENS) otgp->GCCFG = GCCFG_NOVBUSSENS | GCCFG_VBUSASEN | GCCFG_VBUSBSEN | GCCFG_PWRDWN; #else otgp->GCCFG = GCCFG_VBUSASEN | GCCFG_VBUSBSEN | GCCFG_PWRDWN; #endif /* Soft core reset.*/ otg_core_reset(usbp); /* Interrupts on TXFIFOs half empty.*/ otgp->GAHBCFG = 0; /* Endpoints re-initialization.*/ otg_disable_ep(usbp); /* Clear all pending Device Interrupts, only the USB Reset interrupt is required initially.*/ otgp->DIEPMSK = 0; otgp->DOEPMSK = 0; otgp->DAINTMSK = 0; if (usbp->config->sof_cb == NULL) otgp->GINTMSK = GINTMSK_ENUMDNEM | GINTMSK_USBRSTM /*| GINTMSK_USBSUSPM | GINTMSK_ESUSPM |*/; else otgp->GINTMSK = GINTMSK_ENUMDNEM | GINTMSK_USBRSTM /*| GINTMSK_USBSUSPM | GINTMSK_ESUSPM */ | GINTMSK_SOFM; otgp->GINTSTS = 0xFFFFFFFF; /* Clears all pending IRQs, if any. */ /* Global interrupts enable.*/ otgp->GAHBCFG |= GAHBCFG_GINTMSK; } }