diff --git a/boards/nucleo-f303ze/Kconfig b/boards/nucleo-f303ze/Kconfig index b5eb702e31..125a955e13 100644 --- a/boards/nucleo-f303ze/Kconfig +++ b/boards/nucleo-f303ze/Kconfig @@ -21,6 +21,7 @@ config BOARD_NUCLEO_F303ZE select HAS_PERIPH_SPI select HAS_PERIPH_TIMER select HAS_PERIPH_UART + select HAS_PERIPH_USBDEV # Put other features for this board (in alphabetical order) select HAS_RIOTBOOT diff --git a/boards/nucleo-f303ze/Makefile.features b/boards/nucleo-f303ze/Makefile.features index 87a9ea6c2b..44999e4d3b 100644 --- a/boards/nucleo-f303ze/Makefile.features +++ b/boards/nucleo-f303ze/Makefile.features @@ -8,6 +8,7 @@ FEATURES_PROVIDED += periph_rtc FEATURES_PROVIDED += periph_spi FEATURES_PROVIDED += periph_timer FEATURES_PROVIDED += periph_uart +FEATURES_PROVIDED += periph_usbdev # Put other features for this board (in alphabetical order) FEATURES_PROVIDED += riotboot diff --git a/boards/nucleo-f303ze/include/periph_conf.h b/boards/nucleo-f303ze/include/periph_conf.h index fd5e0fc7aa..0ed481ba99 100644 --- a/boards/nucleo-f303ze/include/periph_conf.h +++ b/boards/nucleo-f303ze/include/periph_conf.h @@ -173,6 +173,32 @@ static const spi_conf_t spi_config[] = { #define SPI_NUMOF ARRAY_SIZE(spi_config) /** @} */ +/** + * @brief USB device FS configuration + */ +static const stm32_usbdev_fs_config_t stm32_usbdev_fs_config[] = { + { + .base_addr = (uintptr_t)USB, + .rcc_mask = RCC_APB1ENR_USBEN, + .irqn = USB_LP_CAN_RX0_IRQn, + .apb = APB1, + .dm = GPIO_PIN(PORT_A, 11), + .dp = GPIO_PIN(PORT_A, 12), + .af = GPIO_AF14, + .disconn = GPIO_PIN(PORT_G, 6), + }, +}; + +/** + * @brief Interrupt function name mapping + */ +#define USBDEV_ISR isr_usb_lp_can_rx0 + +/** + * @brief Number of available USB device FS peripherals + */ +#define USBDEV_NUMOF ARRAY_SIZE(stm32_usbdev_fs_config) + #ifdef __cplusplus } #endif diff --git a/boards/p-nucleo-wb55/include/periph_conf.h b/boards/p-nucleo-wb55/include/periph_conf.h index aa71095987..f181852795 100644 --- a/boards/p-nucleo-wb55/include/periph_conf.h +++ b/boards/p-nucleo-wb55/include/periph_conf.h @@ -116,6 +116,7 @@ static const stm32_usbdev_fs_config_t stm32_usbdev_fs_config[] = { .dm = GPIO_PIN(PORT_A, 11), .dp = GPIO_PIN(PORT_A, 12), .af = GPIO_AF10, + .disconn = GPIO_UNDEF, }, }; diff --git a/cpu/stm32/Makefile.dep b/cpu/stm32/Makefile.dep index 614af2857f..23493f47ab 100644 --- a/cpu/stm32/Makefile.dep +++ b/cpu/stm32/Makefile.dep @@ -4,7 +4,7 @@ USEMODULE += periph stm32_clk stm32_vectors ifneq (,$(filter periph_usbdev,$(FEATURES_USED))) - ifneq (wb,$(CPU_FAM)) + ifeq (,$(filter f3 wb,$(CPU_FAM))) USEMODULE += usbdev_synopsys_dwc2 endif USEMODULE += ztimer diff --git a/cpu/stm32/include/periph/cpu_usbdev.h b/cpu/stm32/include/periph/cpu_usbdev.h index 92d859f802..bd978c9422 100644 --- a/cpu/stm32/include/periph/cpu_usbdev.h +++ b/cpu/stm32/include/periph/cpu_usbdev.h @@ -50,6 +50,7 @@ typedef struct { gpio_t dm; /**< Data- gpio */ gpio_t dp; /**< Data+ gpio */ gpio_af_t af; /**< Alternative function */ + gpio_t disconn; /**< GPIO if used for USB disconnect */ } stm32_usbdev_fs_config_t; #ifdef __cplusplus diff --git a/cpu/stm32/periph/Makefile b/cpu/stm32/periph/Makefile index 3d1366b153..23fa83b26d 100644 --- a/cpu/stm32/periph/Makefile +++ b/cpu/stm32/periph/Makefile @@ -51,7 +51,7 @@ endif # Select the correct implementation for `periph_usbdev` ifneq (,$(filter periph_usbdev,$(USEMODULE))) - ifeq (wb,$(CPU_FAM)) + ifneq (,$(filter f3 wb,$(CPU_FAM))) SRC += usbdev_fs.c endif endif diff --git a/cpu/stm32/periph/usbdev_fs.c b/cpu/stm32/periph/usbdev_fs.c index 38477a5fc0..032c6bc78d 100644 --- a/cpu/stm32/periph/usbdev_fs.c +++ b/cpu/stm32/periph/usbdev_fs.c @@ -135,20 +135,30 @@ static void _enable_usb_clk(void) #if defined(RCC_APB1SMENR_USBSMEN) RCC->APB1SMENR |= RCC_APB1SMENR_USBSMEN; -#elif defined(RCC_APB1SMENR_USBSMEN) +#elif defined(RCC_APB1SMENR1_USBSMEN) RCC->APB1SMENR1 |= RCC_APB1SMENR1_USBSMEN; #endif + +#if defined(CRS_CR_AUTOTRIMEN) && defined(CRS_CR_CEN) /* Enable CRS with auto trim enabled */ CRS->CR |= (CRS_CR_AUTOTRIMEN | CRS_CR_CEN); +#endif } static void _enable_gpio(const stm32_usbdev_fs_config_t *conf) { - gpio_init(conf->dp, GPIO_IN); - gpio_init(conf->dm, GPIO_IN); - /* Configure AF for the pins */ - gpio_init_af(conf->dp, conf->af); - gpio_init_af(conf->dm, conf->af); + if (conf->af != GPIO_AF_UNDEF) { + /* Configure AF for the pins */ + gpio_init_af(conf->dp, conf->af); + gpio_init_af(conf->dm, conf->af); + } + + if (conf->disconn != GPIO_UNDEF) { + /* In case the MCU has no internal D+ pullup, a GPIO is used to + * connect/disconnect from USB bus */ + gpio_init(conf->disconn, GPIO_OUT); + gpio_clear(conf->disconn); + } } static void _set_ep_in_status(uint16_t *val, uint16_t mask) @@ -179,28 +189,36 @@ static void _set_ep_out_status(uint16_t *val, uint16_t mask) static inline void _usb_attach(stm32_usbdev_fs_t *usbdev) { + const stm32_usbdev_fs_config_t *conf = usbdev->config; + /* Some ST USB IP doesn't have this feature */ #ifdef USB_BCDR_DPPU - const stm32_usbdev_fs_config_t *conf = usbdev->config; /* Enable DP pullup to signal connection */ _global_regs(conf)->BCDR |= USB_BCDR_DPPU; - while (!(CRS->ISR & CRS_ISR_ESYNCF)); + while (!(CRS->ISR & CRS_ISR_ESYNCF)) {} #else - (void)usbdev; + /* If configuration uses a GPIO for USB connect/disconnect */ + if (conf->disconn != GPIO_UNDEF) { + gpio_set(conf->disconn); + } #endif /* USB_BCDR_DPPU */ } static inline void _usb_detach(stm32_usbdev_fs_t *usbdev) { + const stm32_usbdev_fs_config_t *conf = usbdev->config; + /* Some ST USB IP doesn't have this feature */ #ifdef USB_BCDR_DPPU - const stm32_usbdev_fs_config_t *conf = usbdev->config; DEBUG_PUTS("usbdev_fs: Detaching from host"); /* Disable DP pullup to signal disconnection */ CLRBIT(_global_regs(conf)->BCDR, USB_BCDR_DPPU); #else - (void)usbdev; + /* If configuration uses a GPIO for USB connect/disconnect */ + if (conf->disconn != GPIO_UNDEF) { + gpio_clear(conf->disconn); + } #endif } @@ -261,10 +279,12 @@ static void _usbdev_init(usbdev_t *dev) /* Configure GPIOs */ _enable_gpio(conf); - /* Reset USB IP */ - _global_regs(conf)->CNTR = USB_CNTR_FRES; + /* Reset and power down USB IP */ + _global_regs(conf)->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN; + /* Clear power down */ + _global_regs(conf)->CNTR &= ~USB_CNTR_PDWN; /* Clear reset */ - _global_regs(conf)->CNTR = 0; + _global_regs(conf)->CNTR &= ~USB_CNTR_FRES; /* Clear interrupt register */ _global_regs(conf)->ISTR = 0x0000; /* Set BTABLE at start of USB SRAM */ @@ -273,6 +293,12 @@ static void _usbdev_init(usbdev_t *dev) _global_regs(conf)->DADDR = USB_DADDR_EF; /* Unmask the interrupt in the NVIC */ _enable_irq(); + + /* Disable remapping of USB IRQs if remapping defined */ +#ifdef SYSCFG_CFGR1_USB_IT_RMP + SYSCFG->CFGR1 &= ~SYSCFG_CFGR1_USB_IT_RMP; +#endif + /* Enable USB IRQ */ NVIC_EnableIRQ(conf->irqn); /* fill USB SRAM with zeroes */