first commit for chrg

This commit is contained in:
wmano
2025-08-16 22:58:22 +08:00
commit 52a3ed5862
2306 changed files with 1021208 additions and 0 deletions
@@ -0,0 +1,51 @@
# Note
Please note that host must support dma mode.
## Support Chip List
### STM32
**有且仅有 PB14/PB15 引脚支持 host 模式, 部分 F7/H7 可能 PA11/PA12 也支持**
- STM32F105xc、STM32F107xc
- STM32F205xx、STM32F207xx、STM32F215xx、STM32F217xx
- STM32F401xc、STM32F401xe、STM32F405xx、STM32F407xx、STM32F411xe、STM32F412cx、STM32F412rx、STM32F412vx、STM32F412zx、STM32F413xx、STM32F415xx、STM32F417xx、STM32F423xx、STM32F423xx、STM32F429xx、STM32F437xx、STM32F439xx、STM32F446xx、STM32F469xx、STM32F479xx
- STM32F7xx
- STM32H7xx
- STM32L4xx
- STM32U5xx
### AT32
**有且仅有 AT32F405xx PB14/PB15引脚支持 host 模式**
- AT32F402xx、AT32F405xx、AT32F415xx、AT32F423xx、AT32F425xx、AT32F435xx、AT32F437xx
### GD32
**由于无法读取 DWC2 配置信息,并且有部分寄存器是非标准的,因此暂时无法支持 GD 系列**
- GD32F30X_CL
- GD32F405、GD32F407
- GD32F350、GD32F450
### HC32
- HC32F4A0
### Espressif
- ESP32S2、ESP32S3、ESP32P4
### Sophgo
- CV18xx
### Kendryte
- K230
### Nationstech
- N32H4X
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,367 @@
/*
* Copyright (c) 2025, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __USB_DWC2_PARAM_H__
#define __USB_DWC2_PARAM_H__
/* Maximum number of Endpoints/HostChannels */
#define MAX_EPS_CHANNELS 16
#define HSOTG_REG(x) (x)
#define dwc2_readl(addr) \
(*(volatile uint32_t *)(addr))
#define GUID_OFFSET HSOTG_REG(0x003C)
#define GSNPSID_OFFSET HSOTG_REG(0x0040)
#define GSNPSID_ID_MASK (0xFFFF0000UL)
#define GHWCFG1_OFFSET HSOTG_REG(0x0044)
#define GHWCFG2_OFFSET HSOTG_REG(0x0048)
#define GHWCFG2_OTG_ENABLE_IC_USB (0x01UL << 31U)
#define GHWCFG2_DEV_TOKEN_Q_DEPTH_MASK (0x1FUL << 26U)
#define GHWCFG2_DEV_TOKEN_Q_DEPTH_SHIFT (26U)
#define GHWCFG2_HOST_PERIO_TX_Q_DEPTH_MASK (0x03UL << 24U)
#define GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT (24U)
#define GHWCFG2_NONPERIO_TX_Q_DEPTH_MASK (0x03UL << 22U)
#define GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT (22U)
#define GHWCFG2_MULTI_PROC_INT (0x01UL << 20U)
#define GHWCFG2_DYNAMIC_FIFO (0x01UL << 19U)
#define GHWCFG2_PERIO_EP_SUPPORTED (0x01UL << 18U)
#define GHWCFG2_NUM_HOST_CHAN_MASK (0x0FUL << 14U)
#define GHWCFG2_NUM_HOST_CHAN_SHIFT (14U)
#define GHWCFG2_NUM_DEV_EP_MASK (0x0FUL << 10U)
#define GHWCFG2_NUM_DEV_EP_SHIFT (10U)
#define GHWCFG2_FS_PHY_TYPE_MASK (0x03UL << 8U)
#define GHWCFG2_FS_PHY_TYPE_SHIFT (8U)
#define GHWCFG2_FS_PHY_TYPE_NOT_SUPPORTED (0x00UL)
#define GHWCFG2_FS_PHY_TYPE_DEDICATED (0x01UL)
#define GHWCFG2_FS_PHY_TYPE_SHARED_UTMI (0x02UL)
#define GHWCFG2_FS_PHY_TYPE_SHARED_ULPI (0x03UL)
#define GHWCFG2_HS_PHY_TYPE_MASK (0x03UL << 6U)
#define GHWCFG2_HS_PHY_TYPE_SHIFT (6U)
#define GHWCFG2_HS_PHY_TYPE_NOT_SUPPORTED (0x00UL)
#define GHWCFG2_HS_PHY_TYPE_UTMI (0x01UL)
#define GHWCFG2_HS_PHY_TYPE_ULPI (0x02UL)
#define GHWCFG2_HS_PHY_TYPE_UTMI_ULPI (0x03UL)
#define GHWCFG2_POINT2POINT (0x01UL << 5U)
#define GHWCFG2_ARCHITECTURE_MASK (0x03UL << 3U)
#define GHWCFG2_ARCHITECTURE_SHIFT (3U)
#define GHWCFG2_SLAVE_ONLY_ARCH (0x00UL)
#define GHWCFG2_EXT_DMA_ARCH (0x01UL)
#define GHWCFG2_INT_DMA_ARCH (0x02UL)
#define GHWCFG2_OP_MODE_MASK (0x07UL << 0U)
#define GHWCFG2_OP_MODE_SHIFT (0U)
#define GHWCFG2_OP_MODE_HNP_SRP_CAPABLE (0x00UL)
#define GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE (0x01UL)
#define GHWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE (0x02UL)
#define GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE (0x03UL)
#define GHWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE (0x04UL)
#define GHWCFG2_OP_MODE_SRP_CAPABLE_HOST (0x05UL)
#define GHWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST (0x06UL)
#define GHWCFG2_OP_MODE_UNDEFINED (0x07UL)
#define GHWCFG3_OFFSET HSOTG_REG(0x004C)
#define GHWCFG3_DFIFO_DEPTH_MASK (0xFFFFUL << 16U)
#define GHWCFG3_DFIFO_DEPTH_SHIFT (16U)
#define GHWCFG3_OTG_LPM_EN (0x0001UL << 15U)
#define GHWCFG3_BC_SUPPORT (0x0001UL << 14U)
#define GHWCFG3_OTG_ENABLE_HSIC (0x0001UL << 13U)
#define GHWCFG3_ADP_SUPP (0x0001UL << 12U)
#define GHWCFG3_SYNCH_RESET_TYPE (0x0001UL << 11U)
#define GHWCFG3_OPTIONAL_FEATURES (0x0001UL << 10U)
#define GHWCFG3_VENDOR_CTRL_IF (0x0001UL << 9U)
#define GHWCFG3_I2C (0x0001UL << 8U)
#define GHWCFG3_OTG_FUNC (0x0001UL << 7U)
#define GHWCFG3_PACKET_SIZE_CNTR_WIDTH_MASK (0x0007UL << 4U)
#define GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT (4U)
#define GHWCFG3_XFER_SIZE_CNTR_WIDTH_MASK (0x000FUL << 0U)
#define GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT (0U)
#define GHWCFG4_OFFSET HSOTG_REG(0x0050)
#define GHWCFG4_DESC_DMA_DYN (0x1UL << 31U)
#define GHWCFG4_DESC_DMA (0x1UL << 30U)
#define GHWCFG4_NUM_IN_EPS_MASK (0xFUL << 26U)
#define GHWCFG4_NUM_IN_EPS_SHIFT (26U)
#define GHWCFG4_DED_FIFO_EN (0x1UL << 25U)
#define GHWCFG4_DED_FIFO_SHIFT (25U)
#define GHWCFG4_SESSION_END_FILT_EN (0x1UL << 24U)
#define GHWCFG4_B_VALID_FILT_EN (0x1UL << 23U)
#define GHWCFG4_A_VALID_FILT_EN (0x1UL << 22U)
#define GHWCFG4_VBUS_VALID_FILT_EN (0x1UL << 21U)
#define GHWCFG4_IDDIG_FILT_EN (0x1UL << 20U)
#define GHWCFG4_NUM_DEV_MODE_CTRL_EP_MASK (0xFUL << 16U)
#define GHWCFG4_NUM_DEV_MODE_CTRL_EP_SHIFT (16U)
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK (0x3UL << 14U)
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT (14U)
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8 (0x0UL)
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_16 (0x1UL)
#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8_OR_16 (0x2UL)
#define GHWCFG4_ACG_SUPPORTED (0x1UL << 12U)
#define GHWCFG4_IPG_ISOC_SUPPORTED (0x1UL << 11U)
#define GHWCFG4_SERVICE_INTERVAL_SUPPORTED (0x1UL << 10U)
#define GHWCFG4_XHIBER (0x1UL << 7U)
#define GHWCFG4_HIBER (0x1UL << 6U)
#define GHWCFG4_MIN_AHB_FREQ (0x1UL << 5U)
#define GHWCFG4_POWER_OPTIMIZ (0x1UL << 4U)
#define GHWCFG4_NUM_DEV_PERIO_IN_EP_MASK (0xFUL << 0U)
#define GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT (0U)
/**
* struct dwc2_hw_params - Autodetected parameters.
*
* These parameters are the various parameters read from hardware
* registers during initialization. They typically contain the best
* supported or maximum value that can be configured in the
* corresponding dwc2_core_params value.
*
* The values that are not in dwc2_core_params are documented below.
*
* @snpsid: Value from SNPSID register
* @dev_ep_dirs: Direction of device endpoints (GHWCFG1)
*
* @op_mode: Mode of Operation
* 0 - HNP- and SRP-Capable OTG (Host & Device)
* 1 - SRP-Capable OTG (Host & Device)
* 2 - Non-HNP and Non-SRP Capable OTG (Host & Device)
* 3 - SRP-Capable Device
* 4 - Non-OTG Device
* 5 - SRP-Capable Host
* 6 - Non-OTG Host
* @arch: Architecture
* 0 - Slave only
* 1 - External DMA
* 2 - Internal DMA
* @enable_dynamic_fifo: 0 - Use coreConsultant-specified FIFO size parameters
* 1 - Allow dynamic FIFO sizing (default, if available)
* @host_channels: The number of host channel registers to use
* 1 to 16
* @hs_phy_type: High-speed PHY interface type
* 0 - High-speed interface not supported
* 1 - UTMI+
* 2 - ULPI
* 3 - UTMI+ and ULPI
* @fs_phy_type: Full-speed PHY interface type
* 0 - Full speed interface not supported
* 1 - Dedicated full speed interface
* 2 - FS pins shared with UTMI+ pins
* 3 - FS pins shared with ULPI pins
* @num_dev_ep: Number of device endpoints available
* @nperio_tx_q_depth:
* Non-Periodic Request Queue Depth
* 2, 4 or 8
* @dev_token_q_depth: Device Mode IN Token Sequence Learning Queue
* Depth
* 0 to 30
* @host_perio_tx_q_depth:
* Host Mode Periodic Request Queue Depth
* 2, 4 or 8
*
* @max_transfer_size: The maximum transfer size supported, in bytes
* 2047 to 65,535
* Actual maximum value is autodetected and also
* the default.
* @max_packet_count: The maximum number of packets in a transfer
* 15 to 511
* Actual maximum value is autodetected and also
* the default.
* @i2c_enable: Specifies whether to use the I2Cinterface for a full
* speed PHY. This parameter is only applicable if phy_type
* is FS.
* 0 - No (default)
* 1 - Yes
* @total_fifo_size: Total internal RAM for FIFOs (bytes)
* @lpm_mode: For enabling Link Power Management in the controller
* 0 - Disable
* 1 - Enable
*
* @en_multiple_tx_fifo: Specifies whether dedicated per-endpoint transmit FIFOs
* are enabled for non-periodic IN endpoints in device
* mode.
* @num_dev_in_eps: Number of device IN endpoints available
* @num_dev_perio_in_ep: Number of device periodic IN endpoints
* available
* @dma_desc_enable: When DMA mode is enabled, specifies whether to use
* address DMA mode or descriptor DMA mode for accessing
* the data FIFOs. The driver will automatically detect the
* value for this if none is specified.
* 0 - Address DMA
* 1 - Descriptor DMA (default, if available)
* @power_optimized: Are power optimizations enabled?
* @hibernation: Is hibernation enabled?
* @utmi_phy_data_width: UTMI+ PHY data width
* 0 - 8 bits
* 1 - 16 bits
* 2 - 8 or 16 bits
* @acg_enable: For enabling Active Clock Gating in the controller
* 0 - Disable
* 1 - Enable
* @ipg_isoc_en: This feature indicates that the controller supports
* the worst-case scenario of Rx followed by Rx
* Interpacket Gap (IPG) (32 bitTimes) as per the utmi
* specification for any token following ISOC OUT token.
* 0 - Don't support
* 1 - Support
* @service_interval_mode: For enabling service interval based scheduling in the
* controller.
* 0 - Disable
* 1 - Enable
*/
struct dwc2_hw_params {
uint32_t snpsid;
uint32_t dev_ep_dirs;
unsigned op_mode : 3;
unsigned arch : 2;
unsigned enable_dynamic_fifo : 1;
unsigned host_channels : 5;
unsigned hs_phy_type : 2;
unsigned fs_phy_type : 2;
unsigned num_dev_ep : 4;
unsigned nperio_tx_q_depth : 3;
unsigned host_perio_tx_q_depth : 3;
unsigned dev_token_q_depth : 5;
unsigned max_transfer_size : 26;
unsigned max_packet_count : 11;
unsigned i2c_enable : 1;
unsigned total_fifo_size : 16;
unsigned lpm_mode : 1;
unsigned en_multiple_tx_fifo : 1;
unsigned num_dev_in_eps : 4;
unsigned num_dev_perio_in_ep : 4;
unsigned dma_desc_enable : 1;
unsigned power_optimized : 1;
unsigned hibernation : 1;
unsigned utmi_phy_data_width : 2;
unsigned acg_enable : 1;
unsigned ipg_isoc_en : 1;
unsigned service_interval_mode : 1;
};
#define DWC2_PHY_TYPE_PARAM_FS 0
#define DWC2_PHY_TYPE_PARAM_UTMI 1
#define DWC2_PHY_TYPE_PARAM_ULPI 2
struct dwc2_user_params {
uint8_t phy_type;
uint8_t phy_utmi_width;
bool device_dma_enable;
bool device_dma_desc_enable;
/* (5 * number of control endpoints + 8) + ((largest USB packet used / 4) + 1 for
* status information) + (2 * number of OUT endpoints) + 1 for Global NAK
*/
uint16_t device_rx_fifo_size;
/* IN Endpoints Max packet Size / 4 */
uint16_t device_tx_fifo_size[MAX_EPS_CHANNELS];
bool host_dma_desc_enable;
/*
* (largest USB packet used / 4) + 1 for status information + 1 transfer complete +
* 1 location each for Bulk/Control endpoint for handling NAK/NYET scenario
*/
uint16_t host_rx_fifo_size;
/* largest non-periodic USB packet used / 4 */
uint16_t host_nperio_tx_fifo_size;
/* largest periodic USB packet used / 4 */
uint16_t host_perio_tx_fifo_size;
uint32_t device_gccfg;
uint32_t host_gccfg;
bool b_session_valid_override;
uint32_t total_fifo_size;
};
struct usb_dwc2_user_fifo_config {
/* (5 * number of control endpoints + 8) + ((largest USB packet used / 4) + 1 for
* status information) + (2 * number of OUT endpoints) + 1 for Global NAK
*/
uint16_t device_rx_fifo_size;
/* IN Endpoints Max packet Size / 4 */
uint16_t device_tx_fifo_size[MAX_EPS_CHANNELS];
};
static inline void dwc2_get_hwparams(uint32_t reg_base, struct dwc2_hw_params *hw)
{
unsigned int width;
uint32_t snpsid, hwcfg1, hwcfg2, hwcfg3, hwcfg4;
snpsid = dwc2_readl(reg_base + GSNPSID_OFFSET);
hwcfg1 = dwc2_readl(reg_base + GHWCFG1_OFFSET);
hwcfg2 = dwc2_readl(reg_base + GHWCFG2_OFFSET);
hwcfg3 = dwc2_readl(reg_base + GHWCFG3_OFFSET);
hwcfg4 = dwc2_readl(reg_base + GHWCFG4_OFFSET);
/* snpsid */
hw->snpsid = snpsid;
/* hwcfg1 */
hw->dev_ep_dirs = hwcfg1;
/* hwcfg2 */
hw->op_mode = (hwcfg2 & GHWCFG2_OP_MODE_MASK) >>
GHWCFG2_OP_MODE_SHIFT;
hw->arch = (hwcfg2 & GHWCFG2_ARCHITECTURE_MASK) >>
GHWCFG2_ARCHITECTURE_SHIFT;
hw->enable_dynamic_fifo = !!(hwcfg2 & GHWCFG2_DYNAMIC_FIFO);
hw->host_channels = 1 + ((hwcfg2 & GHWCFG2_NUM_HOST_CHAN_MASK) >>
GHWCFG2_NUM_HOST_CHAN_SHIFT);
hw->hs_phy_type = (hwcfg2 & GHWCFG2_HS_PHY_TYPE_MASK) >>
GHWCFG2_HS_PHY_TYPE_SHIFT;
hw->fs_phy_type = (hwcfg2 & GHWCFG2_FS_PHY_TYPE_MASK) >>
GHWCFG2_FS_PHY_TYPE_SHIFT;
hw->num_dev_ep = (hwcfg2 & GHWCFG2_NUM_DEV_EP_MASK) >>
GHWCFG2_NUM_DEV_EP_SHIFT;
hw->nperio_tx_q_depth =
(hwcfg2 & GHWCFG2_NONPERIO_TX_Q_DEPTH_MASK) >>
GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT << 1;
hw->host_perio_tx_q_depth =
(hwcfg2 & GHWCFG2_HOST_PERIO_TX_Q_DEPTH_MASK) >>
GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT << 1;
hw->dev_token_q_depth =
(hwcfg2 & GHWCFG2_DEV_TOKEN_Q_DEPTH_MASK) >>
GHWCFG2_DEV_TOKEN_Q_DEPTH_SHIFT;
/* hwcfg3 */
width = (hwcfg3 & GHWCFG3_XFER_SIZE_CNTR_WIDTH_MASK) >>
GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT;
hw->max_transfer_size = (1 << (width + 11)) - 1;
width = (hwcfg3 & GHWCFG3_PACKET_SIZE_CNTR_WIDTH_MASK) >>
GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT;
hw->max_packet_count = (1 << (width + 4)) - 1;
hw->i2c_enable = !!(hwcfg3 & GHWCFG3_I2C);
hw->total_fifo_size = (hwcfg3 & GHWCFG3_DFIFO_DEPTH_MASK) >>
GHWCFG3_DFIFO_DEPTH_SHIFT;
hw->lpm_mode = !!(hwcfg3 & GHWCFG3_OTG_LPM_EN);
/* hwcfg4 */
hw->en_multiple_tx_fifo = !!(hwcfg4 & GHWCFG4_DED_FIFO_EN);
hw->num_dev_perio_in_ep = (hwcfg4 & GHWCFG4_NUM_DEV_PERIO_IN_EP_MASK) >>
GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT;
hw->num_dev_in_eps = (hwcfg4 & GHWCFG4_NUM_IN_EPS_MASK) >>
GHWCFG4_NUM_IN_EPS_SHIFT;
hw->dma_desc_enable = !!(hwcfg4 & GHWCFG4_DESC_DMA);
hw->power_optimized = !!(hwcfg4 & GHWCFG4_POWER_OPTIMIZ);
hw->hibernation = !!(hwcfg4 & GHWCFG4_HIBER);
hw->utmi_phy_data_width = (hwcfg4 & GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK) >>
GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT;
hw->acg_enable = !!(hwcfg4 & GHWCFG4_ACG_SUPPORTED);
hw->ipg_isoc_en = !!(hwcfg4 & GHWCFG4_IPG_ISOC_SUPPORTED);
hw->service_interval_mode = !!(hwcfg4 &
GHWCFG4_SERVICE_INTERVAL_SUPPORTED);
}
void dwc2_get_user_params(uint32_t reg_base, struct dwc2_user_params *params);
void dwc2_get_user_fifo_config(uint32_t reg_base, struct usb_dwc2_user_fifo_config *config);
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,113 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbh_core.h"
#include "usb_dwc2_param.h"
extern unsigned int system_core_clock;
uint32_t SystemCoreClock;
const struct dwc2_user_params param_pa11_pa12 = {
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
.device_dma_enable = false,
.device_dma_desc_enable = false,
.device_rx_fifo_size = (320 - 16 - 16 - 16 - 16),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 16, // 64 byte
[2] = 16, // 64 byte
[3] = 16, // 64 byte
[4] = 0,
[5] = 0,
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
#ifdef AT32F415xx
.device_gccfg = ((1 << 16) | (1 << 18) | (1 << 19) | (1 << 21)),
#else
.device_gccfg = ((1 << 16) | (1 << 21)),
#endif
.total_fifo_size = 320 // 1280 byte
};
#if __has_include("at32f402_405.h")
#include "at32f402_405.h"
const struct dwc2_user_params param_pb14_pb15 = {
.phy_type = DWC2_PHY_TYPE_PARAM_UTMI,
.device_dma_enable = true,
.device_dma_desc_enable = false,
.device_rx_fifo_size = (1008 - 16 - 256 - 128 - 128 - 128 - 128),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 256, // 1024 byte
[2] = 128, // 512 byte
[3] = 128, // 512 byte
[4] = 128, // 512 byte
[5] = 128, // 512 byte
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.host_dma_desc_enable = false,
.host_rx_fifo_size = 624,
.host_nperio_tx_fifo_size = 128, // 512 byte
.host_perio_tx_fifo_size = 256, // 1024 byte
.device_gccfg = ((1 << 16) | (1 << 21)),
.host_gccfg = ((1 << 16) | (1 << 21))
};
#endif
#ifndef CONFIG_USB_DWC2_CUSTOM_PARAM
void dwc2_get_user_params(uint32_t reg_base, struct dwc2_user_params *params)
{
SystemCoreClock = system_core_clock;
#if __has_include("at32f402_405.h")
if (reg_base == OTGHS_BASE) {
memcpy(params, &param_pb14_pb15, sizeof(struct dwc2_user_params));
} else {
memcpy(params, &param_pa11_pa12, sizeof(struct dwc2_user_params));
}
#else
memcpy(params, &param_pa11_pa12, sizeof(struct dwc2_user_params));
#endif
#ifdef CONFIG_USB_DWC2_CUSTOM_FIFO
struct usb_dwc2_user_fifo_config s_dwc2_fifo_config;
dwc2_get_user_fifo_config(reg_base, &s_dwc2_fifo_config);
params->device_rx_fifo_size = s_dwc2_fifo_config.device_rx_fifo_size;
for (uint8_t i = 0; i < MAX_EPS_CHANNELS; i++) {
params->device_tx_fifo_size[i] = s_dwc2_fifo_config.device_tx_fifo_size[i];
}
#endif
}
#endif
void usbd_dwc2_delay_ms(uint8_t ms)
{
uint32_t count = SystemCoreClock / 1000 * ms;
while (count--) {
__asm volatile("nop");
}
}
@@ -0,0 +1,291 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include "esp_idf_version.h"
#include "esp_intr_alloc.h"
#include "esp_private/usb_phy.h"
#include "soc/periph_defs.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "usbd_core.h"
#include "usbh_core.h"
#include "usb_dwc2_param.h"
#define GET_USB_INDEX(reg_base) 0
#define GET_USB_INTR_SOURCE(reg_base) ETS_USB_INTR_SOURCE
#define GET_USB_PHY_TARGET(reg_base) USB_PHY_TARGET_INT
#define GET_USB_PHY_SPEED(reg_base) USB_PHY_SPEED_UNDEFINED
#ifdef CONFIG_IDF_TARGET_ESP32S2
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ
#define DEFAULT_USB_INTR_SOURCE ETS_USB_INTR_SOURCE
#elif CONFIG_IDF_TARGET_ESP32S3
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ
#define DEFAULT_USB_INTR_SOURCE ETS_USB_INTR_SOURCE
#elif CONFIG_IDF_TARGET_ESP32P4
#undef GET_USB_INDEX
#define GET_USB_INDEX(reg_base) ((reg_base) == (void*)ESP_USB_HS0_BASE ? 0 : 1)
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ
#define DEFAULT_USB_INTR_SOURCE ETS_USB_OTG_INTR_SOURCE
#define USB_FS_INTR_SOURCE ETS_USB_OTG11_CH0_INTR_SOURCE
#undef GET_USB_INTR_SOURCE
#define GET_USB_INTR_SOURCE(reg_base) ((reg_base) == (void*)ESP_USB_HS0_BASE ? DEFAULT_USB_INTR_SOURCE : USB_FS_INTR_SOURCE)
#undef GET_USB_PHY_TARGET
#define GET_USB_PHY_TARGET(reg_base) ((reg_base) == (void*)ESP_USB_HS0_BASE ? USB_PHY_TARGET_UTMI : USB_PHY_TARGET_INT)
#undef GET_USB_PHY_SPEED
#define GET_USB_PHY_SPEED(reg_base) ((reg_base) == (void*)ESP_USB_HS0_BASE ? USB_PHY_SPEED_HIGH : USB_PHY_SPEED_FULL)
#else
#define DEFAULT_CPU_FREQ_MHZ 160
#endif
uint32_t SystemCoreClock = (DEFAULT_CPU_FREQ_MHZ * 1000 * 1000);
static usb_phy_handle_t s_phy_handle[SOC_USB_OTG_PERIPH_NUM] = {NULL};
static intr_handle_t s_interrupt_handle[SOC_USB_OTG_PERIPH_NUM] = {NULL};
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
const struct dwc2_user_params param_fs = {
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
.device_dma_enable = true,
.device_dma_desc_enable = false,
.device_rx_fifo_size = (200 - 16 * 7),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 16, // 64 byte
[2] = 16, // 64 byte
[3] = 16, // 64 byte
[4] = 16, // 64 byte
[5] = 16, // 64 byte
[6] = 16, // 64 byte
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.host_dma_desc_enable = false,
.host_rx_fifo_size = 80,
.host_nperio_tx_fifo_size = 60, // 240 byte
.host_perio_tx_fifo_size = 60, // 240 byte
};
#elif CONFIG_IDF_TARGET_ESP32P4
const struct dwc2_user_params param_fs = {
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
.device_dma_enable = true,
.device_dma_desc_enable = false,
.device_rx_fifo_size = (200 - 16 * 7),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 16, // 64 byte
[2] = 16, // 64 byte
[3] = 16, // 64 byte
[4] = 16, // 64 byte
[5] = 16, // 64 byte
[6] = 16, // 64 byte
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.host_dma_desc_enable = false,
.host_rx_fifo_size = (200 - 60 - 60),
.host_nperio_tx_fifo_size = 60, // 240 byte
.host_perio_tx_fifo_size = 60, // 240 byte
};
const struct dwc2_user_params param_hs = {
.phy_type = DWC2_PHY_TYPE_PARAM_UTMI,
.device_dma_enable = true,
.device_dma_desc_enable = false,
.device_rx_fifo_size = (896 - 16 - 128 - 128 - 128 - 128 - 16 - 16),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 128, // 512 byte
[2] = 128, // 512 byte
[3] = 128, // 512 byte
[4] = 128, // 512 byte
[5] = 16, // 64 byte
[6] = 16, // 64 byte
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.host_dma_desc_enable = false,
.host_rx_fifo_size = (896 - 128 - 128),
.host_nperio_tx_fifo_size = 128, // 512 byte
.host_perio_tx_fifo_size = 128, // 512 byte
};
#endif
static void usb_dc_interrupt_cb(void *arg_pv)
{
extern void USBD_IRQHandler(uint8_t busid);
uint8_t busid = (uintptr_t)arg_pv;
USBD_IRQHandler(busid);
}
void usb_dc_low_level_init(uint8_t busid)
{
esp_err_t ret;
void *reg_base = (void*)g_usbdev_bus[busid].reg_base;
(void)reg_base;
usb_phy_config_t phy_config = {
.controller = USB_PHY_CTRL_OTG,
.otg_mode = USB_OTG_MODE_DEVICE,
};
phy_config.target = GET_USB_PHY_TARGET(reg_base);
phy_config.otg_speed = GET_USB_PHY_SPEED(reg_base);
ret = usb_new_phy(&phy_config, &s_phy_handle[GET_USB_INDEX(reg_base)]);
if (ret != ESP_OK) {
USB_LOG_ERR("USB Phy Init Failed!\r\n");
return;
}
uintptr_t arg = busid;
// TODO: Check when to enable interrupt
ret = esp_intr_alloc(GET_USB_INTR_SOURCE(reg_base), ESP_INTR_FLAG_LOWMED, usb_dc_interrupt_cb, (void *)arg, &s_interrupt_handle[GET_USB_INDEX(reg_base)]);
if (ret != ESP_OK) {
USB_LOG_ERR("USB Interrupt Init Failed!\r\n");
return;
}
USB_LOG_INFO("cherryusb, version: " CHERRYUSB_VERSION_STR "\r\n");
}
void usb_dc_low_level_deinit(uint8_t busid)
{
void *reg_base = (void*)g_usbdev_bus[busid].reg_base;
(void)reg_base;
if (s_interrupt_handle[GET_USB_INDEX(reg_base)]) {
esp_intr_free(s_interrupt_handle[GET_USB_INDEX(reg_base)]);
s_interrupt_handle[GET_USB_INDEX(reg_base)] = NULL;
}
if (s_phy_handle[GET_USB_INDEX(reg_base)]) {
usb_del_phy(s_phy_handle[GET_USB_INDEX(reg_base)]);
s_phy_handle[GET_USB_INDEX(reg_base)] = NULL;
}
}
static void usb_hc_interrupt_cb(void *arg_pv)
{
extern void USBH_IRQHandler(uint8_t busid);
uint8_t busid = (uintptr_t)arg_pv;
USBH_IRQHandler(busid);
}
void usb_hc_low_level_init(struct usbh_bus *bus)
{
void *reg_base = (void*)bus->hcd.reg_base;
(void)reg_base;
// Host Library defaults to internal PHY
usb_phy_config_t phy_config = {
.controller = USB_PHY_CTRL_OTG,
.otg_mode = USB_OTG_MODE_HOST,
.otg_speed = USB_PHY_SPEED_UNDEFINED, // In Host mode, the speed is determined by the connected device
.ext_io_conf = NULL,
.otg_io_conf = NULL,
};
phy_config.target = GET_USB_PHY_TARGET(reg_base);
esp_err_t ret = usb_new_phy(&phy_config, &s_phy_handle[GET_USB_INDEX(reg_base)]);
if (ret != ESP_OK) {
USB_LOG_ERR("USB Phy Init Failed!\r\n");
return;
}
uintptr_t arg = bus->busid;
// TODO: Check when to enable interrupt
ret = esp_intr_alloc(GET_USB_INTR_SOURCE(reg_base), ESP_INTR_FLAG_LOWMED, usb_hc_interrupt_cb, (void*)(arg), &s_interrupt_handle[GET_USB_INDEX(reg_base)]);
if (ret != ESP_OK) {
USB_LOG_ERR("USB Interrupt Init Failed!\r\n");
return;
}
USB_LOG_INFO("cherryusb, version: " CHERRYUSB_VERSION_STR "\r\n");
}
void usb_hc_low_level_deinit(struct usbh_bus *bus)
{
void *reg_base = (void*)bus->hcd.reg_base;
(void)reg_base;
if (s_interrupt_handle[GET_USB_INDEX(reg_base)]) {
esp_intr_free(s_interrupt_handle[GET_USB_INDEX(reg_base)]);
s_interrupt_handle[GET_USB_INDEX(reg_base)] = NULL;
}
if (s_phy_handle[GET_USB_INDEX(reg_base)]) {
usb_del_phy(s_phy_handle[GET_USB_INDEX(reg_base)]);
s_phy_handle[GET_USB_INDEX(reg_base)] = NULL;
}
}
void dwc2_get_user_params(uint32_t reg_base, struct dwc2_user_params *params)
{
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
memcpy(params, &param_fs, sizeof(struct dwc2_user_params));
#elif CONFIG_IDF_TARGET_ESP32P4
if (reg_base == ESP_USB_HS0_BASE) {
memcpy(params, &param_hs, sizeof(struct dwc2_user_params));
} else {
memcpy(params, &param_fs, sizeof(struct dwc2_user_params));
}
#endif
#ifdef CONFIG_USB_DWC2_CUSTOM_FIFO
struct usb_dwc2_user_fifo_config s_dwc2_fifo_config;
dwc2_get_user_fifo_config(reg_base, &s_dwc2_fifo_config);
params->device_rx_fifo_size = s_dwc2_fifo_config.device_rx_fifo_size;
for (uint8_t i = 0; i < MAX_EPS_CHANNELS; i++)
{
params->device_tx_fifo_size[i] = s_dwc2_fifo_config.device_tx_fifo_size[i];
}
#endif
}
void usbd_dwc2_delay_ms(uint8_t ms)
{
vTaskDelay(pdMS_TO_TICKS(ms));
}
#ifdef CONFIG_USB_DCACHE_ENABLE
#include "esp_cache.h"
void usb_dcache_clean(uintptr_t addr, size_t size)
{
if (size == 0)
return;
esp_cache_msync((void *)addr, size, ESP_CACHE_MSYNC_FLAG_TYPE_DATA | ESP_CACHE_MSYNC_FLAG_DIR_C2M);
}
void usb_dcache_invalidate(uintptr_t addr, size_t size)
{
if (size == 0)
return;
esp_cache_msync((void *)addr, size, ESP_CACHE_MSYNC_FLAG_TYPE_DATA | ESP_CACHE_MSYNC_FLAG_DIR_M2C);
}
void usb_dcache_flush(uintptr_t addr, size_t size)
{
if (size == 0)
return;
esp_cache_msync((void *)addr, size, ESP_CACHE_MSYNC_FLAG_TYPE_DATA | ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_DIR_M2C);
}
#endif
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usb_config.h"
#include "stdint.h"
#include "usb_dwc2_reg.h"
#if 1
#error you need to modify some usb register values then use this chip
#endif
#if CONFIG_USBDEV_EP_NUM != 4 && CONFIG_USBDEV_EP_NUM != 6
#error "gd32 only has 4 endpoints for pa11/pa12 and 6 endpoints for pb14/pb15"
#endif
/* you can find this config in function:usb_core_init, file:drv_usb_core.c, for example:
*
* usb_regs->gr->GCCFG |= GCCFG_PWRON | GCCFG_VBUSACEN | GCCFG_VBUSBCEN;
*
*/
uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base)
{
#ifdef CONFIG_USB_HS
return 0;
#else
return ((1 << 16) | (1 << 18) | (1 << 19) | (1 << 21));
#endif
}
uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
{
#ifdef CONFIG_USB_HS
return 0;
#else
return ((1 << 16) | (1 << 18) | (1 << 19) | (1 << 21));
#endif
}
extern uint32_t SystemCoreClock;
void usbd_dwc2_delay_ms(uint8_t ms)
{
uint32_t count = SystemCoreClock / 1000 * ms;
while (count--) {
__asm volatile("nop");
}
}
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usb_config.h"
#include "usb_dwc2_reg.h"
/* When using [GPIO_SetFunc(USBF_VBUS_PORT, USBF_VBUS_PIN, USBF_VBUS_FUNC);], there is no need to configure GOTGCTL */
#define USB_OTG_GLB ((DWC2_GlobalTypeDef *)(reg_base))
uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base)
{
USB_OTG_GLB->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN;
USB_OTG_GLB->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL;
return 0;
}
uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
{
USB_OTG_GLB->GOTGCTL &= ~USB_OTG_GOTGCTL_BVALOEN;
USB_OTG_GLB->GOTGCTL &= ~USB_OTG_GOTGCTL_BVALOVAL;
return 0;
}
extern uint32_t SystemCoreClock;
void usbd_dwc2_delay_ms(uint8_t ms)
{
uint32_t count = SystemCoreClock / 1000 * ms;
while (count--) {
__asm volatile("nop");
}
}
@@ -0,0 +1,224 @@
/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtthread.h>
#include <rthw.h>
#include "usbd_core.h"
#include "usbh_core.h"
#include "usb_dwc2_param.h"
#include <riscv_io.h>
#include "sysctl_rst.h"
#include "ioremap.h"
#include "mmu.h"
#include "cache.h"
extern rt_mmu_info mmu_info;
#if defined(ENABLE_CHERRY_USB) || defined(PKG_USING_CHERRYUSB) || defined(RT_USING_CHERRYUSB)
#define DEFAULT_USB_HCLK_FREQ_MHZ 200
uint32_t SystemCoreClock = (DEFAULT_USB_HCLK_FREQ_MHZ * 1000 * 1000);
const uintptr_t usb_dev_addr[2] = { 0x91500000UL, 0x91540000UL };
#define USB_IDPULLUP0 (1 << 4)
#define USB_DMPULLDOWN0 (1 << 8)
#define USB_DPPULLDOWN0 (1 << 9)
const struct dwc2_user_params param_common = {
.phy_type = DWC2_PHY_TYPE_PARAM_UTMI,
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
.device_dma_enable = true,
#else
.device_dma_enable = false,
#endif
.device_dma_desc_enable = false,
.device_rx_fifo_size = (3016 - 16 - 256 * 8),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 512, // 1024 byte, double buffer
[2] = 256, // 1024 byte
[3] = 512, // 1024 byte, double buffer
[4] = 256, // 1024 byte
[5] = 256, // 1024 byte
[6] = 256, // 1024 byte
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.host_dma_desc_enable = false,
.host_rx_fifo_size = 3016 - 128 * 2 - 256 * 2,
.host_nperio_tx_fifo_size = 128 * 2, // 512 byte, double buffer
.host_perio_tx_fifo_size = 256 * 2, // 1024 byte, double buffer
.device_gccfg = 0,
.host_gccfg = 0
};
#ifndef CONFIG_USB_DWC2_CUSTOM_PARAM
void dwc2_get_user_params(uint32_t reg_base, struct dwc2_user_params *params)
{
memcpy(params, &param_common, sizeof(struct dwc2_user_params));
#ifdef CONFIG_USB_DWC2_CUSTOM_FIFO
struct usb_dwc2_user_fifo_config s_dwc2_fifo_config;
dwc2_get_user_fifo_config(reg_base, &s_dwc2_fifo_config);
params->device_rx_fifo_size = s_dwc2_fifo_config.device_rx_fifo_size;
for (uint8_t i = 0; i < MAX_EPS_CHANNELS; i++) {
params->device_tx_fifo_size[i] = s_dwc2_fifo_config.device_tx_fifo_size[i];
}
#endif
}
#endif
// USB Host
#if defined(ENABLE_CHERRY_USB_HOST) || defined(PKG_CHERRYUSB_HOST) || defined(RT_CHERRYUSB_HOST)
static void usb_hc_interrupt_cb(int irq, void *arg_pv)
{
USBH_IRQHandler((uint8_t)(uintptr_t)arg_pv);
}
void usb_hc_low_level_init(struct usbh_bus *bus)
{
uint32_t *hs_reg;
uint32_t usb_ctl3;
if ((uintptr_t)rt_hw_mmu_v2p(&mmu_info, (void *)bus->hcd.reg_base) == usb_dev_addr[0]) {
if (!sysctl_reset(SYSCTL_RESET_USB0)) {
USB_LOG_ERR("reset usb0 fail\n");
}
hs_reg = (uint32_t *)rt_ioremap((void *)(0x91585000 + 0x7C), 0x1000);
usb_ctl3 = *hs_reg | USB_IDPULLUP0;
*hs_reg = usb_ctl3 | (USB_DMPULLDOWN0 | USB_DPPULLDOWN0);
rt_iounmap(hs_reg);
rt_hw_interrupt_install(173, usb_hc_interrupt_cb, (void *)(uintptr_t)bus->hcd.hcd_id, "usbh0");
rt_hw_interrupt_umask(173);
} else {
if (!sysctl_reset(SYSCTL_RESET_USB1)) {
USB_LOG_ERR("reset usb1 fail\n");
}
hs_reg = (uint32_t *)rt_ioremap((void *)(0x91585000 + 0x9C), 0x1000);
usb_ctl3 = *hs_reg | USB_IDPULLUP0;
*hs_reg = usb_ctl3 | (USB_DMPULLDOWN0 | USB_DPPULLDOWN0);
rt_iounmap(hs_reg);
rt_hw_interrupt_install(174, usb_hc_interrupt_cb, (void *)(uintptr_t)bus->hcd.hcd_id, "usbh1");
rt_hw_interrupt_umask(174);
}
}
void usb_hc_low_level_deinit(struct usbh_bus *bus)
{
if ((uintptr_t)rt_hw_mmu_v2p(&mmu_info, (void *)bus->hcd.reg_base) == usb_dev_addr[0]) {
rt_hw_interrupt_mask(173);
} else {
rt_hw_interrupt_mask(174);
}
}
#endif // ENABLE_CHERRY_USB_HOST
// USB Device
#if defined(ENABLE_CHERRY_USB_DEVICE) || defined(PKG_CHERRYUSB_DEVICE) || defined(RT_CHERRYUSB_DEVICE)
static void usb_dc_interrupt_cb(int irq, void *arg_pv)
{
USBD_IRQHandler((uint8_t)(uintptr_t)arg_pv);
}
void usb_dc_low_level_init(uint8_t busid)
{
if ((uintptr_t)rt_hw_mmu_v2p(&mmu_info, (void *)g_usbdev_bus[busid].reg_base) == usb_dev_addr[0]) {
if (!sysctl_reset(SYSCTL_RESET_USB0)) {
USB_LOG_ERR("reset usb0 fail\n");
}
uint32_t *hs_reg = (uint32_t *)rt_ioremap((void *)(0x91585000 + 0x7C), 0x1000);
*hs_reg = 0x37;
rt_iounmap(hs_reg);
rt_hw_interrupt_install(173, usb_dc_interrupt_cb, (void *)(uintptr_t)busid, "usbd0");
rt_hw_interrupt_umask(173);
} else {
if (!sysctl_reset(SYSCTL_RESET_USB1)) {
USB_LOG_ERR("reset usb1 fail\n");
}
uint32_t *hs_reg = (uint32_t *)rt_ioremap((void *)(0x91585000 + 0x9C), 0x1000);
*hs_reg = 0x37;
rt_iounmap(hs_reg);
rt_hw_interrupt_install(174, usb_dc_interrupt_cb, (void *)(uintptr_t)busid, "usbd1");
rt_hw_interrupt_umask(174);
}
}
void usb_dc_low_level_deinit(uint8_t busid)
{
if ((uintptr_t)rt_hw_mmu_v2p(&mmu_info, (void *)g_usbdev_bus[busid].reg_base) == usb_dev_addr[0]) {
rt_hw_interrupt_mask(173);
} else {
rt_hw_interrupt_mask(174);
}
}
#endif // ENABLE_CHERRY_USB_DEVICE
void usbd_dwc2_delay_ms(uint8_t ms)
{
rt_thread_mdelay(ms);
}
#ifdef CONFIG_USB_DCACHE_ENABLE
void usb_dcache_clean(uintptr_t addr, size_t size)
{
rt_hw_cpu_dcache_clean((void *)addr, size);
}
void usb_dcache_invalidate(uintptr_t addr, size_t size)
{
rt_hw_cpu_dcache_invalidate((void *)addr, size);
}
void usb_dcache_flush(uintptr_t addr, size_t size)
{
rt_hw_cpu_dcache_clean_flush((void *)addr, size);
}
#endif
#endif // ENABLE_CHERRY_USB
@@ -0,0 +1,193 @@
/*
* Copyright (c) 2025, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbh_core.h"
__WEAK void USBD_IRQHandler(uint8_t busid)
{
}
__WEAK void USBH_IRQHandler(uint8_t busid)
{
}
#if defined(N32H473) || defined(N32H474) || defined(N32H475) || defined(N32H482) || defined(N32H487)
#include "n32h47x_48x_rcc.h"
#include "n32h47x_48x_gpio.h"
#include "n32h47x_48x_exti.h"
#include "misc.h"
typedef void (*usb_dwc2_irq)(uint8_t busid);
static usb_dwc2_irq g_usb_dwc2_irq;
static volatile uint8_t g_usb_dwc2_busid = 0;
static void usbhs_common_init(void)
{
RCC_EnableAHB1PeriphClk(RCC_AHB_PERIPHEN_GPIOA | RCC_AHB_PERIPHEN_GPIOB, ENABLE);
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE);
/* PLL= 240MHz */
#if (HSE_VALUE == 8000000)
/* Select PLL clock as USBHS clock source , clock 15 divisions = 16M */
RCC_ConfigUSBPLLPresClk(RCC_USBPLLCLK_SRC_PLL, RCC_USBPLLCLK_DIV15);
/* Select the corresponding bandwidth and frequency*/
RCC_ConfigUSBHSBandwidth(RCC_USBHS_BW_16M);
/* Select USBHS clock source frequency */
RCC_ConfigUSBHSFrequency(RCC_USBHS_FREQ_16_OR_32M);
/* Select PLL as USBHS clock */
RCC_ConfigUSBHSClk(RCC_USBHS_CLKSRC_PLLPRES);
#else //HSE 16M
RCC_ConfigUSBHSBandwidth(RCC_USBHS_BW_16M);
RCC_ConfigUSBHSFrequency(RCC_USBHS_FREQ_16_OR_32M);
RCC_ConfigUSBHSClk(RCC_USBHS_CLKSRC_HSE);
#endif
/* Reset the USBHS phy clock*/
RCC_EnableAHBPeriphReset(RCC_AHBPRST_USBHSPHYRST);
/* Enables the USBHS peripheral clock*/
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPHEN_USBHS, ENABLE);
NVIC_InitType NVIC_InitStructure;
// EXTI_InitType EXTI_InitStructure;
// NVIC_InitStructure.NVIC_IRQChannel = USB_HS_WKUP_IRQn;
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
// NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = USB_HS_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Configure the EXTI line 23 connected internally to the USBHS IP */
// EXTI_ClrITPendBit(EXTI_LINE23);
// EXTI_InitStructure.EXTI_Line = EXTI_LINE23;
// EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
// EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
// EXTI_InitStructure.EXTI_LineCmd = ENABLE;
// EXTI_InitPeripheral(&EXTI_InitStructure);
}
static void usbhs_gpio_init(void)
{
GPIO_InitType GPIO_InitStructure;
RCC_EnableAHB1PeriphClk(RCC_AHB_PERIPHEN_GPIOA | RCC_AHB_PERIPHEN_GPIOB | RCC_AHB_PERIPHEN_GPIOE, ENABLE);
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE);
GPIO_ConfigPinRemap(0, 0, GPIO_RMP_SWJ_SWD);
GPIO_InitStruct(&GPIO_InitStructure);
#ifdef USBHS_HOST
GPIO_InitStructure.Pin = GPIO_PIN_1;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitPeripheral(GPIOE, &GPIO_InitStructure);
GPIO_ResetBits(GPIOE, GPIO_PIN_1);
GPIO_InitStructure.Pin = GPIO_PIN_3;
GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
GPIO_ResetBits(GPIOB, GPIO_PIN_3);
#endif
// VBUS
// GPIO_InitStructure.Pin = GPIO_PIN_13;
// GPIO_InitStructure.GPIO_Mode = GPIO_MODE_INPUT;
// GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
// // SOF
// GPIO_InitStructure.Pin = GPIO_PIN_4;
// GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;
// GPIO_InitStructure.GPIO_Alternate = 8; // SOF
// GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
// // ID
// GPIO_InitStructure.Pin = GPIO_PIN_12;
// GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;
// GPIO_InitStructure.GPIO_Alternate = 14; // ID
// GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
}
void usb_dc_low_level_init(uint8_t busid)
{
g_usb_dwc2_irq = USBD_IRQHandler;
g_usb_dwc2_busid = busid;
usbhs_common_init();
RCC->USBHSCTRL2 |= (uint32_t)0x01 << 19;
RCC->USBHSCTRL1 |= (uint32_t)0x01 << 31;
}
void usb_dc_low_level_deinit(uint8_t busid)
{
NVIC_InitType NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USB_HS_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
NVIC_Init(&NVIC_InitStructure);
RCC_EnableAHBPeriphReset(RCC_AHBPRST_USBHSPHYRST);
/* Enables the USBHS peripheral clock*/
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPHEN_USBHS, DISABLE);
}
void usb_hc_low_level_init(struct usbh_bus *bus)
{
g_usb_dwc2_irq = USBH_IRQHandler;
g_usb_dwc2_busid = 0;
usbhs_common_init();
RCC->USBHSCTRL2 &= ~(uint32_t)0x01 << 19;
RCC->USBHSCTRL1 |= (uint32_t)0x01 << 31;
}
void usb_hc_low_level_deinit(struct usbh_bus *bus)
{
NVIC_InitType NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USB_HS_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
NVIC_Init(&NVIC_InitStructure);
RCC_EnableAHBPeriphReset(RCC_AHBPRST_USBHSPHYRST);
/* Enables the USBHS peripheral clock*/
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPHEN_USBHS, DISABLE);
}
uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base)
{
return 0;
}
uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
{
return 0;
}
void USB_HS_IRQHandler(void)
{
g_usb_dwc2_irq(g_usb_dwc2_busid);
}
extern uint32_t SystemCoreClock;
void usbd_dwc2_delay_ms(uint8_t ms)
{
uint32_t count = SystemCoreClock / 1000 * ms;
while (count--) {
__asm volatile("nop");
}
}
#endif
@@ -0,0 +1,750 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbh_core.h"
#include "usb_dwc2_param.h"
#ifndef CONFIG_USB_DWC2_CUSTOM_PARAM
#if __has_include("stm32f1xx_hal.h")
#include "stm32f1xx_hal.h"
const struct dwc2_user_params param_pa11_pa12 = {
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
.device_dma_enable = false,
.device_dma_desc_enable = false,
.device_rx_fifo_size = (320 - 16 - 16 - 16 - 16),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 16, // 64 byte
[2] = 16, // 64 byte
[3] = 16, // 64 byte
[4] = 0,
[5] = 0,
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.device_gccfg = ((1 << 16) | (1 << 21)), // fs: USB_OTG_GCCFG_PWRDWN | USB_OTG_GCCFG_NOVBUSSENS
.total_fifo_size = 320 // 1280 byte
};
const struct dwc2_user_params param_pb14_pb15 = { 0 }; // do not support
#if defined(HAL_HCD_MODULE_ENABLED)
#error "HAL_HCD_MODULE_ENABLED is not supported for STM32F1xx, please use HAL_PCD_MODULE_ENABLED"
#endif
#elif __has_include("stm32f2xx_hal.h")
#include "stm32f2xx_hal.h"
const struct dwc2_user_params param_pa11_pa12 = {
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
.device_dma_enable = false,
.device_dma_desc_enable = false,
.device_rx_fifo_size = (320 - 16 - 16 - 16 - 16),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 16, // 64 byte
[2] = 16, // 64 byte
[3] = 16, // 64 byte
[4] = 0,
[5] = 0,
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.device_gccfg = ((1 << 16) | (1 << 21)), // fs: USB_OTG_GCCFG_PWRDWN | USB_OTG_GCCFG_NOVBUSSENS
.total_fifo_size = 320 // 1280 byte
};
const struct dwc2_user_params param_pb14_pb15 = {
#ifdef CONFIG_USB_HS
.phy_type = DWC2_PHY_TYPE_PARAM_UTMI,
#else
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
#endif
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
.device_dma_enable = true,
#else
.device_dma_enable = false,
#endif
.device_dma_desc_enable = false,
.device_rx_fifo_size = (1012 - 16 - 256 - 128 - 128 - 128 - 128),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 256, // 1024 byte
[2] = 128, // 512 byte
[3] = 128, // 512 byte
[4] = 128, // 512 byte
[5] = 128, // 512 byte
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.host_dma_desc_enable = false,
.host_rx_fifo_size = 628,
.host_nperio_tx_fifo_size = 128, // 512 byte
.host_perio_tx_fifo_size = 256, // 1024 byte
#ifdef CONFIG_USB_HS
.device_gccfg = 0,
.host_gccfg = 0,
#else
.device_gccfg = ((1 << 16) | (1 << 21)), // fs: USB_OTG_GCCFG_PWRDWN | USB_OTG_GCCFG_NOVBUSSENS hs:0
.host_gccfg = ((1 << 16) | (1 << 21)) // fs: USB_OTG_GCCFG_PWRDWN | USB_OTG_GCCFG_NOVBUSSENS hs:0
#endif
};
#elif __has_include("stm32f4xx_hal.h")
#include "stm32f4xx_hal.h"
const struct dwc2_user_params param_pa11_pa12 = {
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
.device_dma_enable = false,
.device_dma_desc_enable = false,
.device_rx_fifo_size = (320 - 16 - 16 - 16 - 16),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 16, // 64 byte
[2] = 16, // 64 byte
[3] = 16, // 64 byte
[4] = 0,
[5] = 0,
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
#if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || \
defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || \
defined(STM32F423xx)
.device_gccfg = (1 << 16), // fs: USB_OTG_GCCFG_PWRDWN
.b_session_valid_override = true,
#else
.device_gccfg = ((1 << 16) | (1 << 21)), // fs: USB_OTG_GCCFG_PWRDWN | USB_OTG_GCCFG_NOVBUSSENS
#endif
.total_fifo_size = 320 // 1280 byte
};
const struct dwc2_user_params param_pb14_pb15 = {
#ifdef CONFIG_USB_HS
.phy_type = DWC2_PHY_TYPE_PARAM_UTMI,
#else
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
#endif
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
.device_dma_enable = true,
#else
.device_dma_enable = false,
#endif
.device_dma_desc_enable = false,
.device_rx_fifo_size = (1006 - 16 - 256 - 128 - 128 - 128 - 128), // 1006/1012
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 256, // 1024 byte
[2] = 128, // 512 byte
[3] = 128, // 512 byte
[4] = 128, // 512 byte
[5] = 128, // 512 byte
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.host_dma_desc_enable = false,
.host_rx_fifo_size = 622,
.host_nperio_tx_fifo_size = 128, // 512 byte
.host_perio_tx_fifo_size = 256, // 1024 byte
#ifdef CONFIG_USB_HS
.device_gccfg = 0,
.host_gccfg = 0,
#else
#if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || \
defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || \
defined(STM32F423xx)
.device_gccfg = (1 << 16), // fs: USB_OTG_GCCFG_PWRDWN
.host_gccfg = (1 << 16), // fs: USB_OTG_GCCFG_PWRDWN
.b_session_valid_override = true,
#else
.device_gccfg = ((1 << 16) | (1 << 21)), // fs: USB_OTG_GCCFG_PWRDWN | USB_OTG_GCCFG_NOVBUSSENS hs:0
.host_gccfg = ((1 << 16) | (1 << 21)) // fs: USB_OTG_GCCFG_PWRDWN | USB_OTG_GCCFG_NOVBUSSENS hs:0
#endif
#endif
};
#elif __has_include("stm32f7xx_hal.h")
#include "stm32f7xx_hal.h"
const struct dwc2_user_params param_pa11_pa12 = {
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
.device_dma_enable = false,
.device_dma_desc_enable = false,
.device_rx_fifo_size = (320 - 16 - 16 - 16 - 16),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 16, // 64 byte
[2] = 16, // 64 byte
[3] = 16, // 64 byte
[4] = 0,
[5] = 0,
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.device_gccfg = (1 << 16), // fs: USB_OTG_GCCFG_PWRDWN
.host_gccfg = (1 << 16), // fs: USB_OTG_GCCFG_PWRDWN
.b_session_valid_override = true,
.total_fifo_size = 320 // 1280 byte
};
const struct dwc2_user_params param_pb14_pb15 = {
#if defined(STM32F722xx) || defined(STM32F723xx) || defined(STM32F730xx) || defined(STM32F732xx) || defined(STM32F733xx)
.phy_type = DWC2_PHY_TYPE_PARAM_UTMI,
#else
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
#endif
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
.device_dma_enable = true,
#else
.device_dma_enable = false,
#endif
.device_dma_desc_enable = false,
.device_rx_fifo_size = (1006 - 16 - 256 - 128 - 128 - 128 - 128),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 256, // 1024 byte
[2] = 128, // 512 byte
[3] = 128, // 512 byte
[4] = 128, // 512 byte
[5] = 128, // 512 byte
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.host_dma_desc_enable = false,
.host_rx_fifo_size = 622,
.host_nperio_tx_fifo_size = 128, // 512 byte
.host_perio_tx_fifo_size = 256, // 1024 byte
#if defined(STM32F722xx) || defined(STM32F723xx) || defined(STM32F730xx) || defined(STM32F732xx) || defined(STM32F733xx)
.device_gccfg = (1 << 23), // USB_OTG_GCCFG_PHYHSEN
.host_gccfg = (1 << 23), // USB_OTG_GCCFG_PHYHSEN
#else
#ifdef CONFIG_USB_HS
.device_gccfg = 0,
.host_gccfg = 0,
#else
.device_gccfg = (1 << 16), // fs: USB_OTG_GCCFG_PWRDWN hs:0
.host_gccfg = (1 << 16), // fs: USB_OTG_GCCFG_PWRDWN hs:0
#endif
#endif
.b_session_valid_override = true
};
#elif __has_include("stm32h7xx_hal.h")
#include "stm32h7xx_hal.h"
const struct dwc2_user_params param_pa11_pa12 = {
.phy_type = DWC2_PHY_TYPE_PARAM_FS, // DWC2_PHY_TYPE_PARAM_UTMI
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
.device_dma_enable = true,
#else
.device_dma_enable = false,
#endif
.device_dma_desc_enable = false,
.device_rx_fifo_size = (952 - 16 - 256 - 128 - 128 - 128 - 128),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 256, // 1024 byte
[2] = 128, // 512 byte
[3] = 128, // 512 byte
[4] = 128, // 512 byte
[5] = 128, // 512 byte
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.host_dma_desc_enable = false,
.host_rx_fifo_size = 568,
.host_nperio_tx_fifo_size = 128, // 512 byte
.host_perio_tx_fifo_size = 256, // 1024 byte
.device_gccfg = (1 << 16), // fs: USB_OTG_GCCFG_PWRDWN hs:0
.host_gccfg = (1 << 16), // fs: USB_OTG_GCCFG_PWRDWN hs:0
.b_session_valid_override = true
};
const struct dwc2_user_params param_pb14_pb15 = {
#ifdef CONFIG_USB_HS
.phy_type = DWC2_PHY_TYPE_PARAM_UTMI,
#else
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
#endif
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
.device_dma_enable = true,
#else
.device_dma_enable = false,
#endif
.device_dma_desc_enable = false,
.device_rx_fifo_size = (952 - 16 - 256 - 128 - 128 - 128 - 128),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 256, // 1024 byte
[2] = 128, // 512 byte
[3] = 128, // 512 byte
[4] = 128, // 512 byte
[5] = 128, // 512 byte
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.host_dma_desc_enable = false,
.host_rx_fifo_size = 568,
.host_nperio_tx_fifo_size = 128, // 512 byte
.host_perio_tx_fifo_size = 256, // 1024 byte
#ifdef CONFIG_USB_HS
.device_gccfg = 0,
.host_gccfg = 0,
#else
.device_gccfg = (1 << 16), // fs: USB_OTG_GCCFG_PWRDWN hs:0
.host_gccfg = (1 << 16), // fs: USB_OTG_GCCFG_PWRDWN hs:0
#endif
.b_session_valid_override = true
};
#elif __has_include("stm32h7rsxx_hal.h")
#include "stm32h7rsxx_hal.h"
const struct dwc2_user_params param_pa11_pa12 = {
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
.device_dma_enable = false,
.device_dma_desc_enable = false,
.device_rx_fifo_size = (320 - 16 - 16 - 16 - 16),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 16, // 64 byte
[2] = 16, // 64 byte
[3] = 16, // 64 byte
[4] = 0,
[5] = 0,
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.device_gccfg = (1 << 16), // fs: USB_OTG_GCCFG_PWRDWN
.b_session_valid_override = true,
.total_fifo_size = 320 // 1280 byte
};
const struct dwc2_user_params param_pb14_pb15 = {
.phy_type = DWC2_PHY_TYPE_PARAM_UTMI,
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
.device_dma_enable = true,
#else
.device_dma_enable = false,
#endif
.device_dma_desc_enable = false,
.device_rx_fifo_size = (952 - 16 - 256 - 128 - 128 - 128 - 128),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 256, // 1024 byte
[2] = 128, // 512 byte
[3] = 128, // 512 byte
[4] = 128, // 512 byte
[5] = 128, // 512 byte
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.host_dma_desc_enable = false,
.host_rx_fifo_size = 568,
.host_nperio_tx_fifo_size = 128, // 512 byte
.host_perio_tx_fifo_size = 256, // 1024 byte
.device_gccfg = ((1 << 23) | (1 << 24)), // hs: USB_OTG_GCCFG_VBVALEXTOEN | USB_OTG_GCCFG_VBVALOVAL
.host_gccfg = (1 << 25) // hs: USB_OTG_GCCFG_PULLDOWNEN
};
#elif __has_include("stm32l4xx_hal.h")
#include "stm32l4xx_hal.h"
const struct dwc2_user_params param_pa11_pa12 = {
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
.device_dma_enable = false,
.device_dma_desc_enable = false,
.device_rx_fifo_size = (320 - 16 - 16 - 16 - 16),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 16, // 64 byte
[2] = 16, // 64 byte
[3] = 16, // 64 byte
[4] = 0,
[5] = 0,
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.device_gccfg = (1 << 16),
.b_session_valid_override = true,
.total_fifo_size = 320 // 1280 byte
};
const struct dwc2_user_params param_pb14_pb15 = { 0 }; // do not support
#if defined(HAL_HCD_MODULE_ENABLED)
#error "HAL_HCD_MODULE_ENABLED is not supported for STM32L4xx, please use HAL_PCD_MODULE_ENABLED"
#endif
#elif __has_include("stm32u5xx_hal.h")
#include "stm32u5xx_hal.h"
const struct dwc2_user_params param_pa11_pa12 = {
.phy_type = DWC2_PHY_TYPE_PARAM_FS,
.device_dma_enable = false,
.device_dma_desc_enable = false,
.device_rx_fifo_size = (320 - 16 - 16 - 16 - 16),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 16, // 64 byte
[2] = 16, // 64 byte
[3] = 16, // 64 byte
[4] = 0,
[5] = 0,
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.device_gccfg = (1 << 16),
.b_session_valid_override = true,
.total_fifo_size = 320 // 1280 byte
};
#if defined(STM32U595xx) || defined(STM32U5A5xx) || defined(STM32U599xx) || defined(STM32U5A9xx) || \
defined(STM32U5F7xx) || defined(STM32U5G7xx) || defined(STM32U5F9xx) || defined(STM32U5G9xx)
const struct dwc2_user_params param_pb14_pb15 = {
.phy_type = DWC2_PHY_TYPE_PARAM_UTMI,
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
.device_dma_enable = true,
#else
.device_dma_enable = false,
#endif
.device_dma_desc_enable = false,
.device_rx_fifo_size = (952 - 16 - 256 - 128 - 128 - 128 - 128),
.device_tx_fifo_size = {
[0] = 16, // 64 byte
[1] = 256, // 1024 byte
[2] = 128, // 512 byte
[3] = 128, // 512 byte
[4] = 128, // 512 byte
[5] = 128, // 512 byte
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0,
[12] = 0,
[13] = 0,
[14] = 0,
[15] = 0 },
.host_dma_desc_enable = false,
.host_rx_fifo_size = 568,
.host_nperio_tx_fifo_size = 128, // 512 byte
.host_perio_tx_fifo_size = 256, // 1024 byte
.device_gccfg = ((1 << 23) | (1 << 24)), // hs: USB_OTG_GCCFG_VBVALEXTOEN | USB_OTG_GCCFG_VBVALOVAL
.host_gccfg = (1 << 25) // hs: USB_OTG_GCCFG_PULLDOWNEN
};
#else
const struct dwc2_user_params param_pb14_pb15 = { 0 }; // do not support
#endif
#endif
#endif // CONFIG_USB_DWC2_CUSTOM_PARAM
#if !defined(HAL_HCD_MODULE_ENABLED) && !defined(HAL_PCD_MODULE_ENABLED)
#error please define HAL_HCD_MODULE_ENABLED or HAL_PCD_MODULE_ENABLED in stm32xxx_hal_conf.h
#endif
typedef void (*usb_dwc2_irq)(uint8_t busid);
struct dwc2_instance {
USB_OTG_GlobalTypeDef *Instance;
};
static usb_dwc2_irq g_usb_dwc2_irq[2];
static uint8_t g_usb_dwc2_busid[2] = { 0, 0 };
static struct dwc2_instance g_dwc2_instance;
#if defined(STM32F722xx) || defined(STM32F723xx) || defined(STM32F730xx) || defined(STM32F732xx) || defined(STM32F733xx)
/**
* @brief Enables control of a High Speed USB PHY
* Init the low level hardware : GPIO, CLOCK, NVIC...
* @param USBx Selected device
* @retval HAL status
*/
static int usb_hsphy_init(uint32_t hse_value)
{
__IO uint32_t count = 0U;
/* Enable LDO */
USB_HS_PHYC->USB_HS_PHYC_LDO |= USB_HS_PHYC_LDO_ENABLE;
/* wait for LDO Ready */
while ((USB_HS_PHYC->USB_HS_PHYC_LDO & USB_HS_PHYC_LDO_STATUS) == 0U) {
count++;
if (count > 200000U) {
return -1;
}
}
/* Controls PHY frequency operation selection */
if (hse_value == 12000000U) /* HSE = 12MHz */
{
USB_HS_PHYC->USB_HS_PHYC_PLL = (0x0U << 1);
} else if (hse_value == 12500000U) /* HSE = 12.5MHz */
{
USB_HS_PHYC->USB_HS_PHYC_PLL = (0x2U << 1);
} else if (hse_value == 16000000U) /* HSE = 16MHz */
{
USB_HS_PHYC->USB_HS_PHYC_PLL = (0x3U << 1);
} else if (hse_value == 24000000U) /* HSE = 24MHz */
{
USB_HS_PHYC->USB_HS_PHYC_PLL = (0x4U << 1);
} else if (hse_value == 25000000U) /* HSE = 25MHz */
{
USB_HS_PHYC->USB_HS_PHYC_PLL = (0x5U << 1);
} else if (hse_value == 32000000U) /* HSE = 32MHz */
{
USB_HS_PHYC->USB_HS_PHYC_PLL = (0x7U << 1);
} else {
/* ... */
}
/* Control the tuning interface of the High Speed PHY */
USB_HS_PHYC->USB_HS_PHYC_TUNE |= USB_HS_PHYC_TUNE_VALUE;
/* Enable PLL internal PHY */
USB_HS_PHYC->USB_HS_PHYC_PLL |= USB_HS_PHYC_PLL_PLLEN;
/* 2ms Delay required to get internal phy clock stable */
HAL_Delay(2U);
return 0;
}
#endif
#ifdef HAL_PCD_MODULE_ENABLED
void usb_dc_low_level_init(uint8_t busid)
{
if (g_usbdev_bus[busid].reg_base == 0x40040000UL) { // USB_OTG_HS_PERIPH_BASE
g_usb_dwc2_busid[1] = busid;
g_usb_dwc2_irq[1] = USBD_IRQHandler;
} else {
g_usb_dwc2_busid[0] = busid;
g_usb_dwc2_irq[0] = USBD_IRQHandler;
}
g_dwc2_instance.Instance = (USB_OTG_GlobalTypeDef *)g_usbdev_bus[busid].reg_base;
HAL_PCD_MspInit((PCD_HandleTypeDef *)&g_dwc2_instance);
#if defined(STM32F722xx) || defined(STM32F723xx) || defined(STM32F730xx) || defined(STM32F732xx) || defined(STM32F733xx)
usb_hsphy_init(25000000U);
#endif
}
void usb_dc_low_level_deinit(uint8_t busid)
{
if (g_usbdev_bus[busid].reg_base == 0x40040000UL) { // USB_OTG_HS_PERIPH_BASE
g_usb_dwc2_busid[1] = 0;
g_usb_dwc2_irq[1] = NULL;
} else {
g_usb_dwc2_busid[0] = 0;
g_usb_dwc2_irq[0] = NULL;
}
g_dwc2_instance.Instance = (USB_OTG_GlobalTypeDef *)g_usbdev_bus[busid].reg_base;
HAL_PCD_MspDeInit((PCD_HandleTypeDef *)&g_dwc2_instance);
}
#endif
#ifdef HAL_HCD_MODULE_ENABLED
void usb_hc_low_level_init(struct usbh_bus *bus)
{
if (bus->hcd.reg_base == 0x40040000UL) { // USB_OTG_HS_PERIPH_BASE
g_usb_dwc2_busid[1] = bus->hcd.hcd_id;
g_usb_dwc2_irq[1] = USBH_IRQHandler;
} else {
g_usb_dwc2_busid[0] = bus->hcd.hcd_id;
g_usb_dwc2_irq[0] = USBH_IRQHandler;
}
g_dwc2_instance.Instance = (USB_OTG_GlobalTypeDef *)bus->hcd.reg_base;
HAL_HCD_MspInit((HCD_HandleTypeDef *)&g_dwc2_instance);
#if defined(STM32F722xx) || defined(STM32F723xx) || defined(STM32F730xx) || defined(STM32F732xx) || defined(STM32F733xx)
usb_hsphy_init(25000000U);
#endif
}
void usb_hc_low_level_deinit(struct usbh_bus *bus)
{
if (bus->hcd.reg_base == 0x40040000UL) { // USB_OTG_HS_PERIPH_BASE
g_usb_dwc2_busid[1] = 0;
g_usb_dwc2_irq[1] = NULL;
} else {
g_usb_dwc2_busid[0] = 0;
g_usb_dwc2_irq[0] = NULL;
}
g_dwc2_instance.Instance = (USB_OTG_GlobalTypeDef *)bus->hcd.reg_base;
HAL_HCD_MspDeInit((HCD_HandleTypeDef *)&g_dwc2_instance);
}
#endif
#ifndef CONFIG_USB_DWC2_CUSTOM_PARAM
void dwc2_get_user_params(uint32_t reg_base, struct dwc2_user_params *params)
{
if (reg_base == 0x40040000UL) { // USB_OTG_HS_PERIPH_BASE
memcpy(params, &param_pb14_pb15, sizeof(struct dwc2_user_params));
} else {
memcpy(params, &param_pa11_pa12, sizeof(struct dwc2_user_params));
}
#ifdef CONFIG_USB_DWC2_CUSTOM_FIFO
struct usb_dwc2_user_fifo_config s_dwc2_fifo_config;
dwc2_get_user_fifo_config(reg_base, &s_dwc2_fifo_config);
params->device_rx_fifo_size = s_dwc2_fifo_config.device_rx_fifo_size;
for (uint8_t i = 0; i < MAX_EPS_CHANNELS; i++)
{
params->device_tx_fifo_size[i] = s_dwc2_fifo_config.device_tx_fifo_size[i];
}
#endif
}
#endif
extern uint32_t SystemCoreClock;
void usbd_dwc2_delay_ms(uint8_t ms)
{
uint32_t count = SystemCoreClock / 1000 * ms;
while (count--) {
__asm volatile("nop");
}
}
void OTG_FS_IRQHandler(void)
{
g_usb_dwc2_irq[0](g_usb_dwc2_busid[0]);
}
void OTG_HS_IRQHandler(void)
{
g_usb_dwc2_irq[1](g_usb_dwc2_busid[1]);
}
#ifdef CONFIG_USB_DCACHE_ENABLE
void usb_dcache_clean(uintptr_t addr, size_t size)
{
SCB_CleanDCache_by_Addr((void *)addr, size);
}
void usb_dcache_invalidate(uintptr_t addr, size_t size)
{
SCB_InvalidateDCache_by_Addr((void *)addr, size);
}
void usb_dcache_flush(uintptr_t addr, size_t size)
{
SCB_CleanInvalidateDCache_by_Addr((void *)addr, size);
}
#endif
File diff suppressed because it is too large Load Diff