This commit is contained in:
2024-08-05 20:57:09 +08:00
commit 46d9ee7795
3020 changed files with 1725767 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
# Note
## Support Chip List
- CH32V30x

View File

@@ -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

View File

@@ -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 锟剿点被锟斤拷锟矫拷未锟矫碉拷UEPn_*_DMA锟斤拷锟斤拷锟斤拷锟斤拷
// 1 0 0 锟斤拷锟秸拷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

View File

@@ -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;
}
}

View File

@@ -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;
}
}