drivers: usb_dc_stm32: Add support for all STM32 families
Add support for all STM32 families Signed-off-by: Yannis Damigos <giannis.damigos@gmail.com> Signed-off-by: qianfan Zhao <qianfanguijin@163.com>
This commit is contained in:
parent
79a0fa68e3
commit
921bfeb05a
4 changed files with 116 additions and 26 deletions
|
@ -65,4 +65,11 @@ config I2C_STM32
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if USB
|
||||||
|
|
||||||
|
config USB_DC_STM32
|
||||||
|
def_bool y
|
||||||
|
|
||||||
|
endif # USB
|
||||||
|
|
||||||
endif # SOC_FAMILY_STM32
|
endif # SOC_FAMILY_STM32
|
||||||
|
|
|
@ -27,9 +27,6 @@ endif # GPIO_STM32
|
||||||
|
|
||||||
if USB
|
if USB
|
||||||
|
|
||||||
config USB_DC_STM32
|
|
||||||
def_bool y
|
|
||||||
|
|
||||||
if USB_CDC_ACM
|
if USB_CDC_ACM
|
||||||
|
|
||||||
config CDC_ACM_INT_EP_ADDR
|
config CDC_ACM_INT_EP_ADDR
|
||||||
|
|
|
@ -29,15 +29,16 @@ config USB_DW_IRQ_PRI
|
||||||
config USB_DC_STM32
|
config USB_DC_STM32
|
||||||
bool
|
bool
|
||||||
prompt "USB device controller driver for STM32 devices"
|
prompt "USB device controller driver for STM32 devices"
|
||||||
depends on SOC_SERIES_STM32F4X
|
depends on SOC_FAMILY_STM32
|
||||||
select USB_DEVICE_DRIVER
|
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
|
||||||
select USE_STM32_HAL_PCD_EX
|
select USE_STM32_HAL_PCD_EX
|
||||||
select HAS_DTS_USB
|
select HAS_DTS_USB
|
||||||
default n
|
default n
|
||||||
help
|
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
|
config USB_DC_SAM0
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2017 Christer Weinigel.
|
* Copyright (c) 2017 Christer Weinigel.
|
||||||
|
* Copyright (c) 2017, I-SENSE group of ICCS
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
@ -53,6 +54,18 @@
|
||||||
#define SYS_LOG_LEVEL CONFIG_SYS_LOG_USB_DRIVER_LEVEL
|
#define SYS_LOG_LEVEL CONFIG_SYS_LOG_USB_DRIVER_LEVEL
|
||||||
#include <logging/sys_log.h>
|
#include <logging/sys_log.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 */
|
/* Total in ep number = bidirectional ep number + in ep number */
|
||||||
#define NUM_IN_EP (CONFIG_USB_NUM_BIDIR_ENDPOINTS + \
|
#define NUM_IN_EP (CONFIG_USB_NUM_BIDIR_ENDPOINTS + \
|
||||||
CONFIG_USB_NUM_IN_ENDPOINTS)
|
CONFIG_USB_NUM_IN_ENDPOINTS)
|
||||||
|
@ -67,6 +80,32 @@
|
||||||
*/
|
*/
|
||||||
#define NUM_BIDIR_EP NUM_OUT_EP
|
#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 */
|
/* We need one RX FIFO and n TX-IN FIFOs */
|
||||||
#define FIFO_NUM (1 + NUM_IN_EP)
|
#define FIFO_NUM (1 + NUM_IN_EP)
|
||||||
|
|
||||||
|
@ -76,6 +115,8 @@
|
||||||
/* Allocate FIFO memory evenly between the FIFOs */
|
/* Allocate FIFO memory evenly between the FIFOs */
|
||||||
#define FIFO_EP_WORDS (FIFO_WORDS / FIFO_NUM)
|
#define FIFO_EP_WORDS (FIFO_WORDS / FIFO_NUM)
|
||||||
|
|
||||||
|
#endif /* USB */
|
||||||
|
|
||||||
/* Size of a USB SETUP packet */
|
/* Size of a USB SETUP packet */
|
||||||
#define SETUP_SIZE 8
|
#define SETUP_SIZE 8
|
||||||
|
|
||||||
|
@ -105,7 +146,11 @@ struct usb_dc_stm32_state {
|
||||||
usb_dc_status_callback status_cb; /* Status callback */
|
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 out_ep_state[NUM_OUT_EP];
|
||||||
struct usb_dc_stm32_ep_state in_ep_state[NUM_IN_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;
|
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 device *clk = device_get_binding(STM32_CLOCK_CONTROL_NAME);
|
||||||
struct stm32_pclken pclken = {
|
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,
|
.bus = STM32_CLOCK_BUS_AHB2,
|
||||||
.enr = LL_AHB2_GRP1_PERIPH_OTGFS,
|
.enr = LL_AHB2_GRP1_PERIPH_OTGFS,
|
||||||
|
#endif /* CONFIG_SOC_SERIES_STM32F1X */
|
||||||
|
|
||||||
|
#endif /* USB */
|
||||||
};
|
};
|
||||||
|
|
||||||
clock_control_on(clk, (clock_control_subsys_t *)&pclken);
|
clock_control_on(clk, (clock_control_subsys_t *)&pclken);
|
||||||
|
@ -152,15 +210,27 @@ static int usb_dc_stm32_init(void)
|
||||||
HAL_StatusTypeDef status;
|
HAL_StatusTypeDef status;
|
||||||
unsigned int i;
|
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.Instance = USB_OTG_FS;
|
||||||
usb_dc_stm32_state.pcd.Init.dev_endpoints = NUM_BIDIR_EP;
|
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.speed = USB_OTG_SPEED_FULL;
|
||||||
usb_dc_stm32_state.pcd.Init.phy_itface = PCD_PHY_EMBEDDED;
|
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.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;
|
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");
|
SYS_LOG_DBG("HAL_PCD_Init");
|
||||||
status = HAL_PCD_Init(&usb_dc_stm32_state.pcd);
|
status = HAL_PCD_Init(&usb_dc_stm32_state.pcd);
|
||||||
if (status != HAL_OK) {
|
if (status != HAL_OK) {
|
||||||
|
@ -175,11 +245,19 @@ static int usb_dc_stm32_init(void)
|
||||||
return -EIO;
|
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.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;
|
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) */
|
/* TODO: make this dynamic (depending usage) */
|
||||||
HAL_PCDEx_SetRxFiFo(&usb_dc_stm32_state.pcd, FIFO_EP_WORDS);
|
HAL_PCDEx_SetRxFiFo(&usb_dc_stm32_state.pcd, FIFO_EP_WORDS);
|
||||||
for (i = 0; i < NUM_IN_EP; i++) {
|
for (i = 0; i < NUM_IN_EP; i++) {
|
||||||
|
@ -187,11 +265,11 @@ static int usb_dc_stm32_init(void)
|
||||||
FIFO_EP_WORDS);
|
FIFO_EP_WORDS);
|
||||||
k_sem_init(&usb_dc_stm32_state.in_ep_state[i].write_sem, 1, 1);
|
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,
|
IRQ_CONNECT(CONFIG_USB_IRQ, CONFIG_USB_IRQ_PRI,
|
||||||
usb_dc_stm32_isr, 0, 0);
|
usb_dc_stm32_isr, 0, 0);
|
||||||
irq_enable(CONFIG_USB_IRQ);
|
irq_enable(CONFIG_USB_IRQ);
|
||||||
|
|
||||||
return 0;
|
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;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (max_data_len > USB_OTG_FS_MAX_PACKET_SIZE) {
|
if (max_data_len > EP_MPS) {
|
||||||
max_data_len = USB_OTG_FS_MAX_PACKET_SIZE;
|
max_data_len = EP_MPS;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = HAL_PCD_EP_Receive(&usb_dc_stm32_state.pcd, ep,
|
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;
|
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;
|
ep_state->ep_mps = ep_cfg->ep_mps;
|
||||||
|
|
||||||
switch (ep_cfg->ep_type) {
|
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);
|
struct usb_dc_stm32_ep_state *ep_state = usb_dc_stm32_get_ep_state(ep);
|
||||||
HAL_StatusTypeDef status;
|
HAL_StatusTypeDef status;
|
||||||
int ret;
|
|
||||||
|
|
||||||
SYS_LOG_DBG("ep 0x%02x", ep);
|
SYS_LOG_DBG("ep 0x%02x", ep);
|
||||||
|
|
||||||
|
@ -415,15 +501,10 @@ int usb_dc_ep_enable(const u8_t ep)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = usb_dc_ep_clear_stall(ep);
|
|
||||||
if (ret) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (EP_IS_OUT(ep) && ep != EP0_OUT) {
|
if (EP_IS_OUT(ep) && ep != EP0_OUT) {
|
||||||
return usb_dc_ep_start_read(ep,
|
return usb_dc_ep_start_read(ep,
|
||||||
usb_dc_stm32_state.ep_buf[EP_IDX(ep)],
|
usb_dc_stm32_state.ep_buf[EP_IDX(ep)],
|
||||||
USB_OTG_FS_MAX_PACKET_SIZE);
|
EP_MPS);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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()) {
|
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,
|
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;
|
ret = -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ret && ep == EP0_IN) {
|
if (!ret && ep == EP0_IN && data_len > 0) {
|
||||||
/* Wait for an empty package as from the host.
|
/* Wait for an empty package as from the host.
|
||||||
* This also flushes the TX FIFO to 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()) {
|
if (!k_is_in_isr()) {
|
||||||
irq_enable(STM32F4_IRQ_OTG_FS);
|
irq_enable(CONFIG_USB_IRQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret_bytes) {
|
if (ret_bytes) {
|
||||||
|
@ -550,7 +631,7 @@ int usb_dc_ep_read_continue(u8_t ep)
|
||||||
*/
|
*/
|
||||||
if (ep != EP0_OUT && !ep_state->read_count) {
|
if (ep != EP0_OUT && !ep_state->read_count) {
|
||||||
usb_dc_ep_start_read(ep, usb_dc_stm32_state.ep_buf[EP_IDX(ep)],
|
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;
|
return 0;
|
||||||
|
@ -584,6 +665,10 @@ void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
|
||||||
{
|
{
|
||||||
SYS_LOG_DBG("");
|
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) {
|
if (usb_dc_stm32_state.status_cb) {
|
||||||
usb_dc_stm32_state.status_cb(USB_DC_RESET, NULL);
|
usb_dc_stm32_state.status_cb(USB_DC_RESET, NULL);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue