#ifndef _HSUSB_H #define _HSUSB_H #include #include "ch32fun.h" #include "usb_defines.h" #include "usb_config.h" #if !defined(CH584_CH585) && !defined(CH32V205) && !defined(CH32H4xx) && !defined(CH32V30x) && !defined(CH565_CH569) #error "This lib doesn't work on this MCU" #endif #if defined(CH32V30x) || defined(CH565_CH569) #define USBHS_IMPL 1 // #elif defined(CH584_CH585) || defined(CH32V205) || defined(CH32H4xx) #else #define USBHS_IMPL 2 #endif #ifndef __HIGH_CODE #define __HIGH_CODE #endif #ifndef USBHS_BASE #if defined(CH32V30x) || defined(CH32V205) #define USBHS_BASE (0x40023400) #elif defined(CH32H4xx) #define USBHS_BASE (0x40030000) #else #define USBHS_BASE (0x40009000) #endif #endif #if (USBHS_IMPL==1) #if (FUNCONF_USE_HSI) && !defined(FUSB_SOF_HSITRIM) #define FUSB_SOF_HSITRIM 1 #endif #define TICKS_PER_HSITRIM (FUNCONF_PLL_MULTIPLIER * 20000 * 125) / 1000000 // SOF is sent every 125uS, each HSITRIM changes HSI by 20kHz typedef struct { __IO uint8_t BASE_CTRL; __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 UEP_CONFIG; __IO uint32_t UEP_TYPE; __IO uint32_t UEP_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_T_LEN; __IO uint8_t UEP0_TX_CTRL; __IO uint8_t UEP0_RX_CTRL; __IO uint16_t UEP1_T_LEN; __IO uint8_t UEP1_TX_CTRL; __IO uint8_t UEP1_RX_CTRL; __IO uint16_t UEP2_T_LEN; __IO uint8_t UEP2_TX_CTRL; __IO uint8_t UEP2_RX_CTRL; __IO uint16_t UEP3_T_LEN; __IO uint8_t UEP3_TX_CTRL; __IO uint8_t UEP3_RX_CTRL; __IO uint16_t UEP4_T_LEN; __IO uint8_t UEP4_TX_CTRL; __IO uint8_t UEP4_RX_CTRL; __IO uint16_t UEP5_T_LEN; __IO uint8_t UEP5_TX_CTRL; __IO uint8_t UEP5_RX_CTRL; __IO uint16_t UEP6_T_LEN; __IO uint8_t UEP6_TX_CTRL; __IO uint8_t UEP6_RX_CTRL; __IO uint16_t UEP7_T_LEN; __IO uint8_t UEP7_TX_CTRL; __IO uint8_t UEP7_RX_CTRL; __IO uint16_t UEP8_T_LEN; __IO uint8_t UEP8_TX_CTRL; __IO uint8_t UEP8_RX_CTRL; __IO uint16_t UEP9_T_LEN; __IO uint8_t UEP9_TX_CTRL; __IO uint8_t UEP9_RX_CTRL; __IO uint16_t UEP10_T_LEN; __IO uint8_t UEP10_TX_CTRL; __IO uint8_t UEP10_RX_CTRL; __IO uint16_t UEP11_T_LEN; __IO uint8_t UEP11_TX_CTRL; __IO uint8_t UEP11_RX_CTRL; __IO uint16_t UEP12_T_LEN; __IO uint8_t UEP12_TX_CTRL; __IO uint8_t UEP12_RX_CTRL; __IO uint16_t UEP13_T_LEN; __IO uint8_t UEP13_TX_CTRL; __IO uint8_t UEP13_RX_CTRL; __IO uint16_t UEP14_T_LEN; __IO uint8_t UEP14_TX_CTRL; __IO uint8_t UEP14_RX_CTRL; __IO uint16_t UEP15_T_LEN; __IO uint8_t UEP15_TX_CTRL; __IO uint8_t UEP15_RX_CTRL; } USBHS_TypeDef; #define USBHS_CHECK_NAK_RX (USBHS->INT_ST & 0x80) #define CRB_U_IS_NAK (1<<7) #define CTOG_MATCH_SYNC (1<<6) #define CRB_UIF_SETUP_ACT (1<<5) // CRB_U_SIE_FREE on USBFS #define CRB_UIF_FIFO_OV (1<<4) #define CRB_UIF_HST_SOF (1<<3) #define CRB_UIF_SUSPEND (1<<2) #define CRB_UIF_TRANSFER (1<<1) #define CRB_UIF_BUS_RST (1<<0) #define CSETUP_ACT (1<<15) #define CRB_UIS_TOG_OK (1<<14) #define CMASK_UIS_TOKEN (3<<12) #define CMASK_UIS_ENDP (0xf<<8) #define CUIS_TOKEN_OUT 0x0 #define CUIS_TOKEN_SOF 0x1 #define CUIS_TOKEN_IN 0x2 #define CUIS_TOKEN_SETUP 0x3 #define UEP_TX_EN(n) USBHS->UEP_CONFIG |= ((uint32_t)(1<UEP_CONFIG |= ((uint32_t)(1<<(n+16))) #define USBHS_DONE_TX(n) #define USBHS_DONE_RX(n) #elif (USBHS_IMPL==2) typedef struct { __IO uint8_t BASE_CTRL; __IO uint8_t BASE_MODE; __IO uint8_t INT_EN; __IO uint8_t DEV_AD; __IO uint8_t WAKE_CTRL; __IO uint8_t TEST_MODE; __IO uint16_t LPM_DATA; __IO uint8_t INT_FG; // "Combined" register in some situations. (ST_FG) __IO uint8_t INT_ST; __IO uint8_t MIS_ST; __IO uint16_t FRAME_NO; __IO uint16_t BUS; __IO uint16_t UEP_TX_EN; __IO uint16_t UEP_RX_EN; __IO uint16_t UEP_T_TOG_AUTO; __IO uint16_t UEP_R_TOG_AUTO; __IO uint8_t UEP_T_BURST; __IO uint8_t UEP_T_BURST_MODE; __IO uint8_t UEP_R_BURST; __IO uint8_t UEP_R_RES_MODE; __IO uint32_t UEP_AF_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 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 UEP0_MAX_LEN; __IO uint32_t UEP1_MAX_LEN; __IO uint32_t UEP2_MAX_LEN; __IO uint32_t UEP3_MAX_LEN; __IO uint32_t UEP4_MAX_LEN; __IO uint32_t UEP5_MAX_LEN; __IO uint32_t UEP6_MAX_LEN; __IO uint32_t UEP7_MAX_LEN; __IO uint16_t UEP0_RX_LEN; __IO uint16_t reserved; __IO uint16_t UEP1_RX_LEN; __IO uint16_t UEP1_R_SIZE; __IO uint16_t UEP2_RX_LEN; __IO uint16_t UEP2_R_SIZE; __IO uint16_t UEP3_RX_LEN; __IO uint16_t UEP3_R_SIZE; __IO uint16_t UEP4_RX_LEN; __IO uint16_t UEP4_R_SIZE; __IO uint16_t UEP5_RX_LEN; __IO uint16_t UEP5_R_SIZE; __IO uint16_t UEP6_RX_LEN; __IO uint16_t UEP6_R_SIZE; __IO uint16_t UEP7_RX_LEN; __IO uint16_t UEP7_R_SIZE; __IO uint16_t UEP0_T_LEN; __IO uint8_t UEP0_TX_CTRL; __IO uint8_t UEP0_RX_CTRL; __IO uint16_t UEP1_T_LEN; __IO uint8_t UEP1_TX_CTRL; __IO uint8_t UEP1_RX_CTRL; __IO uint16_t UEP2_T_LEN; __IO uint8_t UEP2_TX_CTRL; __IO uint8_t UEP2_RX_CTRL; __IO uint16_t UEP3_T_LEN; __IO uint8_t UEP3_TX_CTRL; __IO uint8_t UEP3_RX_CTRL; __IO uint16_t UEP4_T_LEN; __IO uint8_t UEP4_TX_CTRL; __IO uint8_t UEP4_RX_CTRL; __IO uint16_t UEP5_T_LEN; __IO uint8_t UEP5_TX_CTRL; __IO uint8_t UEP5_RX_CTRL; __IO uint16_t UEP6_T_LEN; __IO uint8_t UEP6_TX_CTRL; __IO uint8_t UEP6_RX_CTRL; __IO uint16_t UEP7_T_LEN; __IO uint8_t UEP7_TX_CTRL; __IO uint8_t UEP7_RX_CTRL; __IO uint16_t UEP_T_ISO; __IO uint16_t UEP_R_ISO; } USBHS_TypeDef; #define USBHS_CHECK_NAK_RX (USBHS->UEP0_RX_CTRL & (1<<6)) #define UEP_RX_LEN(n) (((volatile uint16_t*)&USBHS->UEP1_RX_LEN)[(n-1)*2]) #define UEP_TX_EN(n) USBHS->UEP_TX_EN |= ((uint16_t)(1<UEP_RX_EN |= ((uint16_t)(1<INT_FG + USBHS->INT_ST #define CRB_UIF_FIFO_OV (1<<7) #define CRB_UIF_LINK_RDY (1<<6) #define CRB_UIF_RX_SOF (1<<5) #define CRB_UIF_TRANSFER (1<<4) #define CRB_UIF_LPM_ACT (1<<3) #define CRB_UIF_BUS_SLEEP (1<<2) #define CRB_UIF_SUSPEND (1<<1) #define CRB_UIF_BUS_RST (1<<0) #define CMASK_UIS_TOKEN (1<<12) #define CMASK_UIS_ENDP (7<<8) #define CUIS_TOKEN_OUT 0x0 #define CUIS_TOKEN_IN 0x1 #define USBHS_DONE_TX(n) UEP_CTRL_TX(n) &= ~(USBHS_UEP_T_DONE) #define USBHS_DONE_RX(n) UEP_CTRL_RX(n) &= ~(USBHS_UEP_R_DONE) #endif #define USBHS_SPEED_TYPE_MASK ((uint8_t)(0x03)) #define USBHS_DEF_UEP_IN 0x80 #define USBHS_DEF_UEP_OUT 0x00 #define USBHS_DEF_UEP_BUSY 0x01 #define USBHS_DEF_UEP_FREE 0x00 #define USBHS_NUM_EP 8 #define USBHS_DEF_UEP0 0 #define USBHS_DEF_UEP1 1 #define USBHS_DEF_UEP2 2 #define USBHS_DEF_UEP3 3 #define USBHS_DEF_UEP4 4 #define USBHS_DEF_UEP5 5 #define USBHS_DEF_UEP6 6 #define USBHS_DEF_UEP7 7 #define USBHS_DEF_UEP8 8 #define USBHS_DEF_UEP9 9 #define USBHS_DEF_UEP10 10 #define USBHS_DEF_UEP11 11 #define USBHS_DEF_UEP12 12 #define USBHS_DEF_UEP13 13 #define USBHS_DEF_UEP14 14 #define USBHS_DEF_UEP15 15 #define USBHS_DEF_UEP0_SIZE 64 #ifndef FUSB_EP_SIZE #define USBHS_UEP_SIZE 64 #else #define USBHS_UEP_SIZE FUSB_EP_SIZE #endif #define UEP_CTRL_LEN(n) (((volatile uint16_t*)&USBHS->UEP0_T_LEN)[n*2]) #define UEP_CTRL_TX(n) (((volatile uint8_t*)&USBHS->UEP0_TX_CTRL)[n*4]) #define UEP_CTRL_RX(n) (((volatile uint8_t*)&USBHS->UEP0_RX_CTRL)[n*4]) #define UEP_DMA_RX(n) (((volatile uint32_t*)&USBHS->UEP0_DMA)[n]) #define UEP_DMA_TX(n) (((volatile uint32_t*)&USBHS->UEP1_TX_DMA)[n-1]) #define USBHS ((USBHS_TypeDef *)USBHS_BASE) extern uint32_t USBDEBUG0, USBDEBUG1, USBDEBUG2; struct _USBState; // Provided functions: int USBHSSetup(); static inline int USBHS_SendEndpointNEW( int endp, const uint8_t* data, int len, int copy); static inline uint8_t * USBHS_GetEPBufferIfAvailable( int endp ); static inline int USBHS_SendEndpoint( int endp, int len ); static inline int USBHS_SendACK( int endp, int tx ); static inline int USBHS_SendNAK( int endp, int tx ); // Implement the following: #if FUSB_HID_USER_REPORTS __HIGH_CODE int HandleHidUserGetReportSetup( struct _USBState * ctx, tusb_control_request_t * req ); __HIGH_CODE int HandleHidUserSetReportSetup( struct _USBState * ctx, tusb_control_request_t * req ); void HandleHidUserReportDataOut( struct _USBState * ctx, uint8_t * data, int len ); int HandleHidUserReportDataIn( struct _USBState * ctx, uint8_t * data, int len ); void HandleHidUserReportOutComplete( struct _USBState * ctx ); #endif #if FUSB_USER_HANDLERS __HIGH_CODE int HandleInRequest( struct _USBState * ctx, int endp, uint8_t * data, int len ); __HIGH_CODE void HandleDataOut( struct _USBState * ctx, int endp, uint8_t * data, int len ); __HIGH_CODE int HandleSetupCustom( struct _USBState * ctx, int setup_code); #endif #if FUSB_OUT_FLOW_CONTROL > 0 void USBHS_RxReady(int endp); #endif typedef enum { USB_SPEED_FULL = 0, USB_SPEED_HIGH = 1, USB_SPEED_LOW = 2, } USB_SPEED_t; typedef enum { USBHS_EP_OFF = 0, USBHS_EP_RX = -1, USBHS_EP_TX = 1, } USBHS_EP_mode; #ifndef FUSB_EP1_MODE #define FUSB_EP1_MODE 0 #endif #ifndef FUSB_EP2_MODE #define FUSB_EP2_MODE 0 #endif #ifndef FUSB_EP3_MODE #define FUSB_EP3_MODE 0 #endif #ifndef FUSB_EP4_MODE #define FUSB_EP4_MODE 0 #endif #ifndef FUSB_EP5_MODE #define FUSB_EP5_MODE 0 #endif #ifndef FUSB_EP6_MODE #define FUSB_EP6_MODE 0 #endif #ifndef FUSB_EP7_MODE #define FUSB_EP7_MODE 0 #endif struct _USBState { __attribute__ ((aligned(4))) uint8_t CTRL0BUFF[64]; __attribute__ ((aligned(4))) uint8_t ENDPOINTS[FUSB_CONFIG_EPS-1][FUSB_EP_SIZE]; // Setup Request uint8_t USBHS_SetupReqCode; uint8_t USBHS_SetupReqType; uint16_t USBHS_SetupReqLen; // Used for tracking place along send. uint32_t USBHS_IndexValue; // USB Device Status uint8_t USBHS_DevConfig; uint8_t USBHS_DevAddr; uint8_t USBHS_DevSleepStatus; uint8_t USBHS_DevEnumStatus; uint8_t* pCtrlPayloadPtr; USBHS_EP_mode endpoint_mode[FUSB_CONFIG_EPS+1]; // IN -1, OUT 1, OFF 0 #define pUSBHS_SetupReqPak ((tusb_control_request_t*)USBHSCTX.CTRL0BUFF) #if FUSB_HID_INTERFACES > 0 uint8_t USBHS_HidIdle[FUSB_HID_INTERFACES]; uint8_t USBHS_HidProtocol[FUSB_HID_INTERFACES]; #endif volatile uint8_t USBHS_Endp_Busy[FUSB_CONFIG_EPS]; volatile uint8_t USBHS_errata_dont_send_endpoint_in_window; volatile uint64_t USBHS_sof_timestamp; }; extern struct _USBState USBHSCTX; #include "hsusb.c" #endif