added - basic flatUSB_config.h concept added - example JSONs added - CDC request replies fixed
134 lines
4.9 KiB
C
134 lines
4.9 KiB
C
#include "usb_drv.h"
|
|
|
|
#include "flatUSB_config.h"
|
|
|
|
#include "stm32f4xx_hal.h"
|
|
|
|
#include "usb_common.h"
|
|
#include "usb_common_defs.h"
|
|
|
|
// ------------------------
|
|
|
|
#ifdef USB_HIGH_SPEED
|
|
__weak void usbdrv_ulpi_init() {
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
// ------------------------
|
|
|
|
// initialize USB peripheral
|
|
void usbdrv_periph_init() {
|
|
USB_CLOCK_ENABLE();
|
|
|
|
// HAL_Delay(1000);
|
|
|
|
//__HAL_RCC_USB_OTG_FS_ULPI_CLK_ENABLE();
|
|
//__HAL_RCC_USB_OTG_FS_FORCE_RESET();
|
|
//__HAL_RCC_USB_OTG_FS_RELEASE_RESET();
|
|
|
|
#if defined(USB_STM32H7)
|
|
SET_BIT(USBG->GUSBCFG, USB_OTG_GUSBCFG_PHYSEL); // select the internal FS PHY
|
|
|
|
WAIT_FOR_nBIT_DELAY(USBG->GRSTCTL, USB_OTG_GRSTCTL_AHBIDL, 1);
|
|
|
|
SET_BIT(USBG->GRSTCTL, USB_OTG_GRSTCTL_CSRST); // reset the USB core
|
|
HAL_Delay(1);
|
|
WAIT_FOR_BIT_DELAY(USBG->GRSTCTL, USB_OTG_GRSTCTL_CSRST, 1);
|
|
#else
|
|
|
|
#if defined(USB_HIGH_SPEED)
|
|
CLEAR_BIT(USBG->GUSBCFG, USB_OTG_GUSBCFG_PHYSEL); // select the external HS PHY
|
|
CLEAR_BIT(USBG->GUSBCFG, USB_OTG_GUSBCFG_TSDPS);
|
|
CLEAR_BIT(USBG->GUSBCFG, USB_OTG_GUSBCFG_ULPIFSLS);
|
|
|
|
CLEAR_BIT(USBG->GUSBCFG, USB_OTG_GUSBCFG_ULPIEVBUSD);
|
|
CLEAR_BIT(USBG->GUSBCFG, USB_OTG_GUSBCFG_ULPIEVBUSI);
|
|
// SET_BIT(USBG->GUSBCFG, USB_OTG_GUSBCFG_PHYSEL);
|
|
|
|
SET_BIT(USBG->GRSTCTL, USB_OTG_GRSTCTL_CSRST); // reset USB core
|
|
HAL_Delay(1);
|
|
WAIT_FOR_BIT(USBG->GRSTCTL, USB_OTG_GRSTCTL_CSRST);
|
|
|
|
usbdrv_ulpi_init(); // initialize PHY
|
|
#endif
|
|
|
|
#endif
|
|
CLEAR_BIT(USBG->GCCFG, USB_OTG_GCCFG_PWRDWN); // power the internal transceiver peripheral
|
|
|
|
CLEAR_BIT(USBG->GAHBCFG, USB_OTG_GAHBCFG_GINT); // mask all interrupts for now
|
|
CLEAR_BIT(USBG->GUSBCFG, USB_OTG_GUSBCFG_HNPCAP | USB_OTG_GUSBCFG_SRPCAP); // disable HNP and SRP
|
|
WRITE_FIELD(USBG->GUSBCFG, USB_OTG_GUSBCFG_TRDT, TRDT_VALUE); // set TRDT according to the RM
|
|
// WRITE_FIELD(USBG->GUSBCFG, USB_OTG_GUSBCFG_TOCAL, TOCAL_VALUE); // set TOCAL
|
|
CLEAR_BIT(USBG->GUSBCFG, USB_OTG_GUSBCFG_FHMOD); // clear Host mode forcing
|
|
SET_BIT(USBG->GUSBCFG, USB_OTG_GUSBCFG_FDMOD); // force Device mode
|
|
|
|
HAL_Delay(25); // wait for Device mode forcing propagation
|
|
WAIT_FOR_BIT(USBG->GINTSTS, 0b1);
|
|
|
|
// SET_BIT(USBD->DCTL, USB_OTG_DCTL_SDIS); // soft disconnect peripheral (should be upper, but since it's controlled by a Device register, cannot be set before switching to device mode)
|
|
|
|
#if defined(USB_STM32H7)
|
|
CLEAR_BIT(USBG->GCCFG, USB_OTG_GCCFG_VBDEN); // turn off VBUSSENSE
|
|
SET_BIT(USBG->GOTGCTL, USB_OTG_GOTGCTL_BVALOEN | USB_OTG_GOTGCTL_BVALOVAL); // force B-session
|
|
#elif defined(USB_STM32F4)
|
|
SET_BIT(USBG->GCCFG, USB_OTG_GCCFG_NOVBUSSENS); // turn off VBUSSENSE
|
|
CLEAR_BIT(USBG->GCCFG, USB_OTG_GCCFG_VBUSBSEN | USB_OTG_GCCFG_VBUSASEN);
|
|
#endif
|
|
|
|
// HAL_Delay(50); // it takes time to forcing Device mode takes effect
|
|
|
|
#ifdef USB_HIGH_SPEED
|
|
// WRITE_FIELD(USBD->DCFG, USB_OTG_DCFG_DSPD, USB_LINESPEED_FULL_SPEED);
|
|
// WRITE_FIELD(USBD->DCFG, USB_OTG_DCFG_DSPD, USB_LINESPEED_HIGH_SPEED_ULPI);
|
|
WRITE_FIELD(USBD->DCFG, USB_OTG_DCFG_DSPD, USB_LINESPEED_FULL_SPEED_ULPI);
|
|
#else
|
|
WRITE_FIELD(USBD->DCFG, USB_OTG_DCFG_DSPD, USB_LINESPEED_FULL_SPEED); // there's no other possible option
|
|
#endif
|
|
|
|
// allow specific interrupts
|
|
uint32_t intmask = /*USB_OTG_GINTMSK_WUIM | // Wake up */
|
|
USB_OTG_GINTMSK_OEPINT | // OUT EP events
|
|
USB_OTG_GINTMSK_IEPINT | // IN EP events
|
|
USB_OTG_GINTMSK_ENUMDNEM | // (Linespeed) Enumeration (negotiation) done
|
|
USB_OTG_GINTMSK_USBRST | // USB Reset
|
|
USB_OTG_GINTMSK_USBSUSPM | // USB Suspend
|
|
USB_OTG_GINTMSK_RXFLVLM; // RX FIFO level (signal if non-empty)
|
|
USBG->GINTMSK = intmask;
|
|
|
|
// set global NAK on all Endpoints
|
|
// usbdrv_set_global_NAK(USB_IN, true);
|
|
// usbdrv_set_global_NAK(USB_OUT, true);
|
|
|
|
// flush Tx and Rx FIFOs
|
|
usbdrv_flush_rx_fifo();
|
|
usbdrv_flush_tx_fifo(USB_FLUSH_TX_FIFO_ALL);
|
|
|
|
// make Tx FIFO empty interrupt fire when Tx FIFO is emtpy
|
|
// SET_BIT(USBG->GAHBCFG, USB_OTG_GAHBCFG_TXFELVL);
|
|
|
|
// set masks for endpoint interrupts
|
|
SET_BIT(USBD->DIEPMSK, USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_ITTXFEMSK); // transfer complete, timeout and Tx FIFO empty while receiving IN for IN EPs
|
|
SET_BIT(USBD->DOEPMSK, USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_STUPM); // transfer complete and SETUP complete for OUT EPs
|
|
|
|
// mask all endpoint interrupts in both directions and also clear flags
|
|
USBD->DAINTMSK = 0;
|
|
USBD->DAINT = 0;
|
|
|
|
// enbale global interrupts
|
|
SET_BIT(USBG->GAHBCFG, USB_OTG_GAHBCFG_GINT);
|
|
}
|
|
|
|
// initialize USB subsystem
|
|
void usbdrv_init() {
|
|
HAL_NVIC_DisableIRQ(USB_IRQn);
|
|
|
|
//usbdrv_init_global_state();
|
|
usbdrv_gpio_init();
|
|
usbdrv_periph_init();
|
|
usbdrv_initial_ep0_setup();
|
|
usbdrv_power_and_connect(true);
|
|
|
|
HAL_NVIC_SetPriority(USB_IRQn, 8, 0);
|
|
HAL_NVIC_EnableIRQ(USB_IRQn);
|
|
} |