From 921bfeb05a1729b600403bd4c928afc6eaf7fdac Mon Sep 17 00:00:00 2001 From: Yannis Damigos Date: Fri, 27 Oct 2017 20:21:12 +0300 Subject: [PATCH] drivers: usb_dc_stm32: Add support for all STM32 families Add support for all STM32 families Signed-off-by: Yannis Damigos Signed-off-by: qianfan Zhao --- .../st_stm32/common/Kconfig.defconfig.series | 7 + .../st_stm32/stm32f4/Kconfig.defconfig.series | 3 - drivers/usb/device/Kconfig | 7 +- drivers/usb/device/usb_dc_stm32.c | 125 +++++++++++++++--- 4 files changed, 116 insertions(+), 26 deletions(-) diff --git a/arch/arm/soc/st_stm32/common/Kconfig.defconfig.series b/arch/arm/soc/st_stm32/common/Kconfig.defconfig.series index cee389f9e2f..21e7631d072 100644 --- a/arch/arm/soc/st_stm32/common/Kconfig.defconfig.series +++ b/arch/arm/soc/st_stm32/common/Kconfig.defconfig.series @@ -65,4 +65,11 @@ config I2C_STM32 endif +if USB + +config USB_DC_STM32 + def_bool y + +endif # USB + endif # SOC_FAMILY_STM32 diff --git a/arch/arm/soc/st_stm32/stm32f4/Kconfig.defconfig.series b/arch/arm/soc/st_stm32/stm32f4/Kconfig.defconfig.series index d4d30290c6b..627fd7691de 100644 --- a/arch/arm/soc/st_stm32/stm32f4/Kconfig.defconfig.series +++ b/arch/arm/soc/st_stm32/stm32f4/Kconfig.defconfig.series @@ -27,9 +27,6 @@ endif # GPIO_STM32 if USB -config USB_DC_STM32 - def_bool y - if USB_CDC_ACM config CDC_ACM_INT_EP_ADDR diff --git a/drivers/usb/device/Kconfig b/drivers/usb/device/Kconfig index c9b7721c03b..03c5907295d 100644 --- a/drivers/usb/device/Kconfig +++ b/drivers/usb/device/Kconfig @@ -29,15 +29,16 @@ config USB_DW_IRQ_PRI config USB_DC_STM32 bool prompt "USB device controller driver for STM32 devices" - depends on SOC_SERIES_STM32F4X + depends on SOC_FAMILY_STM32 select USB_DEVICE_DRIVER - select USE_STM32_LL_USB + select USE_STM32_LL_USB if !SOC_SERIES_STM32F0X && !SOC_SERIES_STM32F3X && !SOC_SERIES_STM32L0X select USE_STM32_HAL_PCD select USE_STM32_HAL_PCD_EX select HAS_DTS_USB default n help - STM32 family USB device controller Driver. + Enable USB support on the STM32 F0, F1, F3, F4 and L4 family of + processors. config USB_DC_SAM0 bool diff --git a/drivers/usb/device/usb_dc_stm32.c b/drivers/usb/device/usb_dc_stm32.c index 4345e08ed5b..b8047aa369c 100644 --- a/drivers/usb/device/usb_dc_stm32.c +++ b/drivers/usb/device/usb_dc_stm32.c @@ -2,6 +2,7 @@ /* * Copyright (c) 2017 Christer Weinigel. + * Copyright (c) 2017, I-SENSE group of ICCS * * SPDX-License-Identifier: Apache-2.0 */ @@ -53,6 +54,18 @@ #define SYS_LOG_LEVEL CONFIG_SYS_LOG_USB_DRIVER_LEVEL #include +/* + * USB LL API provides the EP_TYPE_* defines. STM32Cube does + * not provide USB LL API for STM32F0 and STM32F3 families. + * Map EP_TYPE_* defines to PCD_EP_TYPE_* defines + */ +#if defined(CONFIG_SOC_SERIES_STM32F3X) || defined(CONFIG_SOC_SERIES_STM32F0X) +#define EP_TYPE_CTRL PCD_EP_TYPE_CTRL +#define EP_TYPE_ISOC PCD_EP_TYPE_ISOC +#define EP_TYPE_BULK PCD_EP_TYPE_BULK +#define EP_TYPE_INTR PCD_EP_TYPE_INTR +#endif + /* Total in ep number = bidirectional ep number + in ep number */ #define NUM_IN_EP (CONFIG_USB_NUM_BIDIR_ENDPOINTS + \ CONFIG_USB_NUM_IN_ENDPOINTS) @@ -67,6 +80,32 @@ */ #define NUM_BIDIR_EP NUM_OUT_EP +/* + * USB and USB_OTG_FS are defined in STM32Cube HAL and allows to distinguish + * between two kind of USB DC. STM32 F0, F3, and L0 series support USB device + * controller. STM32 F4 and F7 series support USB_OTG_FS device controller. + * STM32 F1 and L4 series support either USB or USB_OTG_FS device controller. + * + * WARNING: Don't mix USB defined in STM32Cube HAL and CONFIG_USB from Zephyr + * Kconfig system. + */ +#ifdef USB + +#define EP0_MPS 64U +#define EP_MPS 64U + +/* + * USB BTABLE is stored in the PMA. The size of BTABLE is 4 bytes + * per endpoint. + * + */ +#define USB_BTABLE_SIZE (8 * NUM_BIDIR_EP) + +#else /* USB_OTG_FS */ + +#define EP0_MPS USB_OTG_MAX_EP0_SIZE +#define EP_MPS USB_OTG_FS_MAX_PACKET_SIZE + /* We need one RX FIFO and n TX-IN FIFOs */ #define FIFO_NUM (1 + NUM_IN_EP) @@ -76,6 +115,8 @@ /* Allocate FIFO memory evenly between the FIFOs */ #define FIFO_EP_WORDS (FIFO_WORDS / FIFO_NUM) +#endif /* USB */ + /* Size of a USB SETUP packet */ #define SETUP_SIZE 8 @@ -105,7 +146,11 @@ struct usb_dc_stm32_state { usb_dc_status_callback status_cb; /* Status callback */ struct usb_dc_stm32_ep_state out_ep_state[NUM_OUT_EP]; struct usb_dc_stm32_ep_state in_ep_state[NUM_IN_EP]; - u8_t ep_buf[NUM_OUT_EP][USB_OTG_FS_MAX_PACKET_SIZE]; + u8_t ep_buf[NUM_OUT_EP][EP_MPS]; + +#ifdef USB + u32_t pma_offset; +#endif /* USB */ }; static struct usb_dc_stm32_state usb_dc_stm32_state; @@ -138,8 +183,21 @@ static int usb_dc_stm32_clock_enable(void) { struct device *clk = device_get_binding(STM32_CLOCK_CONTROL_NAME); struct stm32_pclken pclken = { + +#ifdef USB + .bus = STM32_CLOCK_BUS_APB1, + .enr = LL_APB1_GRP1_PERIPH_USB, +#else /* USB_OTG_FS */ + +#ifdef CONFIG_SOC_SERIES_STM32F1X + .bus = STM32_CLOCK_BUS_AHB1, + .enr = LL_AHB1_GRP1_PERIPH_OTGFS, +#else .bus = STM32_CLOCK_BUS_AHB2, .enr = LL_AHB2_GRP1_PERIPH_OTGFS, +#endif /* CONFIG_SOC_SERIES_STM32F1X */ + +#endif /* USB */ }; clock_control_on(clk, (clock_control_subsys_t *)&pclken); @@ -152,15 +210,27 @@ static int usb_dc_stm32_init(void) HAL_StatusTypeDef status; unsigned int i; - /* We only support OTG FS for now */ +#ifdef USB + usb_dc_stm32_state.pcd.Instance = USB; + usb_dc_stm32_state.pcd.Init.speed = PCD_SPEED_FULL; + usb_dc_stm32_state.pcd.Init.dev_endpoints = NUM_BIDIR_EP; + usb_dc_stm32_state.pcd.Init.phy_itface = PCD_PHY_EMBEDDED; + usb_dc_stm32_state.pcd.Init.ep0_mps = PCD_EP0MPS_64; + usb_dc_stm32_state.pcd.Init.low_power_enable = 0; +#else /* USB_OTG_FS */ usb_dc_stm32_state.pcd.Instance = USB_OTG_FS; usb_dc_stm32_state.pcd.Init.dev_endpoints = NUM_BIDIR_EP; usb_dc_stm32_state.pcd.Init.speed = USB_OTG_SPEED_FULL; usb_dc_stm32_state.pcd.Init.phy_itface = PCD_PHY_EMBEDDED; usb_dc_stm32_state.pcd.Init.ep0_mps = USB_OTG_MAX_EP0_SIZE; - usb_dc_stm32_state.pcd.Init.dma_enable = DISABLE; usb_dc_stm32_state.pcd.Init.vbus_sensing_enable = DISABLE; +#ifndef CONFIG_SOC_SERIES_STM32F1X + usb_dc_stm32_state.pcd.Init.dma_enable = DISABLE; +#endif + +#endif /* USB */ + SYS_LOG_DBG("HAL_PCD_Init"); status = HAL_PCD_Init(&usb_dc_stm32_state.pcd); if (status != HAL_OK) { @@ -175,11 +245,19 @@ static int usb_dc_stm32_init(void) return -EIO; } - usb_dc_stm32_state.out_ep_state[EP0_IDX].ep_mps = USB_OTG_MAX_EP0_SIZE; + usb_dc_stm32_state.out_ep_state[EP0_IDX].ep_mps = EP0_MPS; usb_dc_stm32_state.out_ep_state[EP0_IDX].ep_type = EP_TYPE_CTRL; - usb_dc_stm32_state.in_ep_state[EP0_IDX].ep_mps = USB_OTG_MAX_EP0_SIZE; + usb_dc_stm32_state.in_ep_state[EP0_IDX].ep_mps = EP0_MPS; usb_dc_stm32_state.in_ep_state[EP0_IDX].ep_type = EP_TYPE_CTRL; +#ifdef USB + /* Start PMA configuration for the endpoints after the BTABLE. */ + usb_dc_stm32_state.pma_offset = USB_BTABLE_SIZE; + + for (i = 0; i < NUM_IN_EP; i++) { + k_sem_init(&usb_dc_stm32_state.in_ep_state[i].write_sem, 1, 1); + } +#else /* USB_OTG_FS */ /* TODO: make this dynamic (depending usage) */ HAL_PCDEx_SetRxFiFo(&usb_dc_stm32_state.pcd, FIFO_EP_WORDS); for (i = 0; i < NUM_IN_EP; i++) { @@ -187,11 +265,11 @@ static int usb_dc_stm32_init(void) FIFO_EP_WORDS); k_sem_init(&usb_dc_stm32_state.in_ep_state[i].write_sem, 1, 1); } +#endif /* USB */ IRQ_CONNECT(CONFIG_USB_IRQ, CONFIG_USB_IRQ_PRI, usb_dc_stm32_isr, 0, 0); irq_enable(CONFIG_USB_IRQ); - return 0; } @@ -268,8 +346,8 @@ int usb_dc_ep_start_read(u8_t ep, u8_t *data, u32_t max_data_len) return -EINVAL; } - if (max_data_len > USB_OTG_FS_MAX_PACKET_SIZE) { - max_data_len = USB_OTG_FS_MAX_PACKET_SIZE; + if (max_data_len > EP_MPS) { + max_data_len = EP_MPS; } status = HAL_PCD_EP_Receive(&usb_dc_stm32_state.pcd, ep, @@ -308,6 +386,15 @@ int usb_dc_ep_configure(const struct usb_dc_ep_cfg_data * const ep_cfg) return -EINVAL; } +#ifdef USB + if (CONFIG_USB_RAM_SIZE <= + (usb_dc_stm32_state.pma_offset + ep_cfg->ep_mps)) { + return -EINVAL; + } + HAL_PCDEx_PMAConfig(&usb_dc_stm32_state.pcd, ep, PCD_SNG_BUF, + usb_dc_stm32_state.pma_offset); + usb_dc_stm32_state.pma_offset += ep_cfg->ep_mps; +#endif ep_state->ep_mps = ep_cfg->ep_mps; switch (ep_cfg->ep_type) { @@ -396,7 +483,6 @@ int usb_dc_ep_enable(const u8_t ep) { struct usb_dc_stm32_ep_state *ep_state = usb_dc_stm32_get_ep_state(ep); HAL_StatusTypeDef status; - int ret; SYS_LOG_DBG("ep 0x%02x", ep); @@ -415,15 +501,10 @@ int usb_dc_ep_enable(const u8_t ep) return -EIO; } - ret = usb_dc_ep_clear_stall(ep); - if (ret) { - return ret; - } - if (EP_IS_OUT(ep) && ep != EP0_OUT) { return usb_dc_ep_start_read(ep, - usb_dc_stm32_state.ep_buf[EP_IDX(ep)], - USB_OTG_FS_MAX_PACKET_SIZE); + usb_dc_stm32_state.ep_buf[EP_IDX(ep)], + EP_MPS); } return 0; @@ -471,7 +552,7 @@ int usb_dc_ep_write(const u8_t ep, const u8_t *const data, } if (!k_is_in_isr()) { - irq_disable(STM32F4_IRQ_OTG_FS); + irq_disable(CONFIG_USB_IRQ); } status = HAL_PCD_EP_Transmit(&usb_dc_stm32_state.pcd, ep, @@ -483,7 +564,7 @@ int usb_dc_ep_write(const u8_t ep, const u8_t *const data, ret = -EIO; } - if (!ret && ep == EP0_IN) { + if (!ret && ep == EP0_IN && data_len > 0) { /* Wait for an empty package as from the host. * This also flushes the TX FIFO to the host. */ @@ -491,7 +572,7 @@ int usb_dc_ep_write(const u8_t ep, const u8_t *const data, } if (!k_is_in_isr()) { - irq_enable(STM32F4_IRQ_OTG_FS); + irq_enable(CONFIG_USB_IRQ); } if (ret_bytes) { @@ -550,7 +631,7 @@ int usb_dc_ep_read_continue(u8_t ep) */ if (ep != EP0_OUT && !ep_state->read_count) { usb_dc_ep_start_read(ep, usb_dc_stm32_state.ep_buf[EP_IDX(ep)], - USB_OTG_FS_MAX_PACKET_SIZE); + EP_MPS); } return 0; @@ -584,6 +665,10 @@ void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd) { SYS_LOG_DBG(""); + HAL_PCD_EP_Open(&usb_dc_stm32_state.pcd, EP0_IN, EP0_MPS, EP_TYPE_CTRL); + HAL_PCD_EP_Open(&usb_dc_stm32_state.pcd, EP0_OUT, EP0_MPS, + EP_TYPE_CTRL); + if (usb_dc_stm32_state.status_cb) { usb_dc_stm32_state.status_cb(USB_DC_RESET, NULL); }