From 66d0f948ba9550ba3b0035ab4736a6d999b2efa4 Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Sun, 2 Oct 2022 16:23:51 +0200 Subject: [PATCH 1/7] cpu/stm32/periph/usbdev_fs: fix register name RCC_APB1SMENR1 is used if RCC_APB1SMENR_USBSMEN is defined. Without this fix, the conditional doesn't have any effect. --- cpu/stm32/periph/usbdev_fs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu/stm32/periph/usbdev_fs.c b/cpu/stm32/periph/usbdev_fs.c index 38477a5fc0..034e58ff8b 100644 --- a/cpu/stm32/periph/usbdev_fs.c +++ b/cpu/stm32/periph/usbdev_fs.c @@ -135,7 +135,7 @@ 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 /* Enable CRS with auto trim enabled */ From 20bdd3452ee331413656f5e8eb7eb7fd9d695910 Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Sun, 2 Oct 2022 16:32:42 +0200 Subject: [PATCH 2/7] cpu/stm32/periph/usbdev_fs: conditional configuration of CRS Conditional configuration of CRS_CR_AUTOTRIMEN allows the compilation of the driver for STM32 MCUs that don't have Clock Recovery System. --- cpu/stm32/periph/usbdev_fs.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cpu/stm32/periph/usbdev_fs.c b/cpu/stm32/periph/usbdev_fs.c index 034e58ff8b..3cd6b630db 100644 --- a/cpu/stm32/periph/usbdev_fs.c +++ b/cpu/stm32/periph/usbdev_fs.c @@ -138,8 +138,11 @@ static void _enable_usb_clk(void) #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) From 3d1a3bf560fb236729077761aa7cdd1d5d0a4986 Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Sun, 2 Oct 2022 19:00:44 +0200 Subject: [PATCH 3/7] cpu/stm32/periph/usbdev_fs: allow USB signals as additional function For a number of STM32 MCUs with the USB-FS device interface the signals USB_DP and USB_DM are not defined as GPIO alternative function but as additional function. Additional functions are directly selected/enabled through peripheral registers hand have not to be configured. In this case, the configuration defines GIO_AF_UNDEF as alternative function. --- cpu/stm32/periph/usbdev_fs.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/cpu/stm32/periph/usbdev_fs.c b/cpu/stm32/periph/usbdev_fs.c index 3cd6b630db..e2fc03a3a0 100644 --- a/cpu/stm32/periph/usbdev_fs.c +++ b/cpu/stm32/periph/usbdev_fs.c @@ -147,12 +147,11 @@ static void _enable_usb_clk(void) 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); + } static void _set_ep_in_status(uint16_t *val, uint16_t mask) { From 1fde5a4401f67e404158cb4d37e73471320caadf Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Mon, 3 Oct 2022 06:45:26 +0200 Subject: [PATCH 4/7] cpu/stm32/periph/usbdev_fs: support GPIO for USB connect/disconnect Since some STM32 MCU don't have internal D+ pullup, there are boards that use a GPIO for USB bus connect/disconnect. --- boards/p-nucleo-wb55/include/periph_conf.h | 1 + cpu/stm32/include/periph/cpu_usbdev.h | 1 + cpu/stm32/periph/usbdev_fs.c | 24 ++++++++++++++++++---- 3 files changed, 22 insertions(+), 4 deletions(-) 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/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/usbdev_fs.c b/cpu/stm32/periph/usbdev_fs.c index e2fc03a3a0..64f8e4ee4d 100644 --- a/cpu/stm32/periph/usbdev_fs.c +++ b/cpu/stm32/periph/usbdev_fs.c @@ -153,6 +153,14 @@ static void _enable_gpio(const stm32_usbdev_fs_config_t *conf) 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) { /* status endpoints bits can only be toggled, writing 0 @@ -181,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)); #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 } From 7f4613da34c3b0d72392bc07e5ee74ee7828481e Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Mon, 3 Oct 2022 07:03:20 +0200 Subject: [PATCH 5/7] cpu/stm32/periph/usbdev_fs: changes to support STM32F3 --- cpu/stm32/Makefile.dep | 2 +- cpu/stm32/periph/Makefile | 2 +- cpu/stm32/periph/usbdev_fs.c | 14 +++++++++++--- 3 files changed, 13 insertions(+), 5 deletions(-) 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/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 64f8e4ee4d..6fca27a128 100644 --- a/cpu/stm32/periph/usbdev_fs.c +++ b/cpu/stm32/periph/usbdev_fs.c @@ -279,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 */ @@ -291,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 */ From bc94881a91772d19a6393b2059ac57fda8dfc59b Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Mon, 3 Oct 2022 07:04:41 +0200 Subject: [PATCH 6/7] boards/nucleo-f303: add periph_usbdev support --- boards/nucleo-f303ze/Kconfig | 1 + boards/nucleo-f303ze/Makefile.features | 1 + boards/nucleo-f303ze/include/periph_conf.h | 26 ++++++++++++++++++++++ 3 files changed, 28 insertions(+) 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 From 08bd418baa6644852f0376940e97fdff11612e20 Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Tue, 4 Oct 2022 08:04:38 +0200 Subject: [PATCH 7/7] cpu/stm32/periph/usbdev_fs: coding style fix --- cpu/stm32/periph/usbdev_fs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu/stm32/periph/usbdev_fs.c b/cpu/stm32/periph/usbdev_fs.c index 6fca27a128..032c6bc78d 100644 --- a/cpu/stm32/periph/usbdev_fs.c +++ b/cpu/stm32/periph/usbdev_fs.c @@ -195,7 +195,7 @@ static inline void _usb_attach(stm32_usbdev_fs_t *usbdev) #ifdef USB_BCDR_DPPU /* 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 /* If configuration uses a GPIO for USB connect/disconnect */ if (conf->disconn != GPIO_UNDEF) {