first
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
# Note
|
||||
|
||||
## Support Chip List
|
||||
|
||||
- CH32V30x
|
@@ -0,0 +1,409 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef _USB_CH32_USBFS_REG_H
|
||||
#define _USB_CH32_USBFS_REG_H
|
||||
|
||||
#define __IO volatile /* defines 'read / write' permissions */
|
||||
|
||||
/* USBOTG_FS Registers */
|
||||
typedef struct
|
||||
{
|
||||
__IO uint8_t BASE_CTRL;
|
||||
__IO uint8_t UDEV_CTRL;
|
||||
__IO uint8_t INT_EN;
|
||||
__IO uint8_t DEV_ADDR;
|
||||
__IO uint8_t Reserve0;
|
||||
__IO uint8_t MIS_ST;
|
||||
__IO uint8_t INT_FG;
|
||||
__IO uint8_t INT_ST;
|
||||
__IO uint16_t RX_LEN;
|
||||
__IO uint16_t Reserve1;
|
||||
__IO uint8_t UEP4_1_MOD;
|
||||
__IO uint8_t UEP2_3_MOD;
|
||||
__IO uint8_t UEP5_6_MOD;
|
||||
__IO uint8_t UEP7_MOD;
|
||||
__IO uint32_t UEP0_DMA;
|
||||
__IO uint32_t UEP1_DMA;
|
||||
__IO uint32_t UEP2_DMA;
|
||||
__IO uint32_t UEP3_DMA;
|
||||
__IO uint32_t UEP4_DMA;
|
||||
__IO uint32_t UEP5_DMA;
|
||||
__IO uint32_t UEP6_DMA;
|
||||
__IO uint32_t UEP7_DMA;
|
||||
__IO uint16_t UEP0_TX_LEN;
|
||||
__IO uint8_t UEP0_TX_CTRL;
|
||||
__IO uint8_t UEP0_RX_CTRL;
|
||||
__IO uint16_t UEP1_TX_LEN;
|
||||
__IO uint8_t UEP1_TX_CTRL;
|
||||
__IO uint8_t UEP1_RX_CTRL;
|
||||
__IO uint16_t UEP2_TX_LEN;
|
||||
__IO uint8_t UEP2_TX_CTRL;
|
||||
__IO uint8_t UEP2_RX_CTRL;
|
||||
__IO uint16_t UEP3_TX_LEN;
|
||||
__IO uint8_t UEP3_TX_CTRL;
|
||||
__IO uint8_t UEP3_RX_CTRL;
|
||||
__IO uint16_t UEP4_TX_LEN;
|
||||
__IO uint8_t UEP4_TX_CTRL;
|
||||
__IO uint8_t UEP4_RX_CTRL;
|
||||
__IO uint16_t UEP5_TX_LEN;
|
||||
__IO uint8_t UEP5_TX_CTRL;
|
||||
__IO uint8_t UEP5_RX_CTRL;
|
||||
__IO uint16_t UEP6_TX_LEN;
|
||||
__IO uint8_t UEP6_TX_CTRL;
|
||||
__IO uint8_t UEP6_RX_CTRL;
|
||||
__IO uint16_t UEP7_TX_LEN;
|
||||
__IO uint8_t UEP7_TX_CTRL;
|
||||
__IO uint8_t UEP7_RX_CTRL;
|
||||
__IO uint32_t Reserve2;
|
||||
__IO uint32_t OTG_CR;
|
||||
__IO uint32_t OTG_SR;
|
||||
} USBOTG_FS_TypeDef;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
__IO uint8_t BASE_CTRL;
|
||||
__IO uint8_t HOST_CTRL;
|
||||
__IO uint8_t INT_EN;
|
||||
__IO uint8_t DEV_ADDR;
|
||||
__IO uint8_t Reserve0;
|
||||
__IO uint8_t MIS_ST;
|
||||
__IO uint8_t INT_FG;
|
||||
__IO uint8_t INT_ST;
|
||||
__IO uint16_t RX_LEN;
|
||||
__IO uint16_t Reserve1;
|
||||
__IO uint8_t Reserve2;
|
||||
__IO uint8_t HOST_EP_MOD;
|
||||
__IO uint16_t Reserve3;
|
||||
__IO uint32_t Reserve4;
|
||||
__IO uint32_t Reserve5;
|
||||
__IO uint32_t HOST_RX_DMA;
|
||||
__IO uint32_t HOST_TX_DMA;
|
||||
__IO uint32_t Reserve6;
|
||||
__IO uint32_t Reserve7;
|
||||
__IO uint32_t Reserve8;
|
||||
__IO uint32_t Reserve9;
|
||||
__IO uint32_t Reserve10;
|
||||
__IO uint16_t Reserve11;
|
||||
__IO uint16_t HOST_SETUP;
|
||||
__IO uint8_t HOST_EP_PID;
|
||||
__IO uint8_t Reserve12;
|
||||
__IO uint8_t Reserve13;
|
||||
__IO uint8_t HOST_RX_CTRL;
|
||||
__IO uint16_t HOST_TX_LEN;
|
||||
__IO uint8_t HOST_TX_CTRL;
|
||||
__IO uint8_t Reserve14;
|
||||
__IO uint32_t Reserve15;
|
||||
__IO uint32_t Reserve16;
|
||||
__IO uint32_t Reserve17;
|
||||
__IO uint32_t Reserve18;
|
||||
__IO uint32_t Reserve19;
|
||||
__IO uint32_t OTG_CR;
|
||||
__IO uint32_t OTG_SR;
|
||||
} USBOTGH_FS_TypeDef;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
__IO uint8_t BASE_CTRL; /*!< 0x40008000 */
|
||||
__IO uint8_t HOST_CTRL; /*!< 0x40008001 */
|
||||
__IO uint8_t INT_EN; /*!< 0x40008002 */
|
||||
__IO uint8_t DEV_ADDR; /*!< 0x40008003 */
|
||||
__IO uint8_t USB_STATUS0; /*!< 0x40008004 */
|
||||
__IO uint8_t MIS_ST; /*!< 0x40008005 */
|
||||
__IO uint8_t INT_FG; /*!< 0x40008006 */
|
||||
__IO uint8_t INT_ST; /*!< 0x40008007 */
|
||||
__IO uint8_t RX_LEN; /*!< 0x40008008 */
|
||||
__IO uint8_t Reserve1; /*!< 0x40008009 */
|
||||
__IO uint8_t Reserve2; /*!< 0x4000800a */
|
||||
__IO uint8_t Reserve3; /*!< 0x4000800b */
|
||||
__IO uint8_t UEP4_1_MOD; /*!< 0x4000800c */
|
||||
__IO uint8_t HOST_EP_MOD; /*!< 0x4000800d */
|
||||
__IO uint8_t UEP567_MOD; /*!< 0x4000800e */
|
||||
__IO uint8_t Reserve4; /*!< 0x4000800f */
|
||||
__IO uint16_t UEP0_DMA; /*!< 0x40008010 */
|
||||
__IO uint16_t Reserve5; /*!< 0x40008012 */
|
||||
__IO uint16_t UEP1_DMA; /*!< 0x40008014 */
|
||||
__IO uint16_t Reserve6; /*!< 0x40008016 */
|
||||
__IO uint16_t HOST_RX_DMA; /*!< 0x40008018 */
|
||||
__IO uint16_t Reserve7; /*!< 0x4000801a */
|
||||
__IO uint16_t HOST_TX_DMA; /*!< 0x4000801c */
|
||||
__IO uint16_t Reserve8; /*!< 0x4000801e */
|
||||
__IO uint8_t UEP0_T_LEN; /*!< 0x40008020 */
|
||||
__IO uint8_t Reserve9; /*!< 0x40008021 */
|
||||
__IO uint8_t UEP0_CTRL; /*!< 0x40008022 */
|
||||
__IO uint8_t Reserve10; /*!< 0x40008023 */
|
||||
__IO uint8_t UEP1_T_LEN; /*!< 0x40008024 */
|
||||
__IO uint8_t Reserve11; /*!< 0x40008025 */
|
||||
__IO uint8_t HOST_SETUP; /*!< 0x40008026 */
|
||||
__IO uint8_t Reserve12; /*!< 0x40008027 */
|
||||
__IO uint8_t HOST_EP_PID; /*!< 0x40008028 */
|
||||
__IO uint8_t Reserve13; /*!< 0x40008029 */
|
||||
__IO uint8_t HOST_RX_CTRL; /*!< 0x4000802a */
|
||||
__IO uint8_t Reserve14; /*!< 0x4000802b */
|
||||
__IO uint8_t HOST_TX_LEN; /*!< 0x4000802c */
|
||||
__IO uint8_t Reserve15; /*!< 0x4000802d */
|
||||
__IO uint8_t HOST_TX_CTRL; /*!< 0x4000802e */
|
||||
__IO uint8_t Reserve16; /*!< 0x4000802f */
|
||||
__IO uint8_t UEP4_T_LEN; /*!< 0x40008030 */
|
||||
__IO uint8_t Reserve17; /*!< 0x40008031 */
|
||||
__IO uint8_t UEP4_CTRL; /*!< 0x40008032 */
|
||||
__IO uint8_t Reserve18[33]; /*!< 0x40008033 */
|
||||
__IO uint16_t UEP5_DMA; /*!< 0x40008054 */
|
||||
__IO uint16_t Reserve19; /*!< 0x40008056 */
|
||||
__IO uint16_t UEP6_DMA; /*!< 0x40008058 */
|
||||
__IO uint16_t Reserve20; /*!< 0x4000805a */
|
||||
__IO uint16_t UEP7_DMA; /*!< 0x4000805c */
|
||||
__IO uint8_t Reserve21[6]; /*!< 0x4000805e */
|
||||
__IO uint8_t UEP5_T_LEN; /*!< 0x40008064 */
|
||||
__IO uint8_t Reserve22; /*!< 0x40008065 */
|
||||
__IO uint8_t UEP5_CTRL; /*!< 0x40008066 */
|
||||
__IO uint8_t Reserve23; /*!< 0x40008067 */
|
||||
__IO uint8_t UEP6_T_LEN; /*!< 0x40008068 */
|
||||
__IO uint8_t Reserve24; /*!< 0x40008069 */
|
||||
__IO uint8_t UEP6_CTRL; /*!< 0x4000806a */
|
||||
__IO uint8_t Reserve25; /*!< 0x4000806b */
|
||||
__IO uint8_t UEP7_T_LEN; /*!< 0x4000806c */
|
||||
__IO uint8_t Reserve26; /*!< 0x4000806d */
|
||||
__IO uint8_t UEP7_CTRL; /*!< 0x4000806e */
|
||||
} USB_FS_TypeDef;
|
||||
|
||||
#define USBFS_BASE ((uint32_t)0x50000000)
|
||||
|
||||
#define USBFS_DEVICE ((USBOTG_FS_TypeDef *)USBFS_BASE)
|
||||
#define USBFS_HOST ((USBOTGH_FS_TypeDef *)USBFS_BASE)
|
||||
|
||||
/******************* GLOBAL ******************/
|
||||
|
||||
/* BASE USB_CTRL */
|
||||
#define USBFS_BASE_CTRL_OFFSET 0x00 // USB base control
|
||||
#define USBFS_UC_HOST_MODE 0x80 // enable USB host mode: 0=device mode, 1=host mode
|
||||
#define USBFS_UC_LOW_SPEED 0x40 // enable USB low speed: 0=12Mbps, 1=1.5Mbps
|
||||
#define USBFS_UC_DEV_PU_EN 0x20 // USB device enable and internal pullup resistance enable
|
||||
#define USBFS_UC_SYS_CTRL1 0x20 // USB system control high bit
|
||||
#define USBFS_UC_SYS_CTRL0 0x10 // USB system control low bit
|
||||
#define USBFS_UC_SYS_CTRL_MASK 0x30 // bit mask of USB system control
|
||||
// UC_HOST_MODE & UC_SYS_CTRL1 & UC_SYS_CTRL0: USB system control
|
||||
// 0 00: disable USB device and disable internal pullup resistance
|
||||
// 0 01: enable USB device and disable internal pullup resistance, need external pullup resistance
|
||||
// 0 1x: enable USB device and enable internal pullup resistance
|
||||
// 1 00: enable USB host and normal status
|
||||
// 1 01: enable USB host and force UDP/UDM output SE0 state
|
||||
// 1 10: enable USB host and force UDP/UDM output J state
|
||||
// 1 11: enable USB host and force UDP/UDM output resume or K state
|
||||
#define USBFS_UC_INT_BUSY 0x08 // enable automatic responding busy for device mode or automatic pause for host mode during interrupt flag UIF_TRANSFER valid
|
||||
#define USBFS_UC_RESET_SIE 0x04 // force reset USB SIE, need software clear
|
||||
#define USBFS_UC_CLR_ALL 0x02 // force clear FIFO and count of USB
|
||||
#define USBFS_UC_DMA_EN 0x01 // DMA enable and DMA interrupt enable for USB
|
||||
|
||||
/* USB INT EN */
|
||||
#define USBFS_INT_EN_OFFSET 0x02
|
||||
#define USBFS_UIE_DEV_SOF 0x80 // enable interrupt for SOF received for USB device mode
|
||||
#define USBFS_UIE_DEV_NAK 0x40 // enable interrupt for NAK responded for USB device mode
|
||||
#define USBFS_UIE_FIFO_OV 0x10 // enable interrupt for FIFO overflow
|
||||
#define USBFS_UIE_HST_SOF 0x08 // enable interrupt for host SOF timer action for USB host mode
|
||||
#define USBFS_UIE_SUSPEND 0x04 // enable interrupt for USB suspend or resume event
|
||||
#define USBFS_UIE_TRANSFER 0x02 // enable interrupt for USB transfer completion
|
||||
#define USBFS_UIE_DETECT 0x01 // enable interrupt for USB device detected event for USB host mode
|
||||
#define USBFS_UIE_BUS_RST 0x01 // enable interrupt for USB bus reset event for USB device mode
|
||||
/* USB_DEV_ADDR */
|
||||
#define USBFS_DEV_ADDR_OFFSET 0x03
|
||||
#define USBFS_UDA_GP_BIT 0x80 // general purpose bit
|
||||
#define USBFS_USB_ADDR_MASK 0x7F // bit mask for USB device address
|
||||
|
||||
/* USB_STATUS */
|
||||
#define USBFS_USB_STATUS_OFFSET 0x04
|
||||
|
||||
/* USB_MIS_ST */
|
||||
#define USBFS_MIS_ST_OFFSET 0x05
|
||||
#define USBFS_UMS_SOF_PRES 0x80 // RO, indicate host SOF timer presage status
|
||||
#define USBFS_UMS_SOF_ACT 0x40 // RO, indicate host SOF timer action status for USB host
|
||||
#define USBFS_UMS_SIE_FREE 0x20 // RO, indicate USB SIE free status
|
||||
#define USBFS_UMS_R_FIFO_RDY 0x10 // RO, indicate USB receiving FIFO ready status (not empty)
|
||||
#define USBFS_UMS_BUS_RESET 0x08 // RO, indicate USB bus reset status
|
||||
#define USBFS_UMS_SUSPEND 0x04 // RO, indicate USB suspend status
|
||||
#define USBFS_UMS_DM_LEVEL 0x02 // RO, indicate UDM level saved at device attached to USB host
|
||||
#define USBFS_UMS_DEV_ATTACH 0x01 // RO, indicate device attached status on USB host
|
||||
|
||||
/* USB_INT_FG */
|
||||
#define USBFS_INT_FG_OFFSET 0x06
|
||||
#define USBFS_U_IS_NAK 0x80 // RO, indicate current USB transfer is NAK received
|
||||
#define USBFS_U_TOG_OK 0x40 // RO, indicate current USB transfer toggle is OK
|
||||
#define USBFS_U_SIE_FREE 0x20 // RO, indicate USB SIE free status
|
||||
#define USBFS_UIF_FIFO_OV 0x10 // FIFO overflow interrupt flag for USB, direct bit address clear or write 1 to clear
|
||||
#define USBFS_UIF_HST_SOF 0x08 // host SOF timer interrupt flag for USB host, direct bit address clear or write 1 to clear
|
||||
#define USBFS_UIF_SUSPEND 0x04 // USB suspend or resume event interrupt flag, direct bit address clear or write 1 to clear
|
||||
#define USBFS_UIF_TRANSFER 0x02 // USB transfer completion interrupt flag, direct bit address clear or write 1 to clear
|
||||
#define USBFS_UIF_DETECT 0x01 // device detected event interrupt flag for USB host mode, direct bit address clear or write 1 to clear
|
||||
#define USBFS_UIF_BUS_RST 0x01 // bus reset event interrupt flag for USB device mode, direct bit address clear or write 1 to clear
|
||||
|
||||
/* USB_INT_ST */
|
||||
#define USBFS_INT_ST_OFFSET 0x07
|
||||
#define USBFS_UIS_IS_SETUP 0x80 // RO, indicate current USB transfer is setup received for USB device mode
|
||||
#define USBFS_UIS_IS_NAK 0x80 // RO, indicate current USB transfer is NAK received for USB device mode
|
||||
#define USBFS_UIS_TOG_OK 0x40 // RO, indicate current USB transfer toggle is OK
|
||||
#define USBFS_UIS_TOKEN1 0x20 // RO, current token PID code bit 1 received for USB device mode
|
||||
#define USBFS_UIS_TOKEN0 0x10 // RO, current token PID code bit 0 received for USB device mode
|
||||
#define USBFS_UIS_TOKEN_MASK 0x30 // RO, bit mask of current token PID code received for USB device mode
|
||||
#define USBFS_UIS_TOKEN_OUT 0x00
|
||||
#define USBFS_UIS_TOKEN_SOF 0x10
|
||||
#define USBFS_UIS_TOKEN_IN 0x20
|
||||
#define USBFS_UIS_TOKEN_SETUP 0x30
|
||||
// UIS_TOKEN1 & UIS_TOKEN0: current token PID code received for USB device mode
|
||||
// 00: OUT token PID received
|
||||
// 01: SOF token PID received
|
||||
// 10: IN token PID received
|
||||
// 11: SETUP token PID received
|
||||
#define USBFS_UIS_ENDP_MASK 0x0F // RO, bit mask of current transfer endpoint number for USB device mode
|
||||
/* USB_RX_LEN */
|
||||
#define USBFS_RX_LEN_OFFSET 0x08
|
||||
|
||||
/******************* DEVICE ******************/
|
||||
|
||||
/* UDEV_CTRL */
|
||||
#define USBFS_UDEV_CTRL_OFFSET 0x01
|
||||
#define USBFS_UD_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable
|
||||
#define USBFS_UD_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level
|
||||
#define USBFS_UD_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level
|
||||
#define USBFS_UD_LOW_SPEED 0x04 // enable USB physical port low speed: 0=full speed, 1=low speed
|
||||
#define USBFS_UD_GP_BIT 0x02 // general purpose bit
|
||||
#define USBFS_UD_PORT_EN 0x01 // enable USB physical port I/O: 0=disable, 1=enable
|
||||
|
||||
/* UEP4_1_MOD */
|
||||
#define USBFS_UEP4_1_MOD_OFFSET 0x0C
|
||||
#define USBFS_UEP1_RX_EN 0x80 // enable USB endpoint 1 receiving (OUT)
|
||||
#define USBFS_UEP1_TX_EN 0x40 // enable USB endpoint 1 transmittal (IN)
|
||||
#define USBFS_UEP1_BUF_MOD 0x10 // buffer mode of USB endpoint 1
|
||||
// UEPn_RX_EN & UEPn_TX_EN & UEPn_BUF_MOD: USB endpoint 1/2/3 buffer mode, buffer start address is UEPn_DMA
|
||||
// 0 0 x: disable endpoint and disable buffer
|
||||
// 1 0 0: 64 bytes buffer for receiving (OUT endpoint)
|
||||
// 1 0 1: dual 64 bytes buffer by toggle bit bUEP_R_TOG selection for receiving (OUT endpoint), total=128bytes
|
||||
// 0 1 0: 64 bytes buffer for transmittal (IN endpoint)
|
||||
// 0 1 1: dual 64 bytes buffer by toggle bit bUEP_T_TOG selection for transmittal (IN endpoint), total=128bytes
|
||||
// 1 1 0: 64 bytes buffer for receiving (OUT endpoint) + 64 bytes buffer for transmittal (IN endpoint), total=128bytes
|
||||
// 1 1 1: dual 64 bytes buffer by bUEP_R_TOG selection for receiving (OUT endpoint) + dual 64 bytes buffer by bUEP_T_TOG selection for transmittal (IN endpoint), total=256bytes
|
||||
#define USBFS_UEP4_RX_EN 0x08 // enable USB endpoint 4 receiving (OUT)
|
||||
#define USBFS_UEP4_TX_EN 0x04 // enable USB endpoint 4 transmittal (IN)
|
||||
// UEP4_RX_EN & UEP4_TX_EN: USB endpoint 4 buffer mode, buffer start address is UEP0_DMA
|
||||
// 0 0: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint)
|
||||
// 1 0: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) + 64 bytes buffer for endpoint 4 receiving (OUT endpoint), total=128bytes
|
||||
// 0 1: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) + 64 bytes buffer for endpoint 4 transmittal (IN endpoint), total=128bytes
|
||||
// 1 1: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint)
|
||||
// + 64 bytes buffer for endpoint 4 receiving (OUT endpoint) + 64 bytes buffer for endpoint 4 transmittal (IN endpoint), total=192bytes
|
||||
|
||||
/* UEP2_3_MOD */
|
||||
#define USBFS_UEP2_3_MOD_OFFSET 0x0D
|
||||
#define USBFS_UEP3_RX_EN 0x80 // enable USB endpoint 3 receiving (OUT)
|
||||
#define USBFS_UEP3_TX_EN 0x40 // enable USB endpoint 3 transmittal (IN)
|
||||
#define USBFS_UEP3_BUF_MOD 0x10 // buffer mode of USB endpoint 3
|
||||
#define USBFS_UEP2_RX_EN 0x08 // enable USB endpoint 2 receiving (OUT)
|
||||
#define USBFS_UEP2_TX_EN 0x04 // enable USB endpoint 2 transmittal (IN)
|
||||
#define USBFS_UEP2_BUF_MOD 0x01 // buffer mode of USB endpoint 2
|
||||
|
||||
/* UEP5_6_MOD */
|
||||
#define USBFS_UEP5_6_MOD_OFFSET 0x0E
|
||||
#define USBFS_UEP6_RX_EN 0x80 // enable USB endpoint 6 receiving (OUT)
|
||||
#define USBFS_UEP6_TX_EN 0x40 // enable USB endpoint 6 transmittal (IN)
|
||||
#define USBFS_UEP6_BUF_MOD 0x10 // buffer mode of USB endpoint 6
|
||||
#define USBFS_UEP5_RX_EN 0x08 // enable USB endpoint 5 receiving (OUT)
|
||||
#define USBFS_UEP5_TX_EN 0x04 // enable USB endpoint 5 transmittal (IN)
|
||||
#define USBFS_UEP5_BUF_MOD 0x01 // buffer mode of USB endpoint 5
|
||||
|
||||
/* UEP7_MOD */
|
||||
#define USBFS_UEP7_MOD_OFFSET 0x0F
|
||||
#define USBFS_UEP7_RX_EN 0x08 // enable USB endpoint 7 receiving (OUT)
|
||||
#define USBFS_UEP7_TX_EN 0x04 // enable USB endpoint 7 transmittal (IN)
|
||||
#define USBFS_UEP7_BUF_MOD 0x01 // buffer mode of USB endpoint 7
|
||||
|
||||
/* USB_DMA */
|
||||
#define USBFS_UEPx_DMA_OFFSET(n) (0x10 + 4 * (n)) // endpoint x DMA buffer address
|
||||
#define USBFS_UEP0_DMA_OFFSET 0x10 // endpoint 0 DMA buffer address
|
||||
#define USBFS_UEP1_DMA_OFFSET 0x14 // endpoint 1 DMA buffer address
|
||||
#define USBFS_UEP2_DMA_OFFSET 0x18 // endpoint 2 DMA buffer address
|
||||
#define USBFS_UEP3_DMA_OFFSET 0x1c // endpoint 3 DMA buffer address
|
||||
#define USBFS_UEP4_DMA_OFFSET 0x20 // endpoint 4 DMA buffer address
|
||||
#define USBFS_UEP5_DMA_OFFSET 0x24 // endpoint 5 DMA buffer address
|
||||
#define USBFS_UEP6_DMA_OFFSET 0x28 // endpoint 6 DMA buffer address
|
||||
#define USBFS_UEP7_DMA_OFFSET 0x2c // endpoint 7 DMA buffer address
|
||||
/* USB_EP_CTRL */
|
||||
#define USBFS_UEPx_T_LEN_OFFSET(n) (0x30 + 4 * (n)) // endpoint x DMA buffer address
|
||||
#define USBFS_UEPx_TX_CTRL_OFFSET(n) (0x30 + 4 * (n) + 2) // endpoint x DMA buffer address
|
||||
#define USBFS_UEPx_RX_CTRL_OFFSET(n) (0x30 + 4 * (n) + 3) // endpoint x DMA buffer address
|
||||
|
||||
#define USBFS_UEP_AUTO_TOG 0x08 // enable automatic toggle after successful transfer completion on endpoint 1/2/3: 0=manual toggle, 1=automatic toggle
|
||||
#define USBFS_UEP_R_TOG 0x04 // expected data toggle flag of USB endpoint X receiving (OUT): 0=DATA0, 1=DATA1
|
||||
#define USBFS_UEP_T_TOG 0x04 // prepared data toggle flag of USB endpoint X transmittal (IN): 0=DATA0, 1=DATA1
|
||||
|
||||
#define USBFS_UEP_R_RES1 0x02 // handshake response type high bit for USB endpoint X receiving (OUT)
|
||||
#define USBFS_UEP_R_RES0 0x01 // handshake response type low bit for USB endpoint X receiving (OUT)
|
||||
#define USBFS_UEP_R_RES_MASK 0x03 // bit mask of handshake response type for USB endpoint X receiving (OUT)
|
||||
#define USBFS_UEP_R_RES_ACK 0x00
|
||||
#define USBFS_UEP_R_RES_TOUT 0x01
|
||||
#define USBFS_UEP_R_RES_NAK 0x02
|
||||
#define USBFS_UEP_R_RES_STALL 0x03
|
||||
// RB_UEP_R_RES1 & RB_UEP_R_RES0: handshake response type for USB endpoint X receiving (OUT)
|
||||
// 00: ACK (ready)
|
||||
// 01: no response, time out to host, for non-zero endpoint isochronous transactions
|
||||
// 10: NAK (busy)
|
||||
// 11: STALL (error)
|
||||
#define USBFS_UEP_T_RES1 0x02 // handshake response type high bit for USB endpoint X transmittal (IN)
|
||||
#define USBFS_UEP_T_RES0 0x01 // handshake response type low bit for USB endpoint X transmittal (IN)
|
||||
#define USBFS_UEP_T_RES_MASK 0x03 // bit mask of handshake response type for USB endpoint X transmittal (IN)
|
||||
#define USBFS_UEP_T_RES_ACK 0x00
|
||||
#define USBFS_UEP_T_RES_TOUT 0x01
|
||||
#define USBFS_UEP_T_RES_NAK 0x02
|
||||
#define USBFS_UEP_T_RES_STALL 0x03
|
||||
// bUEP_T_RES1 & bUEP_T_RES0: handshake response type for USB endpoint X transmittal (IN)
|
||||
// 00: DATA0 or DATA1 then expecting ACK (ready)
|
||||
// 01: DATA0 or DATA1 then expecting no response, time out from host, for non-zero endpoint isochronous transactions
|
||||
// 10: NAK (busy)
|
||||
// 11: TALL (error)
|
||||
|
||||
/******************* HOST ******************/
|
||||
|
||||
#define USBFS_UHOST_CTRL_OFFSET 0x01 // USB host physical prot control
|
||||
#define USBFS_UH_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable
|
||||
#define USBFS_UH_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level
|
||||
#define USBFS_UH_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level
|
||||
#define USBFS_UH_LOW_SPEED 0x04 // enable USB port low speed: 0=full speed, 1=low speed
|
||||
#define USBFS_UH_BUS_RESET 0x02 // control USB bus reset: 0=normal, 1=force bus reset
|
||||
#define USBFS_UH_PORT_EN 0x01 // enable USB port: 0=disable, 1=enable port, automatic disabled if USB device detached
|
||||
|
||||
#define USBFS_UH_EP_MOD_OFFSET USBFS_UEP2_3_MOD_OFFSET
|
||||
#define USBFS_UH_EP_TX_EN 0x40 // enable USB host OUT endpoint transmittal
|
||||
#define USBFS_UH_EP_TBUF_MOD 0x10 // buffer mode of USB host OUT endpoint
|
||||
// bUH_EP_TX_EN & bUH_EP_TBUF_MOD: USB host OUT endpoint buffer mode, buffer start address is UH_TX_DMA
|
||||
// 0 x: disable endpoint and disable buffer
|
||||
// 1 0: 64 bytes buffer for transmittal (OUT endpoint)
|
||||
// 1 1: dual 64 bytes buffer by toggle bit bUH_T_TOG selection for transmittal (OUT endpoint), total=128bytes
|
||||
#define USBFS_UH_EP_RX_EN 0x08 // enable USB host IN endpoint receiving
|
||||
#define USBFS_UH_EP_RBUF_MOD 0x01 // buffer mode of USB host IN endpoint
|
||||
// bUH_EP_RX_EN & bUH_EP_RBUF_MOD: USB host IN endpoint buffer mode, buffer start address is UH_RX_DMA
|
||||
// 0 x: disable endpoint and disable buffer
|
||||
// 1 0: 64 bytes buffer for receiving (IN endpoint)
|
||||
// 1 1: dual 64 bytes buffer by toggle bit bUH_R_TOG selection for receiving (IN endpoint), total=128bytes
|
||||
|
||||
#define USBFS_UH_RX_DMA_OFFSET USBFS_UEPx_DMA_OFFSET(2) // host rx endpoint buffer high address
|
||||
#define USBFS_UH_TX_DMA_OFFSET USBFS_UEPx_DMA_OFFSET(3) // host tx endpoint buffer high address
|
||||
|
||||
#define USBFS_UH_SETUP_OFFSET USBFS_UEPx_TX_CTRL_OFFSET(1)
|
||||
#define USBFS_UH_PRE_PID_EN 0x0400 // USB host PRE PID enable for low speed device via hub
|
||||
#define USBFS_UH_SOF_EN 0x04 // USB host automatic SOF enable
|
||||
|
||||
#define USBFS_UH_EP_PID_OFFSET USBFS_UEPx_T_LEN_OFFSET(2)
|
||||
#define USBFS_UH_TOKEN_MASK 0xF0 // bit mask of token PID for USB host transfer
|
||||
#define USBFS_UH_ENDP_MASK 0x0F // bit mask of endpoint number for USB host transfer
|
||||
|
||||
#define USBFS_UH_RX_CTRL_OFFSET USBFS_UEPx_RX_CTRL_OFFSET(2) // host receiver endpoint control
|
||||
#define USBFS_UH_R_AUTO_TOG 0x08 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle
|
||||
#define USBFS_UH_R_TOG 0x04 // expected data toggle flag of host receiving (IN): 0=DATA0, 1=DATA1
|
||||
#define USBFS_UH_R_RES 0x01 // prepared handshake response type for host receiving (IN): 0=ACK (ready), 1=no response, time out to device, for isochronous transactions
|
||||
|
||||
#define USBFS_UH_TX_LEN_OFFSET USBFS_UEPx_T_LEN_OFFSET(3)
|
||||
|
||||
#define USBFS_UH_TX_CTRL_OFFSET USBFS_UEPx_TX_CTRL_OFFSET(3) // host transmittal endpoint control
|
||||
#define USBFS_UH_T_AUTO_TOG 0x08 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle
|
||||
#define USBFS_UH_T_TOG 0x04 // prepared data toggle flag of host transmittal (SETUP/OUT): 0=DATA0, 1=DATA1
|
||||
#define USBFS_UH_T_RES 0x01 // expected handshake response type for host transmittal (SETUP/OUT): 0=ACK (ready), 1=no response, time out from device, for isochronous transactions
|
||||
|
||||
#endif
|
@@ -0,0 +1,564 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef _USB_CH32_USBHS_REG_H
|
||||
#define _USB_CH32_USBHS_REG_H
|
||||
|
||||
#define __IO volatile /* defines 'read / write' permissions */
|
||||
|
||||
/* USBHS Registers */
|
||||
typedef struct
|
||||
{
|
||||
__IO uint8_t CONTROL;
|
||||
__IO uint8_t HOST_CTRL;
|
||||
__IO uint8_t INT_EN;
|
||||
__IO uint8_t DEV_AD;
|
||||
__IO uint16_t FRAME_NO;
|
||||
__IO uint8_t SUSPEND;
|
||||
__IO uint8_t RESERVED0;
|
||||
__IO uint8_t SPEED_TYPE;
|
||||
__IO uint8_t MIS_ST;
|
||||
__IO uint8_t INT_FG;
|
||||
__IO uint8_t INT_ST;
|
||||
__IO uint16_t RX_LEN;
|
||||
__IO uint16_t RESERVED1;
|
||||
__IO uint32_t ENDP_CONFIG;
|
||||
__IO uint32_t ENDP_TYPE;
|
||||
__IO uint32_t BUF_MODE;
|
||||
__IO uint32_t UEP0_DMA;
|
||||
__IO uint32_t UEP1_RX_DMA;
|
||||
__IO uint32_t UEP2_RX_DMA;
|
||||
__IO uint32_t UEP3_RX_DMA;
|
||||
__IO uint32_t UEP4_RX_DMA;
|
||||
__IO uint32_t UEP5_RX_DMA;
|
||||
__IO uint32_t UEP6_RX_DMA;
|
||||
__IO uint32_t UEP7_RX_DMA;
|
||||
__IO uint32_t UEP8_RX_DMA;
|
||||
__IO uint32_t UEP9_RX_DMA;
|
||||
__IO uint32_t UEP10_RX_DMA;
|
||||
__IO uint32_t UEP11_RX_DMA;
|
||||
__IO uint32_t UEP12_RX_DMA;
|
||||
__IO uint32_t UEP13_RX_DMA;
|
||||
__IO uint32_t UEP14_RX_DMA;
|
||||
__IO uint32_t UEP15_RX_DMA;
|
||||
__IO uint32_t UEP1_TX_DMA;
|
||||
__IO uint32_t UEP2_TX_DMA;
|
||||
__IO uint32_t UEP3_TX_DMA;
|
||||
__IO uint32_t UEP4_TX_DMA;
|
||||
__IO uint32_t UEP5_TX_DMA;
|
||||
__IO uint32_t UEP6_TX_DMA;
|
||||
__IO uint32_t UEP7_TX_DMA;
|
||||
__IO uint32_t UEP8_TX_DMA;
|
||||
__IO uint32_t UEP9_TX_DMA;
|
||||
__IO uint32_t UEP10_TX_DMA;
|
||||
__IO uint32_t UEP11_TX_DMA;
|
||||
__IO uint32_t UEP12_TX_DMA;
|
||||
__IO uint32_t UEP13_TX_DMA;
|
||||
__IO uint32_t UEP14_TX_DMA;
|
||||
__IO uint32_t UEP15_TX_DMA;
|
||||
__IO uint16_t UEP0_MAX_LEN;
|
||||
__IO uint16_t RESERVED2;
|
||||
__IO uint16_t UEP1_MAX_LEN;
|
||||
__IO uint16_t RESERVED3;
|
||||
__IO uint16_t UEP2_MAX_LEN;
|
||||
__IO uint16_t RESERVED4;
|
||||
__IO uint16_t UEP3_MAX_LEN;
|
||||
__IO uint16_t RESERVED5;
|
||||
__IO uint16_t UEP4_MAX_LEN;
|
||||
__IO uint16_t RESERVED6;
|
||||
__IO uint16_t UEP5_MAX_LEN;
|
||||
__IO uint16_t RESERVED7;
|
||||
__IO uint16_t UEP6_MAX_LEN;
|
||||
__IO uint16_t RESERVED8;
|
||||
__IO uint16_t UEP7_MAX_LEN;
|
||||
__IO uint16_t RESERVED9;
|
||||
__IO uint16_t UEP8_MAX_LEN;
|
||||
__IO uint16_t RESERVED10;
|
||||
__IO uint16_t UEP9_MAX_LEN;
|
||||
__IO uint16_t RESERVED11;
|
||||
__IO uint16_t UEP10_MAX_LEN;
|
||||
__IO uint16_t RESERVED12;
|
||||
__IO uint16_t UEP11_MAX_LEN;
|
||||
__IO uint16_t RESERVED13;
|
||||
__IO uint16_t UEP12_MAX_LEN;
|
||||
__IO uint16_t RESERVED14;
|
||||
__IO uint16_t UEP13_MAX_LEN;
|
||||
__IO uint16_t RESERVED15;
|
||||
__IO uint16_t UEP14_MAX_LEN;
|
||||
__IO uint16_t RESERVED16;
|
||||
__IO uint16_t UEP15_MAX_LEN;
|
||||
__IO uint16_t RESERVED17;
|
||||
__IO uint16_t UEP0_TX_LEN;
|
||||
__IO uint8_t UEP0_TX_CTRL;
|
||||
__IO uint8_t UEP0_RX_CTRL;
|
||||
__IO uint16_t UEP1_TX_LEN;
|
||||
__IO uint8_t UEP1_TX_CTRL;
|
||||
__IO uint8_t UEP1_RX_CTRL;
|
||||
__IO uint16_t UEP2_TX_LEN;
|
||||
__IO uint8_t UEP2_TX_CTRL;
|
||||
__IO uint8_t UEP2_RX_CTRL;
|
||||
__IO uint16_t UEP3_TX_LEN;
|
||||
__IO uint8_t UEP3_TX_CTRL;
|
||||
__IO uint8_t UEP3_RX_CTRL;
|
||||
__IO uint16_t UEP4_TX_LEN;
|
||||
__IO uint8_t UEP4_TX_CTRL;
|
||||
__IO uint8_t UEP4_RX_CTRL;
|
||||
__IO uint16_t UEP5_TX_LEN;
|
||||
__IO uint8_t UEP5_TX_CTRL;
|
||||
__IO uint8_t UEP5_RX_CTRL;
|
||||
__IO uint16_t UEP6_TX_LEN;
|
||||
__IO uint8_t UEP6_TX_CTRL;
|
||||
__IO uint8_t UEP6_RX_CTRL;
|
||||
__IO uint16_t UEP7_TX_LEN;
|
||||
__IO uint8_t UEP7_TX_CTRL;
|
||||
__IO uint8_t UEP7_RX_CTRL;
|
||||
__IO uint16_t UEP8_TX_LEN;
|
||||
__IO uint8_t UEP8_TX_CTRL;
|
||||
__IO uint8_t UEP8_RX_CTRL;
|
||||
__IO uint16_t UEP9_TX_LEN;
|
||||
__IO uint8_t UEP9_TX_CTRL;
|
||||
__IO uint8_t UEP9_RX_CTRL;
|
||||
__IO uint16_t UEP10_TX_LEN;
|
||||
__IO uint8_t UEP10_TX_CTRL;
|
||||
__IO uint8_t UEP10_RX_CTRL;
|
||||
__IO uint16_t UEP11_TX_LEN;
|
||||
__IO uint8_t UEP11_TX_CTRL;
|
||||
__IO uint8_t UEP11_RX_CTRL;
|
||||
__IO uint16_t UEP12_TX_LEN;
|
||||
__IO uint8_t UEP12_TX_CTRL;
|
||||
__IO uint8_t UEP12_RX_CTRL;
|
||||
__IO uint16_t UEP13_TX_LEN;
|
||||
__IO uint8_t UEP13_TX_CTRL;
|
||||
__IO uint8_t UEP13_RX_CTRL;
|
||||
__IO uint16_t UEP14_TX_LEN;
|
||||
__IO uint8_t UEP14_TX_CTRL;
|
||||
__IO uint8_t UEP14_RX_CTRL;
|
||||
__IO uint16_t UEP15_TX_LEN;
|
||||
__IO uint8_t UEP15_TX_CTRL;
|
||||
__IO uint8_t UEP15_RX_CTRL;
|
||||
} USBHSD_TypeDef;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
__IO uint8_t CONTROL;
|
||||
__IO uint8_t HOST_CTRL;
|
||||
__IO uint8_t INT_EN;
|
||||
__IO uint8_t DEV_AD;
|
||||
__IO uint16_t FRAME_NO;
|
||||
__IO uint8_t SUSPEND;
|
||||
__IO uint8_t RESERVED0;
|
||||
__IO uint8_t SPEED_TYPE;
|
||||
__IO uint8_t MIS_ST;
|
||||
__IO uint8_t INT_FG;
|
||||
__IO uint8_t INT_ST;
|
||||
__IO uint16_t RX_LEN;
|
||||
__IO uint16_t RESERVED1;
|
||||
__IO uint32_t HOST_EP_CONFIG;
|
||||
__IO uint32_t HOST_EP_TYPE;
|
||||
__IO uint32_t RESERVED2;
|
||||
__IO uint32_t RESERVED3;
|
||||
__IO uint32_t RESERVED4;
|
||||
__IO uint32_t HOST_RX_DMA;
|
||||
__IO uint32_t RESERVED5;
|
||||
__IO uint32_t RESERVED6;
|
||||
__IO uint32_t RESERVED7;
|
||||
__IO uint32_t RESERVED8;
|
||||
__IO uint32_t RESERVED9;
|
||||
__IO uint32_t RESERVED10;
|
||||
__IO uint32_t RESERVED11;
|
||||
__IO uint32_t RESERVED12;
|
||||
__IO uint32_t RESERVED13;
|
||||
__IO uint32_t RESERVED14;
|
||||
__IO uint32_t RESERVED15;
|
||||
__IO uint32_t RESERVED16;
|
||||
__IO uint32_t RESERVED17;
|
||||
__IO uint32_t RESERVED18;
|
||||
__IO uint32_t RESERVED19;
|
||||
__IO uint32_t HOST_TX_DMA;
|
||||
__IO uint32_t RESERVED20;
|
||||
__IO uint32_t RESERVED21;
|
||||
__IO uint32_t RESERVED22;
|
||||
__IO uint32_t RESERVED23;
|
||||
__IO uint32_t RESERVED24;
|
||||
__IO uint32_t RESERVED25;
|
||||
__IO uint32_t RESERVED26;
|
||||
__IO uint32_t RESERVED27;
|
||||
__IO uint32_t RESERVED28;
|
||||
__IO uint32_t RESERVED29;
|
||||
__IO uint32_t RESERVED30;
|
||||
__IO uint32_t RESERVED31;
|
||||
__IO uint32_t RESERVED32;
|
||||
__IO uint32_t RESERVED33;
|
||||
__IO uint16_t HOST_RX_MAX_LEN;
|
||||
__IO uint16_t RESERVED34;
|
||||
__IO uint32_t RESERVED35;
|
||||
__IO uint32_t RESERVED36;
|
||||
__IO uint32_t RESERVED37;
|
||||
__IO uint32_t RESERVED38;
|
||||
__IO uint32_t RESERVED39;
|
||||
__IO uint32_t RESERVED40;
|
||||
__IO uint32_t RESERVED41;
|
||||
__IO uint32_t RESERVED42;
|
||||
__IO uint32_t RESERVED43;
|
||||
__IO uint32_t RESERVED44;
|
||||
__IO uint32_t RESERVED45;
|
||||
__IO uint32_t RESERVED46;
|
||||
__IO uint32_t RESERVED47;
|
||||
__IO uint32_t RESERVED48;
|
||||
__IO uint32_t RESERVED49;
|
||||
__IO uint8_t HOST_EP_PID;
|
||||
__IO uint8_t RESERVED50;
|
||||
__IO uint8_t RESERVED51;
|
||||
__IO uint8_t HOST_RX_CTRL;
|
||||
__IO uint16_t HOST_TX_LEN;
|
||||
__IO uint8_t HOST_TX_CTRL;
|
||||
__IO uint8_t RESERVED52;
|
||||
__IO uint16_t HOST_SPLIT_DATA;
|
||||
} USBHSH_TypeDef;
|
||||
|
||||
#define USBHS_BASE ((uint32_t)(0x40000000 + 0x23400))
|
||||
|
||||
#define USBHS_DEVICE ((USBHSD_TypeDef *)USBHS_BASE)
|
||||
#define USBHS_HOST ((USBHSH_TypeDef *)USBHS_BASE)
|
||||
|
||||
/******************* GLOBAL ******************/
|
||||
|
||||
// USB CONTROL
|
||||
#define USBHS_CONTROL_OFFSET 0x00
|
||||
#define USBHS_DMA_EN (1 << 0)
|
||||
#define USBHS_ALL_CLR (1 << 1)
|
||||
#define USBHS_FORCE_RST (1 << 2)
|
||||
#define USBHS_INT_BUSY_EN (1 << 3)
|
||||
#define USBHS_DEV_PU_EN (1 << 4)
|
||||
#define USBHS_SPEED_MASK (3 << 5)
|
||||
#define USBHS_FULL_SPEED (0 << 5)
|
||||
#define USBHS_HIGH_SPEED (1 << 5)
|
||||
#define USBHS_LOW_SPEED (2 << 5)
|
||||
#define USBHS_HOST_MODE (1 << 7)
|
||||
|
||||
// USB_INT_EN
|
||||
#define USBHS_INT_EN_OFFSET 0x02
|
||||
#define USBHS_BUS_RST_EN (1 << 0)
|
||||
#define USBHS_DETECT_EN (1 << 0)
|
||||
#define USBHS_TRANSFER_EN (1 << 1)
|
||||
#define USBHS_SUSPEND_EN (1 << 2)
|
||||
#define USBHS_SOF_ACT_EN (1 << 3)
|
||||
#define USBHS_FIFO_OV_EN (1 << 4)
|
||||
#define USBHS_SETUP_ACT_EN (1 << 5)
|
||||
#define USBHS_ISO_ACT_EN (1 << 6)
|
||||
#define USBHS_DEV_NAK_EN (1 << 7)
|
||||
|
||||
// USB DEV AD
|
||||
#define USBHS_DEV_AD_OFFSET 0x03
|
||||
// USB FRAME_NO
|
||||
#define USBHS_FRAME_NO_OFFSET 0x04
|
||||
// USB SUSPEND
|
||||
#define USBHS_SUSPEND_OFFSET 0x06
|
||||
#define USBHS_DEV_REMOTE_WAKEUP (1 << 2)
|
||||
#define USBHS_LINESTATE_MASK (2 << 4) /* Read Only */
|
||||
|
||||
// RESERVED0
|
||||
|
||||
// USB SPEED TYPE
|
||||
#define USBHS_SPEED_TYPE_OFFSET 0x08
|
||||
#define USBSPEED_MASK (0x03)
|
||||
|
||||
// USB_MIS_ST
|
||||
#define USBHS_MIS_ST_OFFSET 0x09
|
||||
#define USBHS_SPLIT_CAN (1 << 0)
|
||||
#define USBHS_ATTACH (1 << 1)
|
||||
#define USBHS_SUSPEND (1 << 2)
|
||||
#define USBHS_BUS_RESET (1 << 3)
|
||||
#define USBHS_R_FIFO_RDY (1 << 4)
|
||||
#define USBHS_SIE_FREE (1 << 5)
|
||||
#define USBHS_SOF_ACT (1 << 6)
|
||||
#define USBHS_SOF_PRES (1 << 7)
|
||||
|
||||
// INT_FLAG
|
||||
#define USBHS_INT_FLAG_OFFSET 0x0A
|
||||
#define USBHS_BUS_RST_FLAG (1 << 0)
|
||||
#define USBHS_DETECT_FLAG (1 << 0)
|
||||
#define USBHS_TRANSFER_FLAG (1 << 1)
|
||||
#define USBHS_SUSPEND_FLAG (1 << 2)
|
||||
#define USBHS_HST_SOF_FLAG (1 << 3)
|
||||
#define USBHS_FIFO_OV_FLAG (1 << 4)
|
||||
#define USBHS_SETUP_FLAG (1 << 5)
|
||||
#define USBHS_ISO_ACT_FLAG (1 << 6)
|
||||
|
||||
// INT_ST
|
||||
#define USBHS_INT_ST_OFFSET 0x0B
|
||||
#define USBHS_DEV_UIS_IS_NAK (1 << 7)
|
||||
#define USBHS_DEV_UIS_TOG_OK (1 << 6)
|
||||
#define MASK_UIS_TOKEN (3 << 4)
|
||||
#define MASK_UIS_ENDP (0x0F)
|
||||
#define MASK_UIS_H_RES (0x0F)
|
||||
|
||||
#define USBHS_TOGGLE_OK (0x40)
|
||||
#define USBHS_HOST_RES (0x0f)
|
||||
|
||||
//USB_RX_LEN
|
||||
#define USBHS_RX_LEN_OFFSET 0x0C
|
||||
/******************* DEVICE ******************/
|
||||
|
||||
//UEP_CONFIG
|
||||
#define USBHS_UEP_CONFIG_OFFSET 0x10
|
||||
#define USBHS_EP0_T_EN (1 << 0)
|
||||
#define USBHS_EP0_R_EN (1 << 16)
|
||||
|
||||
#define USBHS_EP1_T_EN (1 << 1)
|
||||
#define USBHS_EP1_R_EN (1 << 17)
|
||||
|
||||
#define USBHS_EP2_T_EN (1 << 2)
|
||||
#define USBHS_EP2_R_EN (1 << 18)
|
||||
|
||||
#define USBHS_EP3_T_EN (1 << 3)
|
||||
#define USBHS_EP3_R_EN (1 << 19)
|
||||
|
||||
#define USBHS_EP4_T_EN (1 << 4)
|
||||
#define USBHS_EP4_R_EN (1 << 20)
|
||||
|
||||
#define USBHS_EP5_T_EN (1 << 5)
|
||||
#define USBHS_EP5_R_EN (1 << 21)
|
||||
|
||||
#define USBHS_EP6_T_EN (1 << 6)
|
||||
#define USBHS_EP6_R_EN (1 << 22)
|
||||
|
||||
#define USBHS_EP7_T_EN (1 << 7)
|
||||
#define USBHS_EP7_R_EN (1 << 23)
|
||||
|
||||
#define USBHS_EP8_T_EN (1 << 8)
|
||||
#define USBHS_EP8_R_EN (1 << 24)
|
||||
|
||||
#define USBHS_EP9_T_EN (1 << 9)
|
||||
#define USBHS_EP9_R_EN (1 << 25)
|
||||
|
||||
#define USBHS_EP10_T_EN (1 << 10)
|
||||
#define USBHS_EP10_R_EN (1 << 26)
|
||||
|
||||
#define USBHS_EP11_T_EN (1 << 11)
|
||||
#define USBHS_EP11_R_EN (1 << 27)
|
||||
|
||||
#define USBHS_EP12_T_EN (1 << 12)
|
||||
#define USBHS_EP12_R_EN (1 << 28)
|
||||
|
||||
#define USBHS_EP13_T_EN (1 << 13)
|
||||
#define USBHS_EP13_R_EN (1 << 29)
|
||||
|
||||
#define USBHS_EP14_T_EN (1 << 14)
|
||||
#define USBHS_EP14_R_EN (1 << 30)
|
||||
|
||||
#define USBHS_EP15_T_EN (1 << 15)
|
||||
#define USBHS_EP15_R_EN (1 << 31)
|
||||
|
||||
//UEP_TYPE
|
||||
#define USBHS_UEP_TYPE_OFFSET 0x14
|
||||
#define USBHS_EP0_T_TYP (1 << 0)
|
||||
#define USBHS_EP0_R_TYP (1 << 16)
|
||||
|
||||
#define USBHS_EP1_T_TYP (1 << 1)
|
||||
#define USBHS_EP1_R_TYP (1 << 17)
|
||||
|
||||
#define USBHS_EP2_T_TYP (1 << 2)
|
||||
#define USBHS_EP2_R_TYP (1 << 18)
|
||||
|
||||
#define USBHS_EP3_T_TYP (1 << 3)
|
||||
#define USBHS_EP3_R_TYP (1 << 19)
|
||||
|
||||
#define USBHS_EP4_T_TYP (1 << 4)
|
||||
#define USBHS_EP4_R_TYP (1 << 20)
|
||||
|
||||
#define USBHS_EP5_T_TYP (1 << 5)
|
||||
#define USBHS_EP5_R_TYP (1 << 21)
|
||||
|
||||
#define USBHS_EP6_T_TYP (1 << 6)
|
||||
#define USBHS_EP6_R_TYP (1 << 22)
|
||||
|
||||
#define USBHS_EP7_T_TYP (1 << 7)
|
||||
#define USBHS_EP7_R_TYP (1 << 23)
|
||||
|
||||
#define USBHS_EP8_T_TYP (1 << 8)
|
||||
#define USBHS_EP8_R_TYP (1 << 24)
|
||||
|
||||
#define USBHS_EP9_T_TYP (1 << 8)
|
||||
#define USBHS_EP9_R_TYP (1 << 25)
|
||||
|
||||
#define USBHS_EP10_T_TYP (1 << 10)
|
||||
#define USBHS_EP10_R_TYP (1 << 26)
|
||||
|
||||
#define USBHS_EP11_T_TYP (1 << 11)
|
||||
#define USBHS_EP11_R_TYP (1 << 27)
|
||||
|
||||
#define USBHS_EP12_T_TYP (1 << 12)
|
||||
#define USBHS_EP12_R_TYP (1 << 28)
|
||||
|
||||
#define USBHS_EP13_T_TYP (1 << 13)
|
||||
#define USBHS_EP13_R_TYP (1 << 29)
|
||||
|
||||
#define USBHS_EP14_T_TYP (1 << 14)
|
||||
#define USBHS_EP14_R_TYP (1 << 30)
|
||||
|
||||
#define USBHS_EP15_T_TYP (1 << 15)
|
||||
#define USBHS_EP15_R_TYP (1 << 31)
|
||||
|
||||
/* BUF_MOD UEP1~15 */
|
||||
#define USBHS_BUF_MOD_OFFSET 0x18
|
||||
#define USBHS_EP0_BUF_MOD (1 << 0)
|
||||
#define USBHS_EP0_ISO_BUF_MOD (1 << 16)
|
||||
|
||||
#define USBHS_EP1_BUF_MOD (1 << 1)
|
||||
#define USBHS_EP1_ISO_BUF_MOD (1 << 17)
|
||||
|
||||
#define USBHS_EP2_BUF_MOD (1 << 2)
|
||||
#define USBHS_EP2_ISO_BUF_MOD (1 << 18)
|
||||
|
||||
#define USBHS_EP3_BUF_MOD (1 << 3)
|
||||
#define USBHS_EP3_ISO_BUF_MOD (1 << 19)
|
||||
|
||||
#define USBHS_EP4_BUF_MOD (1 << 4)
|
||||
#define USBHS_EP4_ISO_BUF_MOD (1 << 20)
|
||||
|
||||
#define USBHS_EP5_BUF_MOD (1 << 5)
|
||||
#define USBHS_EP5_ISO_BUF_MOD (1 << 21)
|
||||
|
||||
#define USBHS_EP6_BUF_MOD (1 << 6)
|
||||
#define USBHS_EP6_ISO_BUF_MOD (1 << 22)
|
||||
|
||||
#define USBHS_EP7_BUF_MOD (1 << 7)
|
||||
#define USBHS_EP7_ISO_BUF_MOD (1 << 23)
|
||||
|
||||
#define USBHS_EP8_BUF_MOD (1 << 8)
|
||||
#define USBHS_EP8_ISO_BUF_MOD (1 << 24)
|
||||
|
||||
#define USBHS_EP9_BUF_MOD (1 << 9)
|
||||
#define USBHS_EP9_ISO_BUF_MOD (1 << 25)
|
||||
|
||||
#define USBHS_EP10_BUF_MOD (1 << 10)
|
||||
#define USBHS_EP10_ISO_BUF_MOD (1 << 26)
|
||||
|
||||
#define USBHS_EP11_BUF_MOD (1 << 11)
|
||||
#define USBHS_EP11_ISO_BUF_MOD (1 << 27)
|
||||
|
||||
#define USBHS_EP12_BUF_MOD (1 << 12)
|
||||
#define USBHS_EP12_ISO_BUF_MOD (1 << 28)
|
||||
|
||||
#define USBHS_EP13_BUF_MOD (1 << 13)
|
||||
#define USBHS_EP13_ISO_BUF_MOD (1 << 29)
|
||||
|
||||
#define USBHS_EP14_BUF_MOD (1 << 14)
|
||||
#define USBHS_EP14_ISO_BUF_MOD (1 << 30)
|
||||
|
||||
#define USBHS_EP15_BUF_MOD (1 << 15)
|
||||
#define USBHS_EP15_ISO_BUF_MOD (1 << 31)
|
||||
//USBHS_EPn_T_EN USBHS_EPn_R_EN USBHS_EPn_BUF_MOD 锟斤拷锟斤拷锟斤拷锟斤拷UEPn_DMA为锟斤拷始锟斤拷址锟缴碉拷锟斤拷锟斤拷锟斤拷锟<E68BB7>
|
||||
// 0 0 x 锟剿点被锟斤拷锟矫o拷未锟矫碉拷UEPn_*_DMA锟斤拷锟斤拷锟斤拷锟斤拷
|
||||
// 1 0 0 锟斤拷锟秸o拷OUT锟斤拷锟斤拷锟斤拷锟斤拷锟阶碉拷址为UEPn_RX_DMA
|
||||
// 1 0 1 bUEPn_RX_TOG[0]=0,使锟矫伙拷锟斤拷锟斤拷UEPn_RX_DMA锟斤拷bUEPn_RX_TOG[0]=1,使锟矫伙拷锟斤拷锟斤拷UEPn_TX_DMA
|
||||
// 0 1 0 锟斤拷锟斤拷(IN)锟斤拷锟斤拷锟斤拷锟阶碉拷址为UEPn_TX_DMA锟斤拷
|
||||
// 0 1 1 bUEPn_TX_TOG[0]=0,使锟矫伙拷锟斤拷锟斤拷UEPn_TX_DMA锟斤拷bUEPn_TX_TOG[0]=1,使锟矫伙拷锟斤拷锟斤拷UEPn_RX_DMA
|
||||
|
||||
/* USB0_DMA */
|
||||
#define USBHS_UEP0_DMA_OFFSET(n) (0x1C) // endpoint 0 DMA buffer address
|
||||
|
||||
/* USBX_RX_DMA */
|
||||
#define USBHS_UEPx_RX_DMA_OFFSET(n) (0x1C + 4 * (n)) // endpoint x DMA buffer address
|
||||
|
||||
#define USBHS_UEPx_TX_DMA_OFFSET(n) (0x58 + 4 * (n)) // endpoint x DMA buffer address
|
||||
|
||||
#define USBHS_UEPx_MAX_LEN_OFFSET(n) (0x98 + 4 * (n)) // endpoint x DMA buffer address
|
||||
|
||||
#define USBHS_UEPx_T_LEN_OFFSET(n) (0xD8 + 4 * (n)) // endpoint x DMA buffer address
|
||||
#define USBHS_UEPx_TX_CTRL_OFFSET(n) (0xD8 + 4 * (n) + 2) // endpoint x DMA buffer address
|
||||
#define USBHS_UEPx_RX_CTRL_OFFSET(n) (0xD8 + 4 * (n) + 3) // endpoint x DMA buffer address
|
||||
|
||||
// UEPn_T_LEN
|
||||
#define USBHS_EP_T_LEN_MASK (0x7FF)
|
||||
|
||||
//UEPn_TX_CTRL
|
||||
#define USBHS_EP_T_RES_MASK (3 << 0)
|
||||
#define USBHS_EP_T_RES_ACK (0 << 0)
|
||||
#define USBHS_EP_T_RES_NYET (1 << 0)
|
||||
#define USBHS_EP_T_RES_NAK (2 << 0)
|
||||
#define USBHS_EP_T_RES_STALL (3 << 0)
|
||||
|
||||
#define USBHS_EP_T_TOG_MASK (3 << 3)
|
||||
#define USBHS_EP_T_TOG_0 (0 << 3)
|
||||
#define USBHS_EP_T_TOG_1 (1 << 3)
|
||||
#define USBHS_EP_T_TOG_2 (2 << 3)
|
||||
#define USBHS_EP_T_TOG_M (3 << 3)
|
||||
|
||||
#define USBHS_EP_T_AUTOTOG (1 << 5)
|
||||
|
||||
//UEPn_RX_CTRL
|
||||
#define USBHS_EP_R_RES_MASK (3 << 0)
|
||||
#define USBHS_EP_R_RES_ACK (0 << 0)
|
||||
#define USBHS_EP_R_RES_NYET (1 << 0)
|
||||
#define USBHS_EP_R_RES_NAK (2 << 0)
|
||||
#define USBHS_EP_R_RES_STALL (3 << 0)
|
||||
|
||||
#define USBHS_EP_R_TOG_MASK (3 << 3)
|
||||
#define USBHS_EP_R_TOG_0 (0 << 3)
|
||||
#define USBHS_EP_R_TOG_1 (1 << 3)
|
||||
#define USBHS_EP_R_TOG_2 (2 << 3)
|
||||
#define USBHS_EP_R_TOG_M (3 << 3)
|
||||
|
||||
#define USBHS_EP_R_AUTOTOG (1 << 5)
|
||||
|
||||
#define USBHS_TOG_MATCH (1 << 6)
|
||||
|
||||
/******************* HOST ******************/
|
||||
// USB HOST_CTRL
|
||||
#define USBHS_SEND_BUS_RESET (1 << 0)
|
||||
#define USBHS_SEND_BUS_SUSPEND (1 << 1)
|
||||
#define USBHS_SEND_BUS_RESUME (1 << 2)
|
||||
#define USBHS_REMOTE_WAKE (1 << 3)
|
||||
#define USBHS_PHY_SUSPENDM (1 << 4)
|
||||
#define USBHS_UH_SOFT_FREE (1 << 6)
|
||||
#define USBHS_SEND_SOF_EN (1 << 7)
|
||||
|
||||
//UH_CONFIG
|
||||
#define USBHS_HOST_TX_EN (1 << 3)
|
||||
#define USBHS_HOST_RX_EN (1 << 18)
|
||||
|
||||
// HOST_EP_TYPE
|
||||
#define USBHS_ENDP_TX_ISO (1 << 3)
|
||||
#define USBHS_ENDP_RX_ISO (1 << (16 + 2))
|
||||
|
||||
// R32_UH_EP_PID
|
||||
#define USBHS_HOST_MASK_TOKEN (0x0f)
|
||||
#define USBHS_HOST_MASK_ENDP (0x0f << 4)
|
||||
|
||||
//R8_UH_RX_CTRL
|
||||
#define USBHS_EP_R_RES_MASK (3 << 0)
|
||||
#define USBHS_EP_R_RES_ACK (0 << 0)
|
||||
#define USBHS_EP_R_RES_NYET (1 << 0)
|
||||
#define USBHS_EP_R_RES_NAK (2 << 0)
|
||||
#define USBHS_EP_R_RES_STALL (3 << 0)
|
||||
|
||||
#define USBHS_UH_R_RES_NO (1 << 2)
|
||||
#define USBHS_UH_R_TOG_1 (1 << 3)
|
||||
#define USBHS_UH_R_TOG_2 (2 << 3)
|
||||
#define USBHS_UH_R_TOG_3 (3 << 3)
|
||||
#define USBHS_UH_R_TOG_AUTO (1 << 5)
|
||||
#define USBHS_UH_R_DATA_NO (1 << 6)
|
||||
//R8_UH_TX_CTRL
|
||||
#define USBHS_UH_T_RES_MASK (3 << 0)
|
||||
#define USBHS_UH_T_RES_ACK (0 << 0)
|
||||
#define USBHS_UH_T_RES_NYET (1 << 0)
|
||||
#define USBHS_UH_T_RES_NAK (2 << 0)
|
||||
#define USBHS_UH_T_RES_STALL (3 << 0)
|
||||
|
||||
#define USBHS_UH_T_RES_NO (1 << 2)
|
||||
#define USBHS_UH_T_TOG_1 (1 << 3)
|
||||
#define USBHS_UH_T_TOG_2 (2 << 3)
|
||||
#define USBHS_UH_T_TOG_3 (3 << 3)
|
||||
#define USBHS_UH_T_TOG_AUTO (1 << 5)
|
||||
#define USBHS_UH_T_DATA_NO (1 << 6)
|
||||
|
||||
// 00: OUT, 01:SOF, 10:IN, 11:SETUP
|
||||
#define PID_OUT 0
|
||||
#define PID_SOF 1
|
||||
#define PID_IN 2
|
||||
#define PID_SETUP 3
|
||||
|
||||
#endif
|
@@ -0,0 +1,404 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usb_ch32_usbfs_reg.h"
|
||||
|
||||
#ifdef CONFIG_USB_HS
|
||||
#error "usb fs do not support hs"
|
||||
#endif
|
||||
|
||||
#ifndef USBD_IRQHandler
|
||||
#define USBD_IRQHandler OTG_FS_IRQHandler //use actual usb irq name instead
|
||||
#endif
|
||||
|
||||
#ifndef USB_NUM_BIDIR_ENDPOINTS
|
||||
#define USB_NUM_BIDIR_ENDPOINTS 8
|
||||
#endif
|
||||
|
||||
#define USB_SET_DMA(ep_idx, addr) (*(volatile uint32_t *)((uint32_t)(&USBFS_DEVICE->UEP0_DMA) + 4 * ep_idx) = addr)
|
||||
#define USB_SET_TX_LEN(ep_idx, len) (*(volatile uint16_t *)((uint32_t)(&USBFS_DEVICE->UEP0_TX_LEN) + 4 * ep_idx) = len)
|
||||
#define USB_GET_TX_LEN(ep_idx) (*(volatile uint16_t *)((uint32_t)(&USBFS_DEVICE->UEP0_TX_LEN) + 4 * ep_idx))
|
||||
#define USB_SET_TX_CTRL(ep_idx, val) (*(volatile uint8_t *)((uint32_t)(&USBFS_DEVICE->UEP0_TX_CTRL) + 4 * ep_idx) = val)
|
||||
#define USB_GET_TX_CTRL(ep_idx) (*(volatile uint8_t *)((uint32_t)(&USBFS_DEVICE->UEP0_TX_CTRL) + 4 * ep_idx))
|
||||
#define USB_SET_RX_CTRL(ep_idx, val) (*(volatile uint8_t *)((uint32_t)(&USBFS_DEVICE->UEP0_RX_CTRL) + 4 * ep_idx) = val)
|
||||
#define USB_GET_RX_CTRL(ep_idx) (*(volatile uint8_t *)((uint32_t)(&USBFS_DEVICE->UEP0_RX_CTRL) + 4 * ep_idx))
|
||||
|
||||
/* Endpoint state */
|
||||
struct ch32_usbfs_ep_state {
|
||||
uint16_t ep_mps; /* Endpoint max packet size */
|
||||
uint8_t ep_type; /* Endpoint type */
|
||||
uint8_t ep_stalled; /* Endpoint stall flag */
|
||||
uint8_t ep_enable; /* Endpoint enable */
|
||||
uint8_t *xfer_buf;
|
||||
uint32_t xfer_len;
|
||||
uint32_t actual_xfer_len;
|
||||
};
|
||||
|
||||
/* Driver state */
|
||||
struct ch32_usbfs_udc {
|
||||
__attribute__((aligned(4))) struct usb_setup_packet setup;
|
||||
volatile uint8_t dev_addr;
|
||||
struct ch32_usbfs_ep_state in_ep[USB_NUM_BIDIR_ENDPOINTS]; /*!< IN endpoint parameters*/
|
||||
struct ch32_usbfs_ep_state out_ep[USB_NUM_BIDIR_ENDPOINTS]; /*!< OUT endpoint parameters */
|
||||
__attribute__((aligned(4))) uint8_t ep_databuf[USB_NUM_BIDIR_ENDPOINTS - 1][64 + 64]; //epx_out(64)+epx_in(64)
|
||||
} g_ch32_usbfs_udc;
|
||||
|
||||
volatile bool ep0_rx_data_toggle;
|
||||
volatile bool ep0_tx_data_toggle;
|
||||
|
||||
void USBD_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
|
||||
|
||||
__WEAK void usb_dc_low_level_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usb_dc_low_level_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
int usb_dc_init(uint8_t busid)
|
||||
{
|
||||
usb_dc_low_level_init();
|
||||
|
||||
USBFS_DEVICE->BASE_CTRL = 0x00;
|
||||
|
||||
USBFS_DEVICE->UEP4_1_MOD = USBFS_UEP4_RX_EN | USBFS_UEP4_TX_EN | USBFS_UEP1_RX_EN | USBFS_UEP1_TX_EN;
|
||||
USBFS_DEVICE->UEP2_3_MOD = USBFS_UEP2_RX_EN | USBFS_UEP2_TX_EN | USBFS_UEP3_RX_EN | USBFS_UEP3_TX_EN;
|
||||
USBFS_DEVICE->UEP5_6_MOD = USBFS_UEP5_RX_EN | USBFS_UEP5_TX_EN | USBFS_UEP6_RX_EN | USBFS_UEP6_TX_EN;
|
||||
USBFS_DEVICE->UEP7_MOD = USBFS_UEP7_RX_EN | USBFS_UEP7_TX_EN;
|
||||
|
||||
USBFS_DEVICE->UEP1_DMA = (uint32_t)g_ch32_usbfs_udc.ep_databuf[0];
|
||||
USBFS_DEVICE->UEP2_DMA = (uint32_t)g_ch32_usbfs_udc.ep_databuf[1];
|
||||
USBFS_DEVICE->UEP3_DMA = (uint32_t)g_ch32_usbfs_udc.ep_databuf[2];
|
||||
USBFS_DEVICE->UEP4_DMA = (uint32_t)g_ch32_usbfs_udc.ep_databuf[3];
|
||||
USBFS_DEVICE->UEP5_DMA = (uint32_t)g_ch32_usbfs_udc.ep_databuf[4];
|
||||
USBFS_DEVICE->UEP6_DMA = (uint32_t)g_ch32_usbfs_udc.ep_databuf[5];
|
||||
USBFS_DEVICE->UEP7_DMA = (uint32_t)g_ch32_usbfs_udc.ep_databuf[6];
|
||||
|
||||
USBFS_DEVICE->INT_FG = 0xFF;
|
||||
USBFS_DEVICE->INT_EN = USBFS_UIE_SUSPEND | USBFS_UIE_BUS_RST | USBFS_UIE_TRANSFER;
|
||||
USBFS_DEVICE->DEV_ADDR = 0x00;
|
||||
|
||||
USBFS_DEVICE->BASE_CTRL = USBFS_UC_DEV_PU_EN | USBFS_UC_INT_BUSY | USBFS_UC_DMA_EN;
|
||||
USBFS_DEVICE->UDEV_CTRL = USBFS_UD_PD_DIS | USBFS_UD_PORT_EN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usb_dc_deinit(uint8_t busid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_set_address(uint8_t busid, const uint8_t addr)
|
||||
{
|
||||
if (addr == 0) {
|
||||
USBFS_DEVICE->DEV_ADDR = (USBFS_DEVICE->DEV_ADDR & USBFS_UDA_GP_BIT) | 0;
|
||||
}
|
||||
g_ch32_usbfs_udc.dev_addr = addr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t usbd_get_port_speed(uint8_t busid)
|
||||
{
|
||||
return USB_SPEED_FULL;
|
||||
}
|
||||
|
||||
int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);
|
||||
|
||||
if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
|
||||
g_ch32_usbfs_udc.out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_ch32_usbfs_udc.out_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
g_ch32_usbfs_udc.out_ep[ep_idx].ep_enable = true;
|
||||
USB_SET_RX_CTRL(ep_idx, USBFS_UEP_R_RES_NAK | USBFS_UEP_AUTO_TOG);
|
||||
} else {
|
||||
g_ch32_usbfs_udc.in_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_ch32_usbfs_udc.in_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
g_ch32_usbfs_udc.in_ep[ep_idx].ep_enable = true;
|
||||
USB_SET_TX_CTRL(ep_idx, USBFS_UEP_T_RES_NAK | USBFS_UEP_AUTO_TOG);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int usbd_ep_close(uint8_t busid, const uint8_t ep)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int usbd_ep_set_stall(uint8_t busid, const uint8_t ep)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep);
|
||||
|
||||
if (USB_EP_DIR_IS_OUT(ep)) {
|
||||
if (ep_idx == 0) {
|
||||
USBFS_DEVICE->UEP0_RX_CTRL = USBFS_UEP_R_TOG | USBFS_UEP_R_RES_STALL;
|
||||
} else {
|
||||
USB_SET_RX_CTRL(ep_idx, (USB_GET_RX_CTRL(ep_idx) & ~USBFS_UEP_R_RES_MASK) | USBFS_UEP_R_RES_STALL);
|
||||
}
|
||||
} else {
|
||||
if (ep_idx == 0) {
|
||||
USBFS_DEVICE->UEP0_TX_CTRL = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_STALL;
|
||||
} else {
|
||||
USB_SET_TX_CTRL(ep_idx, (USB_GET_TX_CTRL(ep_idx) & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_STALL);
|
||||
}
|
||||
}
|
||||
|
||||
if (ep_idx == 0) {
|
||||
USB_SET_DMA(ep_idx, (uint32_t)&g_ch32_usbfs_udc.setup);
|
||||
USB_SET_RX_CTRL(ep_idx, USBFS_UEP_R_RES_ACK);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep);
|
||||
|
||||
if (ep_idx == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (USB_EP_DIR_IS_OUT(ep)) {
|
||||
USB_SET_RX_CTRL(ep_idx, (USB_GET_RX_CTRL(ep_idx) & ~(USBFS_UEP_R_TOG | USBFS_UEP_R_RES_MASK)) | USBFS_UEP_R_RES_ACK);
|
||||
} else {
|
||||
USB_SET_TX_CTRL(ep_idx, (USB_GET_TX_CTRL(ep_idx) & ~(USBFS_UEP_T_TOG | USBFS_UEP_T_RES_MASK)) | USBFS_UEP_T_RES_NAK);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, uint32_t data_len)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep);
|
||||
|
||||
if (!data && data_len) {
|
||||
return -1;
|
||||
}
|
||||
if (!g_ch32_usbfs_udc.in_ep[ep_idx].ep_enable) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
if ((uint32_t)data & 0x03) {
|
||||
printf("data do not align4\r\n");
|
||||
return -3;
|
||||
}
|
||||
|
||||
g_ch32_usbfs_udc.in_ep[ep_idx].xfer_buf = (uint8_t *)data;
|
||||
g_ch32_usbfs_udc.in_ep[ep_idx].xfer_len = data_len;
|
||||
g_ch32_usbfs_udc.in_ep[ep_idx].actual_xfer_len = 0;
|
||||
|
||||
if (ep_idx == 0) {
|
||||
if (data_len == 0) {
|
||||
USB_SET_TX_LEN(ep_idx, 0);
|
||||
} else {
|
||||
data_len = MIN(data_len, g_ch32_usbfs_udc.in_ep[ep_idx].ep_mps);
|
||||
USB_SET_TX_LEN(ep_idx, data_len);
|
||||
USB_SET_DMA(ep_idx, (uint32_t)data);
|
||||
}
|
||||
if (ep0_tx_data_toggle) {
|
||||
USB_SET_TX_CTRL(ep_idx, USBFS_UEP_T_TOG | USBFS_UEP_T_RES_ACK);
|
||||
} else {
|
||||
USB_SET_TX_CTRL(ep_idx, USBFS_UEP_T_RES_ACK);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (data_len == 0) {
|
||||
USB_SET_TX_LEN(ep_idx, 0);
|
||||
} else {
|
||||
data_len = MIN(data_len, g_ch32_usbfs_udc.in_ep[ep_idx].ep_mps);
|
||||
USB_SET_TX_LEN(ep_idx, data_len);
|
||||
memcpy(&g_ch32_usbfs_udc.ep_databuf[ep_idx - 1][64], data, data_len);
|
||||
}
|
||||
USB_SET_TX_CTRL(ep_idx, (USB_GET_TX_CTRL(ep_idx) & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_ACK);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep);
|
||||
|
||||
if (!data && data_len) {
|
||||
return -1;
|
||||
}
|
||||
if (!g_ch32_usbfs_udc.out_ep[ep_idx].ep_enable) {
|
||||
return -2;
|
||||
}
|
||||
if ((uint32_t)data & 0x03) {
|
||||
printf("data do not align4\r\n");
|
||||
return -3;
|
||||
}
|
||||
|
||||
g_ch32_usbfs_udc.out_ep[ep_idx].xfer_buf = (uint8_t *)data;
|
||||
g_ch32_usbfs_udc.out_ep[ep_idx].xfer_len = data_len;
|
||||
g_ch32_usbfs_udc.out_ep[ep_idx].actual_xfer_len = 0;
|
||||
|
||||
if (ep_idx == 0) {
|
||||
if (data_len == 0) {
|
||||
} else {
|
||||
USB_SET_DMA(ep_idx, (uint32_t)data);
|
||||
}
|
||||
if (ep0_rx_data_toggle) {
|
||||
USB_SET_RX_CTRL(ep_idx, USBFS_UEP_R_TOG | USBFS_UEP_R_RES_ACK);
|
||||
} else {
|
||||
USB_SET_RX_CTRL(ep_idx, USBFS_UEP_R_RES_ACK);
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
USB_SET_RX_CTRL(ep_idx, (USB_GET_RX_CTRL(ep_idx) & ~USBFS_UEP_R_RES_MASK) | USBFS_UEP_R_RES_ACK);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void USBD_IRQHandler(void)
|
||||
{
|
||||
uint32_t ep_idx = 0, token, write_count, read_count;
|
||||
uint8_t intflag = 0;
|
||||
|
||||
intflag = USBFS_DEVICE->INT_FG;
|
||||
|
||||
if (intflag & USBFS_UIF_TRANSFER) {
|
||||
token = USBFS_DEVICE->INT_ST & USBFS_UIS_TOKEN_MASK;
|
||||
ep_idx = USBFS_DEVICE->INT_ST & USBFS_UIS_ENDP_MASK;
|
||||
switch (token) {
|
||||
case USBFS_UIS_TOKEN_SETUP:
|
||||
USB_SET_RX_CTRL(ep_idx, USBFS_UEP_R_RES_NAK);
|
||||
usbd_event_ep0_setup_complete_handler(0, (uint8_t *)&g_ch32_usbfs_udc.setup);
|
||||
break;
|
||||
|
||||
case USBFS_UIS_TOKEN_IN:
|
||||
if (ep_idx == 0x00) {
|
||||
if (g_ch32_usbfs_udc.in_ep[ep_idx].xfer_len >= g_ch32_usbfs_udc.in_ep[ep_idx].ep_mps) {
|
||||
g_ch32_usbfs_udc.in_ep[ep_idx].xfer_len -= g_ch32_usbfs_udc.in_ep[ep_idx].ep_mps;
|
||||
g_ch32_usbfs_udc.in_ep[ep_idx].actual_xfer_len += g_ch32_usbfs_udc.in_ep[ep_idx].ep_mps;
|
||||
ep0_tx_data_toggle ^= 1;
|
||||
} else {
|
||||
g_ch32_usbfs_udc.in_ep[ep_idx].actual_xfer_len += g_ch32_usbfs_udc.in_ep[ep_idx].xfer_len;
|
||||
g_ch32_usbfs_udc.in_ep[ep_idx].xfer_len = 0;
|
||||
ep0_tx_data_toggle = true;
|
||||
}
|
||||
|
||||
usbd_event_ep_in_complete_handler(0, ep_idx | 0x80, g_ch32_usbfs_udc.in_ep[ep_idx].actual_xfer_len);
|
||||
|
||||
if (g_ch32_usbfs_udc.dev_addr > 0) {
|
||||
USBFS_DEVICE->DEV_ADDR = (USBFS_DEVICE->DEV_ADDR & USBFS_UDA_GP_BIT) | g_ch32_usbfs_udc.dev_addr;
|
||||
g_ch32_usbfs_udc.dev_addr = 0;
|
||||
}
|
||||
|
||||
if (g_ch32_usbfs_udc.setup.wLength && ((g_ch32_usbfs_udc.setup.bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_OUT)) {
|
||||
/* In status, start reading setup */
|
||||
USB_SET_DMA(ep_idx, (uint32_t)&g_ch32_usbfs_udc.setup);
|
||||
USB_SET_RX_CTRL(ep_idx, USBFS_UEP_R_RES_ACK);
|
||||
ep0_tx_data_toggle = true;
|
||||
|
||||
} else if (g_ch32_usbfs_udc.setup.wLength == 0) {
|
||||
/* In status, start reading setup */
|
||||
USB_SET_DMA(ep_idx, (uint32_t)&g_ch32_usbfs_udc.setup);
|
||||
USB_SET_RX_CTRL(ep_idx, USBFS_UEP_R_RES_ACK);
|
||||
ep0_tx_data_toggle = true;
|
||||
}
|
||||
} else {
|
||||
USB_SET_TX_CTRL(ep_idx, (USB_GET_TX_CTRL(ep_idx) & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_NAK);
|
||||
|
||||
if (g_ch32_usbfs_udc.in_ep[ep_idx].xfer_len > g_ch32_usbfs_udc.in_ep[ep_idx].ep_mps) {
|
||||
g_ch32_usbfs_udc.in_ep[ep_idx].xfer_buf += g_ch32_usbfs_udc.in_ep[ep_idx].ep_mps;
|
||||
g_ch32_usbfs_udc.in_ep[ep_idx].xfer_len -= g_ch32_usbfs_udc.in_ep[ep_idx].ep_mps;
|
||||
g_ch32_usbfs_udc.in_ep[ep_idx].actual_xfer_len += g_ch32_usbfs_udc.in_ep[ep_idx].ep_mps;
|
||||
|
||||
write_count = MIN(g_ch32_usbfs_udc.in_ep[ep_idx].xfer_len, g_ch32_usbfs_udc.in_ep[ep_idx].ep_mps);
|
||||
USB_SET_TX_LEN(ep_idx, write_count);
|
||||
memcpy(&g_ch32_usbfs_udc.ep_databuf[ep_idx - 1][64], g_ch32_usbfs_udc.in_ep[ep_idx].xfer_buf, write_count);
|
||||
|
||||
USB_SET_TX_CTRL(ep_idx, (USB_GET_TX_CTRL(ep_idx) & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_ACK);
|
||||
} else {
|
||||
g_ch32_usbfs_udc.in_ep[ep_idx].actual_xfer_len += g_ch32_usbfs_udc.in_ep[ep_idx].xfer_len;
|
||||
g_ch32_usbfs_udc.in_ep[ep_idx].xfer_len = 0;
|
||||
usbd_event_ep_in_complete_handler(0, ep_idx | 0x80, g_ch32_usbfs_udc.in_ep[ep_idx].actual_xfer_len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case USBFS_UIS_TOKEN_OUT:
|
||||
if (ep_idx == 0x00) {
|
||||
USB_SET_RX_CTRL(ep_idx, USBFS_UEP_R_RES_NAK);
|
||||
|
||||
read_count = USBFS_DEVICE->RX_LEN;
|
||||
|
||||
g_ch32_usbfs_udc.out_ep[ep_idx].actual_xfer_len += read_count;
|
||||
g_ch32_usbfs_udc.out_ep[ep_idx].xfer_len -= read_count;
|
||||
|
||||
usbd_event_ep_out_complete_handler(0, 0x00, g_ch32_usbfs_udc.out_ep[ep_idx].actual_xfer_len);
|
||||
|
||||
if (read_count == 0) {
|
||||
/* Out status, start reading setup */
|
||||
USB_SET_DMA(ep_idx, (uint32_t)&g_ch32_usbfs_udc.setup);
|
||||
USB_SET_RX_CTRL(ep_idx, USBFS_UEP_R_RES_ACK);
|
||||
ep0_rx_data_toggle = true;
|
||||
ep0_tx_data_toggle = true;
|
||||
} else {
|
||||
ep0_rx_data_toggle ^= 1;
|
||||
}
|
||||
} else {
|
||||
if (USBFS_DEVICE->INT_ST & USBFS_UIS_TOG_OK) {
|
||||
USB_SET_RX_CTRL(ep_idx, (USB_GET_RX_CTRL(ep_idx) & ~USBFS_UEP_R_RES_MASK) | USBFS_UEP_R_RES_NAK);
|
||||
read_count = USBFS_DEVICE->RX_LEN;
|
||||
|
||||
memcpy(g_ch32_usbfs_udc.out_ep[ep_idx].xfer_buf, &g_ch32_usbfs_udc.ep_databuf[ep_idx - 1][0], read_count);
|
||||
|
||||
g_ch32_usbfs_udc.out_ep[ep_idx].xfer_buf += read_count;
|
||||
g_ch32_usbfs_udc.out_ep[ep_idx].actual_xfer_len += read_count;
|
||||
g_ch32_usbfs_udc.out_ep[ep_idx].xfer_len -= read_count;
|
||||
|
||||
if ((read_count < g_ch32_usbfs_udc.out_ep[ep_idx].ep_mps) || (g_ch32_usbfs_udc.out_ep[ep_idx].xfer_len == 0)) {
|
||||
usbd_event_ep_out_complete_handler(0, ep_idx, g_ch32_usbfs_udc.out_ep[ep_idx].actual_xfer_len);
|
||||
} else {
|
||||
USB_SET_RX_CTRL(ep_idx, (USB_GET_RX_CTRL(ep_idx) & ~USBFS_UEP_R_RES_MASK) | USBFS_UEP_R_RES_ACK);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case USBFS_UIS_TOKEN_SOF:
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
USBFS_DEVICE->INT_FG = USBFS_UIF_TRANSFER;
|
||||
} else if (intflag & USBFS_UIF_BUS_RST) {
|
||||
USBFS_DEVICE->UEP0_TX_LEN = 0;
|
||||
USBFS_DEVICE->UEP0_TX_CTRL = USBFS_UEP_T_RES_NAK;
|
||||
USBFS_DEVICE->UEP0_RX_CTRL = USBFS_UEP_R_RES_NAK;
|
||||
|
||||
for (uint8_t ep_idx = 1; ep_idx < USB_NUM_BIDIR_ENDPOINTS; ep_idx++) {
|
||||
USB_SET_TX_LEN(ep_idx, 0);
|
||||
USB_SET_TX_CTRL(ep_idx, USBFS_UEP_T_RES_NAK | USBFS_UEP_AUTO_TOG);
|
||||
USB_SET_RX_CTRL(ep_idx, USBFS_UEP_R_RES_NAK | USBFS_UEP_AUTO_TOG);
|
||||
}
|
||||
|
||||
ep0_tx_data_toggle = true;
|
||||
ep0_rx_data_toggle = true;
|
||||
|
||||
memset(&g_ch32_usbfs_udc, 0, sizeof(struct ch32_usbfs_udc));
|
||||
usbd_event_reset_handler(0);
|
||||
USB_SET_DMA(ep_idx, (uint32_t)&g_ch32_usbfs_udc.setup);
|
||||
USB_SET_RX_CTRL(ep_idx, USBFS_UEP_R_RES_ACK);
|
||||
|
||||
USBFS_DEVICE->INT_FG |= USBFS_UIF_BUS_RST;
|
||||
} else if (intflag & USBFS_UIF_SUSPEND) {
|
||||
if (USBFS_DEVICE->MIS_ST & USBFS_UMS_SUSPEND) {
|
||||
} else {
|
||||
}
|
||||
USBFS_DEVICE->INT_FG = USBFS_UIF_SUSPEND;
|
||||
} else {
|
||||
USBFS_DEVICE->INT_FG = intflag;
|
||||
}
|
||||
}
|
@@ -0,0 +1,382 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usb_ch32_usbhs_reg.h"
|
||||
|
||||
#ifndef USBD_IRQHandler
|
||||
#define USBD_IRQHandler USBHS_IRQHandler //use actual usb irq name instead
|
||||
#endif
|
||||
|
||||
#ifndef USB_NUM_BIDIR_ENDPOINTS
|
||||
#define USB_NUM_BIDIR_ENDPOINTS 16
|
||||
#endif
|
||||
|
||||
#define USB_SET_RX_DMA(ep_idx, addr) (*(volatile uint32_t *)((uint32_t)(&USBHS_DEVICE->UEP1_RX_DMA) + 4 * (ep_idx - 1)) = addr)
|
||||
#define USB_SET_TX_DMA(ep_idx, addr) (*(volatile uint32_t *)((uint32_t)(&USBHS_DEVICE->UEP1_TX_DMA) + 4 * (ep_idx - 1)) = addr)
|
||||
#define USB_SET_MAX_LEN(ep_idx, len) (*(volatile uint16_t *)((uint32_t)(&USBHS_DEVICE->UEP0_MAX_LEN) + 4 * ep_idx) = len)
|
||||
#define USB_SET_TX_LEN(ep_idx, len) (*(volatile uint16_t *)((uint32_t)(&USBHS_DEVICE->UEP0_TX_LEN) + 4 * ep_idx) = len)
|
||||
#define USB_GET_TX_LEN(ep_idx) (*(volatile uint16_t *)((uint32_t)(&USBHS_DEVICE->UEP0_TX_LEN) + 4 * ep_idx))
|
||||
#define USB_SET_TX_CTRL(ep_idx, val) (*(volatile uint8_t *)((uint32_t)(&USBHS_DEVICE->UEP0_TX_CTRL) + 4 * ep_idx) = val)
|
||||
#define USB_GET_TX_CTRL(ep_idx) (*(volatile uint8_t *)((uint32_t)(&USBHS_DEVICE->UEP0_TX_CTRL) + 4 * ep_idx))
|
||||
#define USB_SET_RX_CTRL(ep_idx, val) (*(volatile uint8_t *)((uint32_t)(&USBHS_DEVICE->UEP0_RX_CTRL) + 4 * ep_idx) = val)
|
||||
#define USB_GET_RX_CTRL(ep_idx) (*(volatile uint8_t *)((uint32_t)(&USBHS_DEVICE->UEP0_RX_CTRL) + 4 * ep_idx))
|
||||
|
||||
/* Endpoint state */
|
||||
struct ch32_usbhs_ep_state {
|
||||
uint16_t ep_mps; /* Endpoint max packet size */
|
||||
uint8_t ep_type; /* Endpoint type */
|
||||
uint8_t ep_stalled; /* Endpoint stall flag */
|
||||
uint8_t ep_enable; /* Endpoint enable */
|
||||
uint8_t *xfer_buf;
|
||||
uint32_t xfer_len;
|
||||
uint32_t actual_xfer_len;
|
||||
};
|
||||
|
||||
/* Driver state */
|
||||
struct ch32_usbhs_udc {
|
||||
__attribute__((aligned(4))) struct usb_setup_packet setup;
|
||||
volatile uint8_t dev_addr;
|
||||
struct ch32_usbhs_ep_state in_ep[USB_NUM_BIDIR_ENDPOINTS]; /*!< IN endpoint parameters*/
|
||||
struct ch32_usbhs_ep_state out_ep[USB_NUM_BIDIR_ENDPOINTS]; /*!< OUT endpoint parameters */
|
||||
} g_ch32_usbhs_udc;
|
||||
|
||||
void USBHS_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
|
||||
|
||||
volatile uint8_t mps_over_flag = 0;
|
||||
volatile bool ep0_rx_data_toggle;
|
||||
volatile bool ep0_tx_data_toggle;
|
||||
volatile bool epx_tx_data_toggle[USB_NUM_BIDIR_ENDPOINTS - 1];
|
||||
|
||||
__WEAK void usb_dc_low_level_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usb_dc_low_level_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
int usb_dc_init(uint8_t busid)
|
||||
{
|
||||
usb_dc_low_level_init();
|
||||
|
||||
USBHS_DEVICE->HOST_CTRL = 0x00;
|
||||
USBHS_DEVICE->HOST_CTRL = USBHS_PHY_SUSPENDM;
|
||||
|
||||
USBHS_DEVICE->CONTROL = 0;
|
||||
#ifdef CONFIG_USB_HS
|
||||
USBHS_DEVICE->CONTROL = USBHS_DMA_EN | USBHS_INT_BUSY_EN | USBHS_HIGH_SPEED;
|
||||
#else
|
||||
USBHS_DEVICE->CONTROL = USBHS_DMA_EN | USBHS_INT_BUSY_EN | USBHS_FULL_SPEED;
|
||||
#endif
|
||||
|
||||
USBHS_DEVICE->INT_FG = 0xff;
|
||||
USBHS_DEVICE->INT_EN = 0;
|
||||
USBHS_DEVICE->INT_EN = USBHS_SETUP_ACT_EN | USBHS_TRANSFER_EN | USBHS_DETECT_EN;
|
||||
|
||||
/* ALL endpoint enable */
|
||||
USBHS_DEVICE->ENDP_CONFIG = 0xffffffff;
|
||||
|
||||
USBHS_DEVICE->ENDP_TYPE = 0x00;
|
||||
USBHS_DEVICE->BUF_MODE = 0x00;
|
||||
|
||||
USBHS_DEVICE->CONTROL |= USBHS_DEV_PU_EN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usb_dc_deinit(uint8_t busid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_set_address(uint8_t busid, const uint8_t addr)
|
||||
{
|
||||
if (addr == 0) {
|
||||
USBHS_DEVICE->DEV_AD = addr & 0xff;
|
||||
}
|
||||
g_ch32_usbhs_udc.dev_addr = addr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t usbd_get_port_speed(uint8_t busid)
|
||||
{
|
||||
return USB_SPEED_HIGH;
|
||||
}
|
||||
|
||||
int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);
|
||||
|
||||
if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
|
||||
g_ch32_usbhs_udc.out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_ch32_usbhs_udc.out_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
g_ch32_usbhs_udc.out_ep[ep_idx].ep_enable = true;
|
||||
USBHS_DEVICE->ENDP_CONFIG |= (1 << (ep_idx + 16));
|
||||
USB_SET_RX_CTRL(ep_idx, USBHS_EP_R_RES_NAK | USBHS_EP_R_TOG_0 | USBHS_EP_R_AUTOTOG);
|
||||
} else {
|
||||
g_ch32_usbhs_udc.in_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
|
||||
g_ch32_usbhs_udc.in_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
|
||||
g_ch32_usbhs_udc.in_ep[ep_idx].ep_enable = true;
|
||||
USBHS_DEVICE->ENDP_CONFIG |= (1 << (ep_idx));
|
||||
USB_SET_TX_CTRL(ep_idx, USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0 | USBHS_EP_T_AUTOTOG);
|
||||
}
|
||||
USB_SET_MAX_LEN(ep_idx, USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_close(uint8_t busid, const uint8_t ep)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_set_stall(uint8_t busid, const uint8_t ep)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep);
|
||||
|
||||
if (USB_EP_DIR_IS_OUT(ep)) {
|
||||
if (ep_idx == 0) {
|
||||
USBHS_DEVICE->UEP0_RX_CTRL = USBHS_EP_R_RES_STALL;
|
||||
} else {
|
||||
USB_SET_RX_CTRL(ep_idx, (USB_GET_RX_CTRL(ep_idx) & ~USBHS_EP_R_RES_MASK) | USBHS_EP_R_RES_STALL);
|
||||
}
|
||||
} else {
|
||||
if (ep_idx == 0) {
|
||||
USBHS_DEVICE->UEP0_TX_CTRL = USBHS_EP_T_RES_STALL;
|
||||
} else {
|
||||
USB_SET_TX_CTRL(ep_idx, (USB_GET_TX_CTRL(ep_idx) & ~USBHS_EP_T_RES_MASK) | USBHS_EP_T_RES_STALL);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep);
|
||||
|
||||
if (USB_EP_DIR_IS_OUT(ep)) {
|
||||
USB_SET_RX_CTRL(ep_idx, USBHS_EP_R_RES_ACK | USBHS_EP_R_TOG_0);
|
||||
} else {
|
||||
USB_SET_TX_CTRL(ep_idx, USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, uint32_t data_len)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep);
|
||||
uint32_t tmp;
|
||||
|
||||
if (!data && data_len) {
|
||||
return -1;
|
||||
}
|
||||
if (!g_ch32_usbhs_udc.in_ep[ep_idx].ep_enable) {
|
||||
return -2;
|
||||
}
|
||||
if ((uint32_t)data & 0x03) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
g_ch32_usbhs_udc.in_ep[ep_idx].xfer_buf = (uint8_t *)data;
|
||||
g_ch32_usbhs_udc.in_ep[ep_idx].xfer_len = data_len;
|
||||
g_ch32_usbhs_udc.in_ep[ep_idx].actual_xfer_len = 0;
|
||||
|
||||
if (ep_idx == 0) {
|
||||
if (data_len == 0) {
|
||||
USB_SET_TX_LEN(ep_idx, 0);
|
||||
} else {
|
||||
data_len = MIN(data_len, g_ch32_usbhs_udc.in_ep[ep_idx].ep_mps);
|
||||
USB_SET_TX_LEN(ep_idx, data_len);
|
||||
USBHS_DEVICE->UEP0_DMA = (uint32_t)data;
|
||||
}
|
||||
tmp = ep0_tx_data_toggle ? USBHS_EP_T_TOG_1 : USBHS_EP_T_TOG_0;
|
||||
USBHS_DEVICE->UEP0_TX_CTRL = USBHS_EP_T_RES_ACK | tmp;
|
||||
} else {
|
||||
if (data_len == 0) {
|
||||
USB_SET_TX_LEN(ep_idx, 0);
|
||||
} else {
|
||||
data_len = MIN(data_len, g_ch32_usbhs_udc.in_ep[ep_idx].ep_mps);
|
||||
USB_SET_TX_LEN(ep_idx, data_len);
|
||||
USB_SET_TX_DMA(ep_idx, (uint32_t)data);
|
||||
}
|
||||
tmp = USB_GET_TX_CTRL(ep_idx);
|
||||
tmp &= ~(USBHS_EP_T_RES_MASK | USBHS_EP_T_TOG_MASK);
|
||||
tmp |= USBHS_EP_T_RES_ACK;
|
||||
tmp |= (epx_tx_data_toggle[ep_idx - 1] ? USBHS_EP_T_TOG_1 : USBHS_EP_T_TOG_0);
|
||||
USB_SET_TX_CTRL(ep_idx, tmp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len)
|
||||
{
|
||||
uint8_t ep_idx = USB_EP_GET_IDX(ep);
|
||||
|
||||
if (!data && data_len) {
|
||||
return -1;
|
||||
}
|
||||
if (!g_ch32_usbhs_udc.out_ep[ep_idx].ep_enable) {
|
||||
return -2;
|
||||
}
|
||||
if ((uint32_t)data & 0x03) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
g_ch32_usbhs_udc.out_ep[ep_idx].xfer_buf = (uint8_t *)data;
|
||||
g_ch32_usbhs_udc.out_ep[ep_idx].xfer_len = data_len;
|
||||
g_ch32_usbhs_udc.out_ep[ep_idx].actual_xfer_len = 0;
|
||||
|
||||
if (ep_idx == 0) {
|
||||
if (data_len == 0) {
|
||||
USBHS_DEVICE->UEP0_RX_CTRL = USBHS_EP_R_RES_ACK | USBHS_EP_R_TOG_1;
|
||||
} else {
|
||||
USBHS_DEVICE->UEP0_DMA = (uint32_t)data;
|
||||
USBHS_DEVICE->UEP0_RX_CTRL = USBHS_EP_R_RES_ACK | (ep0_rx_data_toggle ? USBHS_EP_R_TOG_1 : USBHS_EP_R_TOG_0);
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
USB_SET_RX_DMA(ep_idx, (uint32_t)data);
|
||||
USB_SET_RX_CTRL(ep_idx, (USB_GET_RX_CTRL(ep_idx) & ~USBHS_EP_R_RES_MASK) | USBHS_EP_R_RES_ACK);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void USBD_IRQHandler(void)
|
||||
{
|
||||
uint32_t ep_idx, token, write_count, read_count;
|
||||
uint8_t intflag = 0;
|
||||
|
||||
intflag = USBHS_DEVICE->INT_FG;
|
||||
|
||||
if (intflag & USBHS_TRANSFER_FLAG) {
|
||||
ep_idx = (USBHS_DEVICE->INT_ST) & MASK_UIS_ENDP;
|
||||
token = (((USBHS_DEVICE->INT_ST) & MASK_UIS_TOKEN) >> 4) & 0x03;
|
||||
|
||||
if (token == PID_IN) {
|
||||
if (ep_idx == 0x00) {
|
||||
if (g_ch32_usbhs_udc.in_ep[ep_idx].xfer_len >= g_ch32_usbhs_udc.in_ep[ep_idx].ep_mps) {
|
||||
g_ch32_usbhs_udc.in_ep[ep_idx].xfer_len -= g_ch32_usbhs_udc.in_ep[ep_idx].ep_mps;
|
||||
g_ch32_usbhs_udc.in_ep[ep_idx].actual_xfer_len += g_ch32_usbhs_udc.in_ep[ep_idx].ep_mps;
|
||||
ep0_tx_data_toggle ^= 1;
|
||||
} else {
|
||||
g_ch32_usbhs_udc.in_ep[ep_idx].actual_xfer_len += g_ch32_usbhs_udc.in_ep[ep_idx].xfer_len;
|
||||
g_ch32_usbhs_udc.in_ep[ep_idx].xfer_len = 0;
|
||||
ep0_tx_data_toggle = true;
|
||||
}
|
||||
|
||||
usbd_event_ep_in_complete_handler(0, ep_idx | 0x80, g_ch32_usbhs_udc.in_ep[ep_idx].actual_xfer_len);
|
||||
|
||||
if (g_ch32_usbhs_udc.dev_addr > 0) {
|
||||
USBHS_DEVICE->DEV_AD = g_ch32_usbhs_udc.dev_addr & 0xff;
|
||||
g_ch32_usbhs_udc.dev_addr = 0;
|
||||
}
|
||||
|
||||
if (g_ch32_usbhs_udc.setup.wLength && ((g_ch32_usbhs_udc.setup.bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_OUT)) {
|
||||
/* In status, start reading setup */
|
||||
USBHS_DEVICE->UEP0_DMA = (uint32_t)&g_ch32_usbhs_udc.setup;
|
||||
USBHS_DEVICE->UEP0_RX_CTRL = USBHS_EP_R_RES_ACK;
|
||||
ep0_tx_data_toggle = true;
|
||||
|
||||
} else if (g_ch32_usbhs_udc.setup.wLength == 0) {
|
||||
/* In status, start reading setup */
|
||||
USBHS_DEVICE->UEP0_DMA = (uint32_t)&g_ch32_usbhs_udc.setup;
|
||||
USBHS_DEVICE->UEP0_RX_CTRL = USBHS_EP_R_RES_ACK;
|
||||
ep0_tx_data_toggle = true;
|
||||
}
|
||||
} else {
|
||||
USB_SET_TX_CTRL(ep_idx, (USB_GET_TX_CTRL(ep_idx) & ~(USBHS_EP_T_RES_MASK | USBHS_EP_T_TOG_MASK)) | USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0);
|
||||
|
||||
if (g_ch32_usbhs_udc.in_ep[ep_idx].xfer_len > g_ch32_usbhs_udc.in_ep[ep_idx].ep_mps) {
|
||||
g_ch32_usbhs_udc.in_ep[ep_idx].xfer_buf += g_ch32_usbhs_udc.in_ep[ep_idx].ep_mps;
|
||||
g_ch32_usbhs_udc.in_ep[ep_idx].xfer_len -= g_ch32_usbhs_udc.in_ep[ep_idx].ep_mps;
|
||||
g_ch32_usbhs_udc.in_ep[ep_idx].actual_xfer_len += g_ch32_usbhs_udc.in_ep[ep_idx].ep_mps;
|
||||
epx_tx_data_toggle[ep_idx - 1] ^= 1;
|
||||
|
||||
write_count = MIN(g_ch32_usbhs_udc.in_ep[ep_idx].xfer_len, g_ch32_usbhs_udc.in_ep[ep_idx].ep_mps);
|
||||
USB_SET_TX_LEN(ep_idx, write_count);
|
||||
USB_SET_TX_DMA(ep_idx, (uint32_t)g_ch32_usbhs_udc.in_ep[ep_idx].xfer_buf);
|
||||
|
||||
uint32_t tmp = USB_GET_TX_CTRL(ep_idx);
|
||||
tmp &= ~(USBHS_EP_T_RES_MASK | USBHS_EP_T_TOG_MASK);
|
||||
tmp |= USBHS_EP_T_RES_ACK;
|
||||
tmp |= (epx_tx_data_toggle[ep_idx - 1] ? USBHS_EP_T_TOG_1 : USBHS_EP_T_TOG_0);
|
||||
USB_SET_TX_CTRL(ep_idx, tmp);
|
||||
} else {
|
||||
g_ch32_usbhs_udc.in_ep[ep_idx].actual_xfer_len += g_ch32_usbhs_udc.in_ep[ep_idx].xfer_len;
|
||||
g_ch32_usbhs_udc.in_ep[ep_idx].xfer_len = 0;
|
||||
epx_tx_data_toggle[ep_idx - 1] ^= 1;
|
||||
usbd_event_ep_in_complete_handler(0, ep_idx | 0x80, g_ch32_usbhs_udc.in_ep[ep_idx].actual_xfer_len);
|
||||
}
|
||||
}
|
||||
} else if (token == PID_OUT) {
|
||||
if (ep_idx == 0x00) {
|
||||
read_count = USBHS_DEVICE->RX_LEN;
|
||||
|
||||
g_ch32_usbhs_udc.out_ep[ep_idx].actual_xfer_len += read_count;
|
||||
g_ch32_usbhs_udc.out_ep[ep_idx].xfer_len -= read_count;
|
||||
|
||||
usbd_event_ep_out_complete_handler(0, 0x00, g_ch32_usbhs_udc.out_ep[ep_idx].actual_xfer_len);
|
||||
|
||||
if (read_count == 0) {
|
||||
/* Out status, start reading setup */
|
||||
USBHS_DEVICE->UEP0_DMA = (uint32_t)&g_ch32_usbhs_udc.setup;
|
||||
USBHS_DEVICE->UEP0_RX_CTRL = USBHS_EP_R_RES_ACK;
|
||||
ep0_rx_data_toggle = true;
|
||||
ep0_tx_data_toggle = true;
|
||||
} else {
|
||||
ep0_rx_data_toggle ^= 1;
|
||||
}
|
||||
} else {
|
||||
if (USBHS_DEVICE->INT_ST & USBHS_DEV_UIS_TOG_OK) {
|
||||
USB_SET_RX_CTRL(ep_idx, (USB_GET_RX_CTRL(ep_idx) & ~USBHS_EP_R_RES_MASK) | USBHS_EP_R_RES_NAK);
|
||||
read_count = USBHS_DEVICE->RX_LEN;
|
||||
|
||||
g_ch32_usbhs_udc.out_ep[ep_idx].xfer_buf += read_count;
|
||||
g_ch32_usbhs_udc.out_ep[ep_idx].actual_xfer_len += read_count;
|
||||
g_ch32_usbhs_udc.out_ep[ep_idx].xfer_len -= read_count;
|
||||
|
||||
if ((read_count < g_ch32_usbhs_udc.out_ep[ep_idx].ep_mps) || (g_ch32_usbhs_udc.out_ep[ep_idx].xfer_len == 0)) {
|
||||
usbd_event_ep_out_complete_handler(0, ep_idx, g_ch32_usbhs_udc.out_ep[ep_idx].actual_xfer_len);
|
||||
} else {
|
||||
USB_SET_RX_DMA(ep_idx, (uint32_t)g_ch32_usbhs_udc.out_ep[ep_idx].xfer_buf);
|
||||
USB_SET_RX_CTRL(ep_idx, (USB_GET_RX_CTRL(ep_idx) & ~USBHS_EP_R_RES_MASK) | USBHS_EP_R_RES_ACK);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
USBHS_DEVICE->INT_FG = USBHS_TRANSFER_FLAG;
|
||||
} else if (intflag & USBHS_SETUP_FLAG) {
|
||||
usbd_event_ep0_setup_complete_handler(0, (uint8_t *)&g_ch32_usbhs_udc.setup);
|
||||
USBHS_DEVICE->INT_FG = USBHS_SETUP_FLAG;
|
||||
} else if (intflag & USBHS_DETECT_FLAG) {
|
||||
USBHS_DEVICE->ENDP_CONFIG = USBHS_EP0_T_EN | USBHS_EP0_R_EN;
|
||||
|
||||
USBHS_DEVICE->UEP0_TX_LEN = 0;
|
||||
USBHS_DEVICE->UEP0_TX_CTRL = USBHS_EP_T_RES_NAK;
|
||||
|
||||
ep0_tx_data_toggle = true;
|
||||
ep0_rx_data_toggle = true;
|
||||
|
||||
for (uint8_t ep_idx = 1; ep_idx < USB_NUM_BIDIR_ENDPOINTS; ep_idx++) {
|
||||
USB_SET_TX_LEN(ep_idx, 0);
|
||||
USB_SET_TX_CTRL(ep_idx, USBHS_EP_T_AUTOTOG | USBHS_EP_T_RES_NAK); // autotog does not work
|
||||
USB_SET_RX_CTRL(ep_idx, USBHS_EP_R_AUTOTOG | USBHS_EP_R_RES_NAK);
|
||||
epx_tx_data_toggle[ep_idx - 1] = false;
|
||||
}
|
||||
|
||||
memset(&g_ch32_usbhs_udc, 0, sizeof(struct ch32_usbhs_udc));
|
||||
usbd_event_reset_handler(0);
|
||||
USBHS_DEVICE->UEP0_DMA = (uint32_t)&g_ch32_usbhs_udc.setup;
|
||||
USBHS_DEVICE->UEP0_RX_CTRL = USBHS_EP_R_RES_ACK;
|
||||
USBHS_DEVICE->INT_FG = USBHS_DETECT_FLAG;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user