Add usbd cdc

This commit is contained in:
songyanguang 2025-08-13 20:00:06 +08:00
parent b175f77b10
commit 0da14e6546
18 changed files with 2684 additions and 1 deletions

View File

@ -17,3 +17,7 @@ export MCU = CH569W
ifeq ($(CONFIG_BSP_USING_SERDES), y)
export LINK_BOARD += $(KERNEL_ROOT)/board/ch569w/third_party_driver/serdes/libSERDES.a
endif
ifeq ($(CONFIG_BSP_USING_USBD), y)
export LINK_BOARD += $(KERNEL_ROOT)/board/ch569w/third_party_driver/usb/usbd/simulate_cdc/USB30/libCH56x_USB30_device_lib.a
endif

View File

@ -20,6 +20,13 @@ menuconfig BSP_USING_SERDES
source "$BSP_DIR/third_party_driver/serdes/Kconfig"
endif
menuconfig BSP_USING_USB
bool "Using usb device"
default y
if BSP_USING_USB
source "$BSP_DIR/third_party_driver/usb/Kconfig"
endif
menuconfig BSP_USING_WDT
bool "Using watchdog timer device"
default n

View File

@ -10,10 +10,14 @@ ifeq ($(CONFIG_BSP_USING_SPI),y)
SRC_DIR += spi
endif
ifeq ($(CONFIG_BSP_USING_SPI),y)
ifeq ($(CONFIG_BSP_USING_SERDES),y)
SRC_DIR += serdes
endif
ifeq ($(CONFIG_BSP_USING_USB),y)
SRC_DIR += usb
endif
ifeq ($(CONFIG_BSP_USING_WDT),y)
SRC_DIR += wdt
endif

View File

@ -0,0 +1,56 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_usb20.h
* Author : WCH
* Version : V1.2
* Date : 2024/07/10
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef USB20_CH56X_USB20_H_
#define USB20_CH56X_USB20_H_
#include "CH56x_common.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Global define */
#define U20_MAXPACKET_LEN 512
#define U20_UEP0_MAXSIZE 64
#define PID_OUT 0
#define PID_SOF 1
#define PID_IN 2
/* Global Variable */
typedef struct __attribute__((packed))
{
UINT8 dev_speed;
UINT8 dev_addr;
UINT8 dev_config_value;
UINT8 dev_sleep_status;
UINT8 dev_enum_status;
}DevInfo_Typedef;
extern const UINT8 hs_device_descriptor[];
extern const UINT8 hs_config_descriptor[];
extern const UINT8 hs_string_descriptor0[];
extern const UINT8 hs_string_descriptor1[];
extern const UINT8 hs_string_descriptor2[];
extern const UINT8 hs_bos_descriptor[];
/* Function declaration */
void USB20_Device_Init ( FunctionalState sta );
UINT16 U20_NonStandard_Request_Deal();
UINT16 U20_Standard_Request_Deal();
UINT16 U20_Endp0_IN_Callback(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,61 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_usb30.h
* Author : WCH
* Version : V1.2
* Date : 2024/07/10
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef USB30_CH56X_USB30_H_
#define USB30_CH56X_USB30_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "CH56x_common.h"
/* Global define */
#define endpoint_1_OUT_burst_level 1
#define endpoint_1_IN_burst_level 1
#define endpoint_2_OUT_burst_level 1
#define endpoint_2_IN_burst_level 1
#define SIZE_DEVICE_DESC 18
#define SIZE_CONFIG_DESC 85
#define SIZE_STRING_LANGID 4
#define SIZE_STRING_VENDOR 8
#define SIZE_STRING_PRODUCT 38
#define SIZE_STRING_SERIAL 22
#define SIZE_BOS_DESC 22
#define SIZE_STRING_OS 18
#define LINK_STA_1 (1<<0)
#define LINK_STA_3 (1<<2)
/* Global Variable */
extern __attribute__ ((aligned(16))) UINT8 endp0RTbuff[512] __attribute__((section(".DMADATA")));
extern __attribute__ ((aligned(16))) UINT8 endp1RTbuff[4096] __attribute__((section(".DMADATA")));
extern __attribute__ ((aligned(16))) UINT8 endp2Rxbuff[4096] __attribute__((section(".DMADATA")));
extern __attribute__ ((aligned(16))) UINT8 endp2Txbuff[4096] __attribute__((section(".DMADATA")));
extern UINT8V Link_Sta;
/* Function declaration */
void USB30D_init(FunctionalState sta);
void TMR0_IRQHandler() __attribute__((interrupt()));
void LINK_IRQHandler() __attribute__((interrupt()));
void USBSS_IRQHandler(void) __attribute__((interrupt())); //USB3.0 interrupt service
#ifdef __cplusplus
}
#endif
#endif /* USER_USB30_DESC_H_ */

View File

@ -0,0 +1,482 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_usb30_lib.h
* Author : WCH
* Version : V1.2
* Date : 2024/07/10
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef USB30_CH56X_USB30_LIB_H_
#define USB30_CH56X_USB30_LIB_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "CH56x_common.h"
// link CFG
#define TERM_EN (1<<1)
#define PIPE_RESET (1<<3)
#define LFPS_RX_PD (1<<5)
#define CFG_EQ_EN (1<<6)
#define TX_SWING (1<<7)
#define DEEMPH_CFG (1<<8)
#define POWER_MODE_0 ((UINT32)0x00000000)
#define POWER_MODE_1 ((UINT32)0x00000001)
#define POWER_MODE_2 ((UINT32)0x00000002)
#define POWER_MODE_3 ((UINT32)0x00000003)
#define LINK_PRESENT (1<<0)
#define RX_WARM_RESET ((UINT32)1<<1)
#define LINK_TXEQ (1<<6)
#define GO_DISABLED (1<<4)
#define POLLING_EN (1<<12)
#define TX_HOT_RESET ((UINT32)1<<16)
#define RX_HOT_RESET ((UINT32)1<<24)
#define TX_WARM_RESET ((UINT32)1<<8)
#define TX_Ux_EXIT ((UINT32)1<<9)
// link int flag
#define LINK_RDY_FLAG (1<<0)
#define LINK_RECOV_FLAG (1<<1)
#define LINK_INACT_FLAG (1<<2)
#define LINK_DISABLE_FLAG (1<<3)
#define LINK_GO_U3_FLAG (1<<4)
#define LINK_GO_U2_FLAG (1<<5)
#define LINK_GO_U1_FLAG (1<<6)
#define LINK_GO_U0_FLAG (1<<7)
#define LINK_U3_WAKE_FLAG (1<<8)
#define LINK_Ux_REJECT_FLAG (1<<9)
#define TERM_PRESENT_FLAG (1<<10)
#define LINK_TXEQ_FLAG (1<<11)
#define LINK_Ux_EXIT_FLAG (1<<12)
#define WARM_RESET_FLAG (1<<13)
#define U3_WAKEUP_FLAG (1<<14)
#define HOT_RESET_FLAG (1<<15)
#define LINK_RX_DET_FLAG (1<<20)
#define EP0_R_EN (1<<0)
#define EP1_R_EN (1<<1)
#define EP2_R_EN (1<<2)
#define EP3_R_EN (1<<3)
#define EP4_R_EN (1<<4)
#define EP5_R_EN (1<<5)
#define EP6_R_EN (1<<6)
#define EP7_R_EN (1<<7)
#define EP0_T_EN (1<<8)
#define EP1_T_EN (1<<9)
#define EP2_T_EN (1<<10)
#define EP3_T_EN (1<<11)
#define EP4_T_EN (1<<12)
#define EP5_T_EN (1<<13)
#define EP6_T_EN (1<<14)
#define EP7_T_EN (1<<15)
#define USB_FORCE_RST (1<<2)
#define USB_ALL_CLR (1<<1)
// LMP
#define LMP_HP (0)
#define LMP_SUBTYPE_MASK (0xf<<5)
#define SET_LINK_FUNC (0x1<<5)
#define U2_INACT_TOUT (0x2<<5)
#define VENDOR_TEST (0x3<<5)
#define PORT_CAP (0x4<<5)
#define PORT_CFG (0x5<<5)
#define PORT_CFG_RES (0x6<<5)
#define LINK_SPEED (1<<9)
#define NUM_HP_BUF (4<<0)
#define DOWN_STREAM (1<<16)
#define UP_STREAM (2<<16)
#define TIE_BRK (1<<20)
/**********device status***********/
typedef enum _DEVICE_STATE
{
UNCONNECTED,
ATTACHED,
POWERED,
SUSPENDED,
ADDRESSED,
CONFIGURED
} DEVICE_STATE;
/**********standard request command***********/
typedef struct __PACKED
{
UINT8 bRequestType;
UINT8 bRequest;
UINT8 wValueL;
UINT8 wValueH;
UINT8 wIndexL;
UINT8 wIndexH;
UINT16 wLength;
} *PUSB_SETUP;
#define UsbSetupBuf ((PUSB_SETUP)endp0RTbuff)//endpoint 0
#define ENDP0_MAXPACK 512
// status response
#define NRDY 0
#define ACK 0x01
#define STALL 0x02
#define INVALID 0x03
// number of NUMP
#define NUMP_0 0x00
#define NUMP_1 0x01
#define NUMP_2 0x02
#define NUMP_3 0x03
#define NUMP_4 0x04
#define NUMP_5 0x05
#define NUMP_6 0x06
/* USB endpoint direction */
#define OUT 0x00
#define IN 0x80
/* USB endpoint serial number */
#define ENDP_0 0x00
#define ENDP_1 0x01
#define ENDP_2 0x02
#define ENDP_3 0x03
#define ENDP_4 0x04
#define ENDP_5 0x05
#define ENDP_6 0x06
#define ENDP_7 0x07
#define USB_DESCR_TYP_BOS 0x0f
#define USB_DESCR_UNSUPPORTED 0xffff
#define INVALID_REQ_CODE 0xFF
/* string descriptor type */
#ifndef USB_DESCR_STRING
#define USB_DESCR_LANGID_STRING 0x00
#define USB_DESCR_VENDOR_STRING 0x01
#define USB_DESCR_PRODUCT_STRING 0x02
#define USB_DESCR_SERIAL_STRING 0x03
#define USB_DESCR_OS_STRING 0xee
#endif
extern void USB30_Device_forceclr();
/*******************************************************************************
* @fn USB30_Device_Init
*
* @brief USB3.0 Device initialization
*
* @return None
*/
extern UINT8 USB30_Device_Init(void);
/*******************************************************************************
* @fn USB30_Lib_Getversion
*
* @brief USB3.0 Device Lib initialization
*
* @return None
*/
extern UINT8 USB30_Lib_Getversion(void);
/*******************************************************************************
* @fn USB30_ISO_Setendp
*
* @brief Configure synchronization endpoint
*
* @return None
*/
extern void USB30_ISO_Setendp(UINT8 num,FunctionalState Status );
/*******************************************************************************
* @fn USB30_ISO_Setdelay( UINT32 dly )
*
* @brief Set synchronization delay time
*
* @param dly - delay time
*
* @return None
*/
extern void USB30_ISO_Setdelay( UINT32 dly );
/*******************************************************************************
* @fn USB30_ITP_Enable
*
* @brief USB ITP enable
*
* @param Status - enable/disable
*
* @return None
*/
extern void USB30_ITP_Enable(FunctionalState Status);
/*******************************************************************************
* @fn USB30_OUT_Status
*
* @brief Get the length of endpoint received data
*
* @param endp - Endpoint number
* nump - The remaining number of packets that can be received by the endpoint
* len - The length of data received by the endpoint. For burst transmission,
* it indicates the length of the last packet received by the endpoint.
* status - Indicates whether the host still has data packets to be distributed,
* 1 - the end of the burst received non-full packets,
* 0 - the host still has data packets to be distributed.
*
* @return None
*/
extern void USB30_OUT_Status(UINT8 endp,UINT8 *nump,UINT16 *len,UINT8 *status);
/*******************************************************************************
* @fn USB30_OUT_Set
*
* @brief Endpoint receive settings
*
* @param endp - Set endpoint number
* nump - The remaining number of packets that can be received by the endpoint
* status - Endpoint Status :0-NRDY,1-ACK,2-STALL
*
* @return None
*/
extern void USB30_OUT_Set(UINT8 endp,UINT8 status,UINT8 nump);
/*******************************************************************************
* @fn USB30_OUT_ClearIT
*
* @brief Clear the OUT transaction completion interrupt, and only keep the package serial number
*
* @param endp - Set endpoint number
*
* @return None
*/
extern void USB30_OUT_ClearIT(UINT8 endp);
/*******************************************************************************
* @fn USB30_OUT_ClearPendingIT
*
* @brief Clear the OUT transaction completion interrupt, and keep other endpoint configurations
*
* @param endp - Set endpoint number
*
* @return None
*/
extern void USB30_OUT_ClearPendingIT(UINT8 endp);
/*******************************************************************************
* @fn USB30_OUT_ITflag
*
* @brief Get the OUT transaction completion interrupt flag
*
* @param endp - Set endpoint number
*
* @return 1 - interrupt 0 - non-interrupt
*/
extern UINT8 USB30_OUT_ITflag(UINT8 endp);
/*******************************************************************************
* @fn USB30_IN_Set
*
* @brief Endpoint sending settings
*
* @param endp - endpoint number
* lpf - end of burst: 1-enable 0-disable
* nump - The number of packets that the endpoint can send
* status - endpoint status: 0-NRDY,1-ACK,2-STALL
* TxLen - The data length of the last packet sent by the endpoint
*
* @return None
*/
extern void USB30_IN_Set(UINT8 endp,FunctionalState lpf,UINT8 status,UINT8 nump,UINT16 TxLen);
/*******************************************************************************
* @fn USB30_IN_ClearPendingIT
*
* @brief Clear the IN transaction completion interrupt and keep the other configurations of the endpoint
*
* @param endp - endpoint number
*
* @return None
*/
extern void USB30_IN_ClearPendingIT(UINT8 endp);
/*******************************************************************************
* @fn USB30_IN_ClearIT
*
* @brief Clear the IN transaction interrupt and the remaining status of the endpoint,
* and only retain the packet serial number.
*
* @param endp - endpoint number
*
* @return None
*/
extern void USB30_IN_ClearIT(UINT8 endp);
/*******************************************************************************
* @fn USB30_IN_ITflagT
*
* @brief Get IN transaction completion interrupt flag
*
* @param endp - Set endpoint number
*
* @return None
*/
extern UINT8 USB30_IN_ITflag(UINT8 endp);
/*******************************************************************************
* @fn USB30_IN_Nump
*
* @brief Get the remaining number of packets to be sent by the endpoint
*
* @param endp - endpoint number
*
* @return Remaining number of packets to be sent
*/
extern UINT8 USB30_IN_Nump(UINT8 endp);
/*******************************************************************************
* @fn USB30_Send_ERDY
*
* @brief send ERDY packet
*
* @param endp - endpoint number
* nump - Number of packets received or sent by the endpoint
*
* @return None
*/
extern void USB30_Send_ERDY(UINT8 endp,UINT8 nump);
/*******************************************************************************
* @fn USB30_Device_Setaddress
*
* @brief Set device address
*
* @param address - device address
*
* @return None
*/
extern void USB30_Device_Setaddress( UINT32 address );
/*******************************************************************************
* @fn USB30_IN_Nump
*
* @brief Get the remaining number of packets to be sent by the endpoint
*
* @return Control the length of data sent by the host when the transmission data stage is OUT
*/
extern UINT16 USB30_Setup_OutData(void);
/*******************************************************************************
* @fn USB30_IRQHandler
*
* @brief USB30_IRQHandler
*
* @return None
*/
extern void USB30_IRQHandler();
/*******************************************************************************
* @fn USB30_StandardReq
*
* @brief USB device mode standard request command processing
*
* @return The length of data sent by the host request device
*/
extern UINT16 USB30_StandardReq();
/*******************************************************************************
* @fn USB30_NonStandardReq
*
* @brief USB device mode non-standard request command processing
*
* @return The length of data sent by the host request device
*/
extern UINT16 USB30_NonStandardReq();
/*******************************************************************************
* @fn EP0_IN_Callback
*
* @brief endpoint 0 IN Transfer completion callback function
*
* @return Data length
*/
extern UINT16 EP0_IN_Callback();
/*******************************************************************************
* @fn EP0_OUT_Callback
*
* @brief endpoint 0 OUT Transfer completion callback function
*
* @return None
*/
extern UINT16 EP0_OUT_Callback();
/*******************************************************************************
* @fn USB30_Setup_Status
*
* @brief Control transmission status stage
*
* @return None
*/
extern void USB30_Setup_Status();
/*******************************************************************************
* @fn USB30_ITP_Callback
*
* @brief ITP Callback function
*
* @return None
*/
extern void USB30_ITP_Callback(UINT32 ITPCounter);
/*******************************************************************************
* @fn USB30_switch_pwr_mode
*
* @brief switch USB3.0 Power mode
*
* @return None
*/
extern void USB30_Switch_Powermode( UINT8 pwr_mode );
/*******************************************************************************
* @fn EPn_IN_Callback()
*
* @brief endpointN IN transaction callback function
*
* @return None
*/
extern void EP1_IN_Callback(void);
extern void EP2_IN_Callback(void);
extern void EP3_IN_Callback(void);
extern void EP4_IN_Callback(void);
extern void EP5_IN_Callback(void);
extern void EP6_IN_Callback(void);
extern void EP7_IN_Callback(void);
/*******************************************************************************
* @fn EPn_IN_Callback()
*
* @brief endpointN OUT transaction callback function
*
* @return None
*/
extern void EP1_OUT_Callback(void);
extern void EP2_OUT_Callback(void);
extern void EP3_OUT_Callback(void);
extern void EP4_OUT_Callback(void);
extern void EP5_OUT_Callback(void);
extern void EP6_OUT_Callback(void);
extern void EP7_OUT_Callback(void);
#ifdef __cplusplus
}
#endif
#endif /* USB30_CH56X_USB30_LIB_H_ */

View File

@ -0,0 +1,27 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : cdc.h
* Author : WCH
* Version : V1.2
* Date : 2024/07/10
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef CDC_CDC_H_
#define CDC_CDC_H_
extern volatile UINT16 USBByteCount;
extern volatile UINT16 USBBufOutPoint;
extern volatile UINT8 UploadPoint2_Busy;
extern volatile UINT8 DownloadPoint2_Busy;
extern volatile UINT16 Uart_Sendlenth;
void CDC_Uart_Init( UINT32 baudrate );
void TMR2_TimerInit1( void );
void CDC_Uart_Deal( void );
void CDC_Variable_Clear(void);
#endif /* CDC_CDC_H_ */

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_usb.h
* @brief define aiit-arm32-board usb function and struct
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
#ifndef CONNECT_USB_H
#define CONNECT_USB_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef BSP_USING_USBD_CDC
// TODO
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,6 @@
menuconfig BSP_USING_USBD
bool "Using usbd device"
default y
if BSP_USING_USBD
source "$BSP_DIR/third_party_driver/usb/usbd/Kconfig"
endif

View File

@ -0,0 +1,5 @@
ifeq ($(CONFIG_BSP_USING_USBD),y)
SRC_DIR += usbd
endif
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,3 @@
menuconfig BSP_USING_USBD_CDC
bool "Using usbd cdc device"
default y

View File

@ -0,0 +1,5 @@
ifeq ($(CONFIG_BSP_USING_USBD_CDC),y)
SRC_DIR += simulate_cdc
endif
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,337 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : cdc.c
* Author : WCH
* Version : V1.2
* Date : 2024/07/10
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "CH56x_common.h"
#include "CH56x_usb30_LIB.h"
#include "CH56x_usb30.h"
#include "CH56x_usb20.h"
#include "cdc.h"
/* Global define */
#define UART_REV_LEN 1024 //uart receive buffer size
#define UART_TIMEOUT 1000
/* Global Variable */
__attribute__ ((aligned(16))) UINT8 Receive_Uart_Buf[UART_REV_LEN] __attribute__((section(".DMADATA")));//uart receive buffer
volatile UINT16 Uart_Input_Point = 0; //Circular buffer write pointer
volatile UINT16 Uart_Output_Point = 0; //Loop buffer fetch pointer
volatile UINT16 UartByteCount = 0; //The number of bytes remaining to be fetched in the current buffer
volatile UINT16 USBByteCount = 0; //Data received by USB endpoint
volatile UINT16 USBBufOutPoint = 0; //Get data pointer
volatile UINT8 UploadPoint2_Busy = 0; //Upload whether the endpoint is busy
volatile UINT8 DownloadPoint2_Busy = 0; //Download whether the endpoint is busy
volatile UINT16 Uart_Timecount = 0; //Timeout processing calculation time
volatile UINT16 Uart_Sendlenth = 0; //USB upload data length
/* Function declaration */
void TMR2_IRQHandler (void) __attribute__((interrupt()));
void UART2_IRQHandler (void) __attribute__((interrupt()));
/*******************************************************************************
* @fn CDC_Uart_Init
*
* @brief CDC UART initialization
*
* @param baudrate: UART2 communication baud rate.
*
* @return None
*/
void CDC_Uart_Init( UINT32 baudrate )
{
UINT32 x;
UINT32 t = FREQ_SYS;
x = 10 * t * 2 / 16 / baudrate;
x = ( x + 5 ) / 10;
R8_UART2_DIV = 1;
R16_UART2_DL = x;
R8_UART2_FCR = RB_FCR_FIFO_TRIG | RB_FCR_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN;
R8_UART2_LCR = RB_LCR_WORD_SZ;
R8_UART2_IER = RB_IER_TXD_EN;
GPIOA_SetBits(GPIO_Pin_3);
GPIOA_ModeCfg(GPIO_Pin_2, GPIO_ModeIN_PU_NSMT);
GPIOA_ModeCfg(GPIO_Pin_3, GPIO_Slowascent_PP_8mA);
UART2_ByteTrigCfg( UART_7BYTE_TRIG );
UART2_INTCfg( ENABLE, RB_IER_RECV_RDY|RB_IER_LINE_STAT );
PFIC_EnableIRQ( UART2_IRQn );
}
/*******************************************************************************
* @fn TMR2_TimerInit1
*
* @brief CDC timeout timer initialization
*
* @return None
*/
void TMR2_TimerInit1( void )
{
R32_TMR2_CNT_END = FREQ_SYS/100000; //10us
R8_TMR2_CTRL_MOD = RB_TMR_ALL_CLEAR;
R8_TMR2_CTRL_MOD = RB_TMR_COUNT_EN;
R8_TMR2_INTER_EN |= 0x01;
PFIC_EnableIRQ( TMR2_IRQn );
}
/*******************************************************************************
* @fn TMR2_IRQHandler
*
* @brief CDC timer interrupt function
*
* @return None
*/
void TMR2_IRQHandler( void )
{
if( R8_TMR2_INT_FLAG &0x01 )
{
R8_TMR2_INT_FLAG = 0x01;
Uart_Timecount++;
}
}
/*******************************************************************************
* @fn U30_CDC_UartRx_Deal
*
* @brief usb3.0 CDC serial port receiving data processing
*
* @return None
*/
void U30_CDC_UartRx_Deal( void )
{
if(!UploadPoint2_Busy)
{
Uart_Sendlenth = UartByteCount;
if(Uart_Sendlenth > 0)
{
if( (Uart_Sendlenth >= (UART_REV_LEN/2) && DownloadPoint2_Busy == 0 ) || Uart_Timecount > UART_TIMEOUT )//If the sent data overflows or times out, upload the data
{
if(Uart_Output_Point+Uart_Sendlenth>UART_REV_LEN)//Determine if the pointer to the stored data array is out of bounds
{
Uart_Sendlenth = UART_REV_LEN-Uart_Output_Point;
}
if(Uart_Sendlenth > (UART_REV_LEN/2))//Limit sending length
{
Uart_Sendlenth = (UART_REV_LEN/2);
}
UartByteCount -= Uart_Sendlenth;//Reduce the length of data to be sent
memcpy(endp2Txbuff,&Receive_Uart_Buf[Uart_Output_Point],Uart_Sendlenth);//Copy the data to be sent to the USB buffer
Uart_Output_Point+=Uart_Sendlenth;//Move buffer pointer
if(Uart_Output_Point>=UART_REV_LEN)
{
Uart_Output_Point = 0;
}
UploadPoint2_Busy = 1;
/* Start USB sending */
USB30_IN_ClearIT( ENDP_2 );
USB30_IN_Set( ENDP_2 , ENABLE , ACK , 1, Uart_Sendlenth);
USB30_Send_ERDY( ENDP_2 | IN , 1 );
Uart_Timecount = 0;
}
}
}
}
/*******************************************************************************
* @fn U20_CDC_UartRx_Deal
*
* @brief usb2.0 CDC serial port receiving data processing
*
* @return None
*/
void U20_CDC_UartRx_Deal( void )
{
UINT16 i= 0;
if(!UploadPoint2_Busy)
{
Uart_Sendlenth = UartByteCount;
if(Uart_Sendlenth>0)
{
if( (Uart_Sendlenth >= (UART_REV_LEN/4)) || Uart_Timecount > UART_TIMEOUT )
{
if(Uart_Output_Point+Uart_Sendlenth>UART_REV_LEN)
{
Uart_Sendlenth = UART_REV_LEN - Uart_Output_Point;
}
if(Uart_Sendlenth > (UART_REV_LEN/4))
{
Uart_Sendlenth = (UART_REV_LEN/4);
}
UartByteCount -= Uart_Sendlenth;
memcpy(endp2Txbuff,&Receive_Uart_Buf[Uart_Output_Point],Uart_Sendlenth);
Uart_Output_Point+=Uart_Sendlenth;
if(Uart_Output_Point>=UART_REV_LEN)
{
Uart_Output_Point = 0;
}
UploadPoint2_Busy = 1;
R16_UEP2_T_LEN = Uart_Sendlenth;
R8_UEP2_TX_CTRL = (R8_UEP2_TX_CTRL & ~RB_UEP_TRES_MASK) | UEP_T_RES_ACK;
Uart_Timecount = 0;
}
}
}
}
/*******************************************************************************
* @fn U30_CDC_UartTx_Deal
*
* @brief usb3.0 CDC serial port sending data processing
*
* @return None
*/
void U30_CDC_UartTx_Deal( void )
{
static UINT16 i = 0;
if(USBByteCount)//If there is any remaining data to be downloaded, it will be sent through the uart
{
UART2_SendString(&endp2Rxbuff[USBBufOutPoint++],1);
USBByteCount --;
}
if( DownloadPoint2_Busy == 0 )
{
if(USBByteCount == 0 && UploadPoint2_Busy == 0)//Allow Next Send
{
USBBufOutPoint = 0;
DownloadPoint2_Busy = 1;
USBSS->UEP2_RX_DMA = (UINT32)(UINT8 *)endp2Rxbuff;
USB30_OUT_ClearIT(ENDP_2);
USB30_OUT_Set( ENDP_2 , ACK , 1 );
USB30_Send_ERDY( ENDP_2 | OUT , 1 );
}
}
}
/*******************************************************************************
* @fn U20_CDC_UartTx_Deal
*
* @brief usb2.0 CDC serial port sending data processing
*
* @return None
*/
void U20_CDC_UartTx_Deal( void )
{
static UINT16 i = 0;
if(USBByteCount)
{
UART2_SendString(&endp2Rxbuff[USBBufOutPoint++],1);
USBByteCount--;
if(USBByteCount==0){
USBBufOutPoint = 0;
R32_UEP2_RX_DMA = (UINT32)(UINT8 *)endp2Rxbuff;
R8_UEP2_RX_CTRL = (R8_UEP2_RX_CTRL &~RB_UEP_RRES_MASK)|UEP_R_RES_ACK;
}
}
}
/*******************************************************************************
* @fn CDC_Uart_Deal
*
* @brief CDC processing function
*
* @return None
*/
void CDC_Uart_Deal( void )
{
if( Link_Sta == LINK_STA_1)//2.0
{
U20_CDC_UartTx_Deal();
U20_CDC_UartRx_Deal();
}
else
{
U30_CDC_UartTx_Deal();
U30_CDC_UartRx_Deal();
}
}
/*******************************************************************************
* @fn CDC_Variable_Clear
*
* @brief CDC variable initialization
*
* @return None
*/
void CDC_Variable_Clear(void){
Uart_Input_Point = 0;
Uart_Output_Point = 0;
UartByteCount = 0;
USBByteCount = 0;
USBBufOutPoint = 0;
UploadPoint2_Busy = 0;
Uart_Timecount = 0;
Uart_Sendlenth = 0;
}
/*******************************************************************************
* @fn UART2_IRQHandler
*
* @brief CDC serial port interrupt function
*
* @return None
*/
void UART2_IRQHandler(void)
{
UINT8 i,rec_length;
UINT8 rec[7] = {0};
switch( UART2_GetITFlag() )
{
case UART_II_LINE_STAT: //Line status error
printf("error:%x\n",R8_UART2_LSR);
break;
case UART_II_RECV_RDY: //Data reaches the trigger point
for(rec_length = 0; rec_length < 7; rec_length++)
{
Receive_Uart_Buf[Uart_Input_Point++] = UART2_RecvByte();
if(Uart_Input_Point>=UART_REV_LEN )
{
Uart_Input_Point = 0;
}
}
UartByteCount += rec_length;
Uart_Timecount = 0;
break;
case UART_II_RECV_TOUT: //Receive timeout
rec_length = UART2_RecvString(rec);
for(i = 0; i < rec_length ; i++)
{
Receive_Uart_Buf[Uart_Input_Point++] = rec[i];
if(Uart_Input_Point>=UART_REV_LEN )
{
Uart_Input_Point = 0;
}
}
UartByteCount += i;
Uart_Timecount = 0;
break;
case UART_II_THR_EMPTY: //Send buffer empty
break;
default:
break;
}
}

View File

@ -0,0 +1,3 @@
SRC_FILES := connect_cdc.c USB20/CH56x_usb20.c USB30/CH56x_usb30.c CDC/cdc.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,756 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_usb20.c
* Author : WCH
* Version : V1.2
* Date : 2024/07/10
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "CH56x_common.h"
#include "CH56x_usb20.h"
#include "CH56x_usb30.h"
#include "CH56x_usb30_LIB.h"
#include "cdc.h"
/* Global Variable */
UINT32V U20_vitrul_buad = 115200;
UINT16V U20_EndpnMaxSize = 512;
UINT16V SetupReqLen=0; //Host request data length
UINT16V SetupLen = 0; //Data length actually sent or received in data phase
UINT32V seq_num = 0;
DevInfo_Typedef g_devInfo;
static UINT8V SetupReqType = 0; //Host request descriptor type
static UINT8V SetupReq = 0; //Host request descriptor type
static PUINT8 pDescr;
extern UINT8V Link_Sta;
__attribute__ ((aligned(16))) UINT8 vendor_buff[16] __attribute__((section(".DMADATA")));
/* Function declaration */
void USBHS_IRQHandler(void) __attribute__((interrupt()));
const UINT8 hs_device_descriptor[] =
{
0x12, // bLength
0x01, // DEVICE descriptor type
0x00, // 2.00
0x02,
0x02, // device class
0x00, // device sub-class
0x00, // vendor specific protocol
0x40, // max packet size 64B
0x86, // vendor id-0x1A86(qinheng)
0x1A,
0x0c, // product id 0xfe0c
0xfe,
0x01, //bcdDevice 0x01
0x00,
0x01, // manufacturer index string
0x02, // product index string
0x03, // serial number index string
0x01 // number of configurations
};
const UINT8 hs_config_descriptor[] =
{
0x09, // length of this descriptor
0x02, // CONFIGURATION (2)
0x43, // total length includes endpoint descriptors (should be 1 more than last address)
0x00, // total length high byte
0x02, // number of interfaces
0x01, // configuration value for this one
0x00, // configuration - string is here, 0 means no string
0x80, // attributes - bus powered, no wakeup
0x32, // max power - 800 ma is 100 (64 hex)
/*control interface*/
0x09, // length of the interface descriptor
0x04, // INTERFACE (4)
0x00, // Zero based index 0f this interface
0x00, // Alternate setting value (?)
0x01, // Number of endpoints (not counting 0)
0x02, // Interface class, ff is vendor specific
0x02, // Interface sub-class
0x01, // Interface protocol
0x00, // Index to string descriptor for this interface
/*Header Functional Descriptor*/
0x05, /* bLength: Endpoint Descriptor size */
0x24, /* bDescriptorType: CS_INTERFACE */
0x00, /* bDescriptorSubtype: Header Func Desc */
0x10, /* bcdCDC: spec release number */
0x01,
/*Call Management Functional Descriptor*/
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x01, /* bDescriptorSubtype: Call Management Func Desc */
0x00,
0x01,
0x04,
0x24,
0x02,
0x02,
0x05,
0x24,
0x06,
0x00,
0x01,
0x07, // length of this endpoint descriptor
0x05, // ENDPOINT (5)
0x81, // endpoint direction (80 is in) and address
0x03, // transfer type - 00 = control, 01 = iso, 10 = bulk, 11 = int
0x40, // max packet size - 1024 bytes
0x00, // max packet size - high
0x01, // polling interval in milliseconds (1 for iso)
/*data interface*/
0x09, // length of the interface descriptor
0x04, // INTERFACE (4)
0x01, // Zero based index 0f this interface
0x00, // Alternate setting value (?)
0x02, // Number of endpoints (not counting 0)
0x0a, // Interface class, ff is vendor specific
0x00, // Interface sub-class
0x00, // Interface protocol
0x00, // Index to string descriptor for this interface
//Endpoint 2 Descriptor
0x07, // length of this endpoint descriptor
0x05, // ENDPOINT (5)
0x82, // endpoint direction (80 is in) and address
0x02, // transfer type - 00 = control, 01 = iso, 10 = bulk, 11 = int
0x00, // max packet size - 1024 bytes
0x02, // max packet size - high
0x00, // polling interval in milliseconds (1 for iso)
//endp2_descriptor
0x07, // length of this endpoint descriptor
0x05, // ENDPOINT (5)
0x02, // endpoint direction (00 is out) and address
0x02, // transfer type - 00 = control, 01 = iso, 10 = bulk, 11 = int
0x00, // max packet size - 1024 bytes
0x02, // max packet size - high
0x00, // polling interval in milliseconds (1 for iso)
};
/* Language Descriptor */
const UINT8 hs_string_descriptor0[] =
{
0x04, // this descriptor length
0x03, // descriptor type
0x09, // Language ID 0 low byte
0x04 // Language ID 0 high byte
};
/* Manufacturer Descriptor */
const UINT8 hs_string_descriptor1[] =
{
0x08, // length of this descriptor
0x03,
'W',
0x00,
'C',
0x00,
'H',
0x00
};
/* Product Descriptor */
const UINT8 hs_string_descriptor2[]=
{
38, //38 bytes
0x03, //0x03
0x57, 0x00, //W
0x43, 0x00, //C
0x48, 0x00, //H
0x20, 0x00, //
0x55, 0x00, //U
0x53, 0x00, //S
0x42, 0x00, //B
0x32, 0x00, //2
0x2e, 0x00, //.
0x30, 0x00, //0
0x20, 0x00, //
0x44, 0x00, //D
0x45, 0x00, //E
0x56, 0x00, //V
0x49, 0x00, //I
0x43, 0x00, //C
0x45, 0x00, //E
0x20, 0x00 //
};
const UINT8 hs_bos_descriptor[] =
{
0x05, // length of this descriptor
0x0f, // CONFIGURATION (2)
0x16, // total length includes endpoint descriptors (should be 1 more than last address)
0x00, // total length high byte
0x02, // number of device cap
0x07,
0x10, // DEVICE CAPABILITY type
0x02, // USB2.0 EXTENSION
0x02,
0x00,
0x00,
0x00,
0x0a, // length of this descriptor
0x10, // DEVICE CAPABILITY type
0x03, // superspeed usb device capability
0x00, //
0x0e, // ss/hs/fs
0x00,
0x01, // the lowest speed is full speed
0x0a, // u1 exit latency is 10us
0xff, // u1 exit latency is 8us
0x07
};
/*******************************************************************************
* @fn USB20_Endp_Init
*
* @brief USB2.0 Endpoint initialization
*
* @return None
*/
void USB20_Endp_Init () // USBHS device endpoint initial
{
R8_UEP4_1_MOD = RB_UEP1_TX_EN;
R8_UEP2_3_MOD = RB_UEP2_RX_EN | RB_UEP2_TX_EN ;
R16_UEP0_MAX_LEN = 64;
R16_UEP1_MAX_LEN = 512;
R16_UEP2_MAX_LEN = 512;
R32_UEP0_RT_DMA = (UINT32)(UINT8 *)endp0RTbuff;
R32_UEP1_TX_DMA = (UINT32)(UINT8 *)endp1RTbuff;
R32_UEP2_TX_DMA = (UINT32)(UINT8 *)endp2Txbuff;
R32_UEP2_RX_DMA = (UINT32)(UINT8 *)endp2Rxbuff;
R16_UEP0_T_LEN = 0;
R8_UEP0_TX_CTRL = UEP_T_RES_NAK;
R8_UEP0_RX_CTRL = 0;
R16_UEP1_T_LEN = 0;
R8_UEP1_TX_CTRL = UEP_T_RES_NAK ;
R16_UEP2_T_LEN = U20_MAXPACKET_LEN;
R8_UEP2_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_0;
R8_UEP2_RX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_0;
}
/*******************************************************************************
* @fn USB20_Device_Init
*
* @brief USB2.0 Device initialization
*
* @param sta - ENABLE / DISABLE
*
* @return None
*/
void USB20_Device_Init ( FunctionalState sta ) // USBHS device initial
{
UINT16 i;
UINT32 *p;
if(sta)
{
R8_USB_CTRL = 0;
R8_USB_CTRL = UCST_HS | RB_DEV_PU_EN | RB_USB_INT_BUSY |RB_USB_DMA_EN;
R8_USB_INT_EN = RB_USB_IE_SETUPACT | RB_USB_IE_TRANS | RB_USB_IE_SUSPEND |RB_USB_IE_BUSRST ;
USB20_Endp_Init();
}
else
{
R8_USB_CTRL = RB_USB_CLR_ALL | RB_USB_RESET_SIE;
}
}
/*******************************************************************************
* @fn USB20_Device_setaddress
*
* @brief USB2.0 Set device address
*
* @param address
*
* @return None
**/
void USB20_Device_Setaddress( UINT32 address )
{
R8_USB_DEV_AD = address; // SET ADDRESS
}
/*******************************************************************************
* @fn U20_NonStandard_Request_Deal
*
* @brief Non-standard request processing
*
* @return None
*/
UINT16 U20_NonStandard_Request_Deal()
{
UINT16 len = 0;
switch( UsbSetupBuf->bRequest )
{
/* Open the serial port and send the baud rate */
case 0x20:
R8_UEP0_RX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_1;
break;
/* Read the current serial port configuration */
case 0x21:
*(UINT32 *)&endp0RTbuff[0] = U20_vitrul_buad;
endp0RTbuff[4]=0x00;endp0RTbuff[5]=0x00;endp0RTbuff[6]=0x08;
len = 7;
break;
/* Close uart */
case 0x22:
CDC_Variable_Clear();
break;
case 0x02:
break;
default:
return USB_DESCR_UNSUPPORTED;
break;
}
return len;
}
/*******************************************************************************
* @fn U20_Standard_Request_Deal
*
* @brief USB2.0 standard request deal
*
* @return None
*/
UINT16 U20_Standard_Request_Deal()
{
UINT16 len = 0;
UINT8 endp_dir;
SetupLen = 0;
endp_dir = UsbSetupBuf->bRequestType & 0x80;
switch( SetupReq )
{
case USB_GET_DESCRIPTOR:
{
switch( UsbSetupBuf->wValueH )
{
case USB_DESCR_TYP_DEVICE:
pDescr = (UINT8 *)hs_device_descriptor;
SetupLen = ( SetupReqLen > sizeof(hs_device_descriptor) )? sizeof(hs_device_descriptor):SetupReqLen;
break;
case USB_DESCR_TYP_CONFIG:
pDescr = (UINT8 *)hs_config_descriptor;
SetupLen = ( SetupReqLen > sizeof(hs_config_descriptor) )? sizeof(hs_config_descriptor):SetupReqLen;
break;
case USB_DESCR_TYP_STRING:
switch( UsbSetupBuf->wValueL )
{
case USB_DESCR_LANGID_STRING:
pDescr = (UINT8 *)hs_string_descriptor0;
SetupLen = ( SetupReqLen > sizeof(hs_string_descriptor0) )? sizeof(hs_string_descriptor0):SetupReqLen;
break;
case USB_DESCR_VENDOR_STRING:
pDescr = (UINT8 *)hs_string_descriptor1;
SetupLen = ( SetupReqLen > sizeof(hs_string_descriptor1) )? sizeof(hs_string_descriptor1):SetupReqLen;
break;
case USB_DESCR_PRODUCT_STRING:
pDescr =(UINT8 *) hs_string_descriptor2;
SetupLen = ( SetupReqLen > sizeof(hs_string_descriptor2) )? sizeof(hs_string_descriptor2):SetupReqLen;
break;
case USB_DESCR_SERIAL_STRING:
break;
default:
SetupLen = USB_DESCR_UNSUPPORTED;
break;
}
break;
case USB_DESCR_TYP_BOS:
pDescr =(UINT8 *) hs_bos_descriptor;
SetupLen = ( SetupReqLen > sizeof(hs_bos_descriptor) )? sizeof(hs_bos_descriptor):SetupReqLen;
break;
default :
SetupLen = USB_DESCR_UNSUPPORTED;
break;
}
}
break;
case USB_SET_ADDRESS:
g_devInfo.dev_addr = UsbSetupBuf->wValueL;
break;
case USB_GET_CONFIGURATION:
endp0RTbuff[ 0 ] = g_devInfo.dev_config_value;
SetupLen = 1;
break;
case USB_SET_CONFIGURATION:
if( (R8_USB_SPD_TYPE & RB_USBSPEED_MASK) == UST_FS )
{
U20_EndpnMaxSize = 64;
}
else if( (R8_USB_SPD_TYPE & RB_USBSPEED_MASK) == UST_LS )
{
U20_EndpnMaxSize = 8;
}
g_devInfo.dev_config_value = UsbSetupBuf->wValueL;
g_devInfo.dev_enum_status = 0x01;
break;
case USB_CLEAR_FEATURE:
if( ( UsbSetupBuf->bRequestType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP )
{
switch( UsbSetupBuf->wIndexL )
{
case 0x82:
R16_UEP2_T_LEN= 0;
R8_UEP2_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_0;
break;
case 0x02:
R8_UEP2_TX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_0;
break;
case 0x81:
R16_UEP1_T_LEN = 0;
R8_UEP1_TX_CTRL = UEP_T_RES_NAK | RB_UEP_T_TOG_0;
break;
case 0x01:
R8_UEP1_RX_CTRL = UEP_T_RES_ACK | RB_UEP_R_TOG_0;
break;
default:
SetupLen = USB_DESCR_UNSUPPORTED;
break;
}
}
else if( ( UsbSetupBuf->bRequestType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_DEVICE )
{
if( ( UsbSetupBuf->wValueL ) == 1 )
{
g_devInfo.dev_sleep_status &= ~0x01;
}
}
else
{
SetupLen = USB_DESCR_UNSUPPORTED;
}
break;
case USB_SET_FEATURE:
if( ( UsbSetupBuf->bRequestType & 0x1F ) == 0x00 )
{
if( UsbSetupBuf->wValueL == 0x01 )
{
if( hs_config_descriptor[ 7 ] & 0x20 )
{
g_devInfo.dev_sleep_status = 0x01;
}
else
{
SetupLen = USB_DESCR_UNSUPPORTED;
}
}
else
{
SetupLen = USB_DESCR_UNSUPPORTED;
}
}
else if( ( UsbSetupBuf->bRequestType & 0x1F ) == 0x02 )
{
if( UsbSetupBuf->wValueL == 0x00 )
{
switch( UsbSetupBuf->wIndexL )
{
case 0x82:
R8_UEP2_TX_CTRL = ( R8_UEP2_TX_CTRL & ~RB_UEP_TRES_MASK ) | UEP_T_RES_STALL;
break;
case 0x02:
R8_UEP2_RX_CTRL = ( R8_UEP2_RX_CTRL & ~RB_UEP_RRES_MASK ) | UEP_R_RES_STALL;
break;
case 0x81:
R8_UEP1_TX_CTRL = ( R8_UEP1_TX_CTRL & ~RB_UEP_TRES_MASK ) | UEP_T_RES_STALL;
break;
case 0x01:
R8_UEP1_RX_CTRL = ( R8_UEP1_RX_CTRL & ~RB_UEP_RRES_MASK ) | UEP_R_RES_STALL;
break;
default:
SetupLen = USB_DESCR_UNSUPPORTED;
break;
}
}
else
{
SetupLen = USB_DESCR_UNSUPPORTED;
}
}
else
{
SetupLen = USB_DESCR_UNSUPPORTED;
}
break;
case USB_GET_INTERFACE:
break;
case USB_SET_INTERFACE:
break;
case USB_GET_STATUS:
endp0RTbuff[ 0 ] = 0x00;
endp0RTbuff[ 1 ] = 0x00;
SetupLen = 2;
if( UsbSetupBuf->wIndexL == 0x81 )
{
if( ( R8_UEP1_TX_CTRL & RB_UEP_TRES_MASK ) == UEP_T_RES_STALL )
{
endp0RTbuff[ 0 ] = 0x01;
SetupLen = 1;
}
}
else if( UsbSetupBuf->wIndexL == 0x01 )
{
if( ( R8_UEP1_RX_CTRL & RB_UEP_RRES_MASK ) == UEP_R_RES_STALL )
{
endp0RTbuff[ 0 ] = 0x01;
SetupLen = 1;
}
}
else if( UsbSetupBuf->wIndexL == 0x82 )
{
if( ( R8_UEP2_TX_CTRL & RB_UEP_TRES_MASK ) == UEP_T_RES_STALL )
{
endp0RTbuff[ 0 ] = 0x01;
SetupLen = 1;
}
}
else if( UsbSetupBuf->wIndexL == 0x02 )
{
if( ( R8_UEP2_RX_CTRL & RB_UEP_RRES_MASK ) == UEP_R_RES_STALL )
{
endp0RTbuff[ 0 ] = 0x01;
SetupLen = 1;
}
}
break;
default:
SetupLen = USB_DESCR_UNSUPPORTED;
break;
}
if( (SetupLen != USB_DESCR_UNSUPPORTED) && (SetupLen != 0))
{
len = ( SetupLen >= U20_UEP0_MAXSIZE ) ? U20_UEP0_MAXSIZE : SetupLen;
if(endp_dir)
{
memcpy( endp0RTbuff, pDescr, len );
pDescr += len;
}
SetupLen -= len;
}
return len;
}
/*******************************************************************************
* @fn USBHSD_IRQHandler
*
* @brief USB2.0 Interrupt Handler.
*
* @return None
*/
void USBHS_IRQHandler(void) //USBHS interrupt service
{
UINT32 end_num;
UINT32 rx_token;
UINT16 ret_len,i;
UINT16 rxlen;
UINT8 *p8;
UINT8 int_flg;
UINT32 baudrate;
int_flg = R8_USB_INT_FG;
if( int_flg & RB_USB_IF_SETUOACT ) //SETUP interrupt
{
#if 0
printf("SETUP :");
p8 = (UINT8 *)endp0RTbuff;
for(i=0; i<8; i++) { printf("%02x ", *p8++); }
printf("\n");
#endif
SetupReqType = UsbSetupBuf->bRequestType;
SetupReq = UsbSetupBuf->bRequest;
SetupReqLen = UsbSetupBuf->wLength; //Data length
/*Analyze host requests*/
if((UsbSetupBuf->bRequestType & USB_REQ_TYP_MASK) != USB_REQ_TYP_STANDARD)
{
ret_len = U20_NonStandard_Request_Deal();
}
else
{
ret_len = U20_Standard_Request_Deal();
}
if(ret_len == 0xFFFF)
{
R16_UEP0_T_LEN = 0;
R8_UEP0_TX_CTRL = UEP_T_RES_STALL ;
R8_UEP0_RX_CTRL = UEP_R_RES_STALL ;
}
else
{
R16_UEP0_T_LEN = ret_len;
R8_UEP0_TX_CTRL = UEP_T_RES_ACK | RB_UEP_T_TOG_1;
R8_UEP0_RX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_1;
}
R8_USB_INT_FG = RB_USB_IF_SETUOACT; // clear int flag
}
/*Transaction transfer complete interrupt*/
else if( int_flg & RB_USB_IF_TRANSFER )
{
end_num = R8_USB_INT_ST & 0xf;
rx_token = ( (R8_USB_INT_ST )>>4) & 0x3;
#if 0
if( !(R8_USB_INT_ST & RB_USB_ST_TOGOK) )
{
printf(" TOG MATCH FAIL : ENDP %x token %x \n", end_num, rx_token);
}
#endif
switch( end_num )
{
case 0:
if( rx_token == PID_IN )
{
ret_len = U20_Endp0_IN_Callback();
if(ret_len == 0)
{
R8_UEP0_RX_CTRL = UEP_R_RES_ACK | RB_UEP_R_TOG_1;
R16_UEP0_T_LEN = 0;
R8_UEP0_TX_CTRL = 0;
}
else
{
R16_UEP0_T_LEN = ret_len;
R8_UEP0_TX_CTRL ^= RB_UEP_T_TOG_1;
R8_UEP0_TX_CTRL = ( R8_UEP0_TX_CTRL &~RB_UEP_TRES_MASK )| UEP_T_RES_ACK ;
}
}
else if( rx_token == PID_OUT )
{
SetupLen -= SetupLen > R16_USB_RX_LEN ? R16_USB_RX_LEN :SetupLen;
if( SetupLen > 0 )
{
R8_UEP0_RX_CTRL ^=RB_UEP_R_TOG_1;
R8_UEP0_RX_CTRL = ( R8_UEP0_RX_CTRL &~RB_UEP_RRES_MASK) | UEP_R_RES_ACK;
}
else
{
R16_UEP0_T_LEN = 0;
R8_UEP0_TX_CTRL = UEP_T_RES_ACK | RB_UEP_T_TOG_1;
R8_UEP0_RX_CTRL = 0 ;
}
/* save bauds */
baudrate = endp0RTbuff[ 0 ];
baudrate += ((UINT32)endp0RTbuff[ 1 ] << 8 );
baudrate += ((UINT32)endp0RTbuff[ 2 ] << 16 );
baudrate += ((UINT32)endp0RTbuff[ 3 ] << 24 );
U20_vitrul_buad = baudrate;
CDC_Uart_Init(baudrate);
}
break;
case 1:
break;
case 2:
if(rx_token == PID_IN)
{
R16_UEP2_T_LEN = 0;
R8_UEP2_TX_CTRL ^= RB_UEP_T_TOG_1;
R8_UEP2_TX_CTRL = (R8_UEP2_TX_CTRL & ~RB_UEP_TRES_MASK) | UEP_T_RES_NAK;
UploadPoint2_Busy = 0;
}
else if(rx_token == PID_OUT)
{
USBByteCount = R16_USB_RX_LEN;
R8_UEP2_RX_CTRL ^= RB_UEP_R_TOG_1;
R8_UEP2_RX_CTRL = (R8_UEP2_RX_CTRL &~RB_UEP_RRES_MASK) | UEP_R_RES_NAK;
}
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
default:
break;
}
R8_USB_INT_FG = RB_USB_IF_TRANSFER;
}
else if( int_flg & RB_USB_IF_BUSRST )
{
USB20_Endp_Init();
USB20_Device_Setaddress( 0 );
R8_USB_INT_FG = RB_USB_IF_BUSRST;
if( Link_Sta == LINK_STA_1 )
{
PFIC_EnableIRQ(USBSS_IRQn);
PFIC_EnableIRQ(LINK_IRQn);
PFIC_EnableIRQ(TMR0_IRQn);
R8_TMR0_INTER_EN = 1;
TMR0_TimerInit( 67000000 );
USB30D_init(ENABLE);
}
}
else if( int_flg & RB_USB_IF_SUSPEND )
{
R8_USB_INT_FG = RB_USB_IF_SUSPEND;
}
}
/*******************************************************************************
* @fn U20_Endp0_IN_Callback
*
* @brief U20_Endp0_IN_Callback Handler.
*
* @return None
*/
UINT16 U20_Endp0_IN_Callback(void)
{
UINT16 len = 0;
switch(SetupReq)
{
case USB_GET_DESCRIPTOR:
len = SetupLen >= U20_UEP0_MAXSIZE ? U20_UEP0_MAXSIZE : SetupLen;
memcpy(endp0RTbuff, pDescr, len);
SetupLen -= len;
pDescr += len;
break;
case USB_SET_ADDRESS:
USB20_Device_Setaddress(g_devInfo.dev_addr);
break;
default:
break;
}
return len;
}

View File

@ -0,0 +1,832 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_usb30.c
* Author : WCH
* Version : V1.2
* Date : 2024/07/10
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "CH56x_common.h"
#include "CH56x_usb30_LIB.h"
#include "CH56x_usb20.h"
#include "CH56x_usb30.h"
#include "cdc.h"
/* Global Variable */
UINT8V Tx_Lmp_Port = 0;
UINT8V Link_Sta = 0;
UINT32V vitrul_buad = 115200;
static UINT32 SetupLen = 0;
static UINT8 SetupReqCode = 0;
static PUINT8 pDescr;
__attribute__ ((aligned(16))) UINT8 endp0RTbuff[512] __attribute__((section(".DMADATA"))); //Endpoint 0 data receiving and sending buffer
__attribute__ ((aligned(16))) UINT8 endp1RTbuff[4096] __attribute__((section(".DMADATA"))); //Endpoint 1 data receiving and sending buffer
__attribute__ ((aligned(16))) UINT8 endp2Rxbuff[4096] __attribute__((section(".DMADATA"))); //Endpoint 2 data receiving and sending buffer
__attribute__ ((aligned(16))) UINT8 endp2Txbuff[4096] __attribute__((section(".DMADATA"))); //Endpoint 2 data receiving and sending buffer
/*Superspeed device descriptor*/
const UINT8 SS_DeviceDescriptor[] =
{
0x12, // bLength
0x01, // DEVICE descriptor type
0x00, // 3.00
0x03,
0x02, // device class
0x00, // device sub-class
0x00, // vendor specific protocol
0x09, // max packet size 512B
0x86, // vendor id 0x1a86
0x1a,
0x0c, // product id 0xfe0c
0xfe,
0x01, // bcdDevice
0x00,
0x01, // manufacturer index string
0x02, // product index string
0x03, // serial number index string
0x01 // number of configurations
};
/*Superspeed Configuration Descriptor*/
const UINT8 SS_ConfigDescriptor[] =
{
0x09, // length of this descriptor
0x02, // CONFIGURATION (2)
85, // total length includes endpoint descriptors (should be 1 more than last address)
0x00, // total length high byte
0x02, // number of interfaces
0x01, // configuration value for this one
0x00, // configuration - string is here, 0 means no string
0x80, // attributes - bus powered, no wakeup
0x64, // max power - 800 ma is 100 (64 hex)
0x09, // length of the interface descriptor
0x04, // INTERFACE (4)
0x00, // Zero based index 0f this interface
0x00, // Alternate setting value (?)
0x01, // Number of endpoints (not counting 0)
0x02, // Interface class, ff is vendor specific
0x02, // Interface sub-class
0x01, // Interface protocol
0x00, // Index to string descriptor for this interface
0x05, /* bLength: Endpoint Descriptor size */
0x24, /* bDescriptorType: CS_INTERFACE */
0x00, /* bDescriptorSubtype: Header Func Desc */
0x10, /* bcdCDC: spec release number */
0x01,
0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x01, /* bDescriptorSubtype: Call Management Func Desc */
0x00,
0x01,
0x04,
0x24,
0x02,
0x02,
0x05,
0x24,
0x06,
0x00,
0x01,
0x07, // length of this endpoint descriptor
0x05, // ENDPOINT (5)
0x81, // endpoint direction (80 is in) and address
0x03, // transfer type - 00 = control, 01 = iso, 10 = bulk, 11 = int
0x00, // max packet size - 1024 bytes
0x04, // max packet size - high
0x08, // polling interval in milliseconds (1 for iso)
0x06, // length of this endpoint compansion descriptor
0x30,
0x00, // max burst size
0x00, // no stream
0x00,
0x00,
0x09, // length of the interface descriptor
0x04, // INTERFACE (4)
0x01, // Zero based index 0f this interface
0x00, // Alternate setting value (?)
0x02, // Number of endpoints (not counting 0)
0x0a, // Interface class, ff is vendor specific
0x00, // Interface sub-class
0x00, // Interface protocol
0x00, // Index to string descriptor for this interface
//Endpoint 2 Descriptor
0x07, // length of this endpoint descriptor
0x05, // ENDPOINT (5)
0x82, // endpoint direction (80 is in) and address
0x02, // transfer type - 00 = control, 01 = iso, 10 = bulk, 11 = int
0x00, // max packet size - 1024 bytes
0x04, // max packet size - high
0x00, // polling interval in milliseconds (1 for iso)
0x06, // length of this endpoint compansion descriptor
0x30,
0x00, // max burst size
0x00, // no stream
0x00,
0x00,
//endp2_descriptor
0x07, // length of this endpoint descriptor
0x05, // ENDPOINT (5)
0x02, // endpoint direction (00 is out) and address
0x02, // transfer type - 00 = control, 01 = iso, 10 = bulk, 11 = int
0x00, // max packet size - 1024 bytes
0x04, // max packet size - high
0x00, // polling interval in milliseconds (1 for iso)
0x06, // length of this endpoint compansion descriptor
0x30,
0x00, // max burst size
0x00, // no stream
0x00,
0x00
};
/*String Descriptor Lang ID*/
const UINT8 StringLangID[] =
{
0x04, // this descriptor length
0x03, // descriptor type
0x09, // Language ID 0 low byte
0x04 // Language ID 0 high byte
};
/*String Descriptor Vendor*/
const UINT8 StringVendor[] =
{
0x08, // length of this descriptor
0x03,
'W',
0x00,
'C',
0x00,
'H',
0x00
};
/*String Descriptor Product*/
const UINT8 StringProduct[]=
{
38, //38 bytes in length
0x03, //Type code
0x57, 0x00, //W
0x43, 0x00, //C
0x48, 0x00, //H
0x20, 0x00, //
0x55, 0x00, //U
0x53, 0x00, //S
0x42, 0x00, //B
0x33, 0x00, //3
0x2e, 0x00, //.
0x30, 0x00, //0
0x20, 0x00, //
0x44, 0x00, //D
0x45, 0x00, //E
0x56, 0x00, //V
0x49, 0x00, //I
0x43, 0x00, //C
0x45, 0x00, //E
0x20, 0x00
};
/*String Descriptor Serial*/
UINT8 StringSerial[] =
{
0x16, // length of this descriptor
0x03,
'0',
0x00,
'1',
0x00,
'2',
0x00,
'3',
0x00,
'4',
0x00,
'5',
0x00,
'6',
0x00,
'7',
0x00,
'8',
0x00,
'9',
0x00,
};
const UINT8 OSStringDescriptor[] =
{
0x12, // length of this descriptor
0x03,
'M',
0x00,
'S',
0x00,
'F',
0x00,
'T',
0x00,
'1',
0x00,
'0',
0x00,
'0',
0x00,
0x01,
0x00
};
const UINT8 BOSDescriptor[] =
{
0x05, // length of this descriptor
0x0f, // CONFIGURATION (2)
0x16, // total length includes endpoint descriptors (should be 1 more than last address)
0x00, // total length high byte
0x02, // number of device cap
//dev_cap_descriptor1
0x07,
0x10, // DEVICE CAPABILITY type
0x02, // USB2.0 EXTENSION
0x06,
0x00,
0x00,
0x00,
//dev_cap_descriptor2
0x0a, // length of this descriptor
0x10, // DEVICE CAPABILITY type
0x03, // superspeed usb device capability
0x00, //
0x0e, // ss/hs/fs
0x00,
0x01, // the lowest speed is full speed
0x0a, // u1 exit latency is 10us
0xff, // u1 exit latency is 8us
0x07
};
/*******************************************************************************
* @fn USB30D_init
*
* @brief USB3.0 initialization
*
* @return None
*/
void USB30D_init(FunctionalState sta) {
UINT16 i,s;
if (sta) {
USB30_Device_Init();
USBSS->UEP0_DMA = (UINT32)(UINT8 *)endp0RTbuff;
USBSS->UEP1_TX_DMA = (UINT32)(UINT8 *)endp1RTbuff;
USBSS->UEP2_TX_DMA = (UINT32)(UINT8 *)endp2Txbuff;
USBSS->UEP2_RX_DMA = (UINT32)(UINT8 *)endp2Rxbuff;
USBSS->UEP_CFG = EP0_R_EN | EP0_T_EN | EP1_T_EN | EP2_R_EN | EP2_T_EN;// set end point rx/tx enable
USB30_OUT_Set(ENDP_2, ACK, 1);
}
else {
USB30_Switch_Powermode(POWER_MODE_2);
USBSS->LINK_CFG = PIPE_RESET | LFPS_RX_PD;
USBSS->LINK_CTRL = GO_DISABLED | POWER_MODE_3;
USBSS->LINK_INT_CTRL = 0;
USB30_Device_forceclr();
}
}
/*******************************************************************************
* @fn USB30_NonStandardReq
*
* @brief USB3.0 Nonstandard request processing function
*
* @return Length
*/
UINT16 USB30_NonStandardReq() {
UINT16 len = 0;
SetupReqCode = UsbSetupBuf->bRequest;
SetupLen = UsbSetupBuf->wLength;
switch (SetupReqCode) {
/* Open the serial port and send the baud rate */
case 0x20:
USB30_OUT_Set(ENDP_0, ACK, 1 );
break;
/* Read the current serial port configuration */
case 0x21:
*(UINT32 *)&endp0RTbuff[50] = vitrul_buad;
endp0RTbuff[54]=0x00;endp0RTbuff[55]=0x00;endp0RTbuff[56]=0x08;
SetupLen = 7;
break;
/* Close uart */
case 0x22:
CDC_Variable_Clear();
break;
default:
printf("stall\n");
SetupReqCode = INVALID_REQ_CODE;
return USB_DESCR_UNSUPPORTED;
break;
}
len = SetupLen >= ENDP0_MAXPACK ? ENDP0_MAXPACK : SetupLen;
memcpy(endp0RTbuff, &endp0RTbuff[50], len);
SetupLen -= len;
pDescr += len;
return len;
}
/*******************************************************************************
* @fn USB30_StandardReq
*
* @brief USB3.0 Standard request
*
* @return Length
*/
UINT16 USB30_StandardReq() {
UINT16 len = 0;
SetupReqCode = UsbSetupBuf->bRequest;
SetupLen = UsbSetupBuf->wLength;
if (( UsbSetupBuf->bRequestType & USB_REQ_TYP_MASK) != USB_REQ_TYP_STANDARD)
{
len= USB30_NonStandardReq();
}
else
{
switch (SetupReqCode) {
case USB_GET_DESCRIPTOR:
switch (UsbSetupBuf->wValueH) {
case USB_DESCR_TYP_DEVICE:
if (SetupLen > SIZE_DEVICE_DESC)
SetupLen = SIZE_DEVICE_DESC;
pDescr = (PUINT8) SS_DeviceDescriptor;
break;
case USB_DESCR_TYP_CONFIG:
if (SetupLen > SIZE_CONFIG_DESC)
SetupLen = SIZE_CONFIG_DESC;
pDescr = (PUINT8) SS_ConfigDescriptor;
break;
case USB_DESCR_TYP_BOS:
if (SetupLen > SIZE_BOS_DESC)
SetupLen = SIZE_BOS_DESC;
pDescr = (PUINT8) BOSDescriptor;
break;
case USB_DESCR_TYP_STRING:
switch (UsbSetupBuf->wValueL) {
case USB_DESCR_LANGID_STRING:
if (SetupLen > SIZE_STRING_LANGID)
SetupLen = SIZE_STRING_LANGID;
pDescr = (PUINT8) StringLangID;
break;
case USB_DESCR_VENDOR_STRING:
if (SetupLen > SIZE_STRING_VENDOR)
SetupLen = SIZE_STRING_VENDOR;
pDescr = (PUINT8) StringVendor;
break;
case USB_DESCR_PRODUCT_STRING:
if (SetupLen > SIZE_STRING_PRODUCT)
SetupLen = SIZE_STRING_PRODUCT;
pDescr = (PUINT8) StringProduct;
break;
case USB_DESCR_SERIAL_STRING:
if (SetupLen > SIZE_STRING_SERIAL)
SetupLen = SIZE_STRING_SERIAL;
pDescr = (PUINT8) StringSerial;
break;
case USB_DESCR_OS_STRING:
if (SetupLen > SIZE_STRING_OS)
SetupLen = SIZE_STRING_OS;
pDescr = (PUINT8) OSStringDescriptor;
break;
default:
len = USB_DESCR_UNSUPPORTED;
SetupReqCode = INVALID_REQ_CODE;
break;
}
break;
default:
len = USB_DESCR_UNSUPPORTED;
SetupReqCode = INVALID_REQ_CODE;
break;
}
len = SetupLen >= ENDP0_MAXPACK ? ENDP0_MAXPACK : SetupLen;
memcpy(endp0RTbuff, pDescr, len);
SetupLen -= len;
pDescr += len;
break;
case USB_SET_ADDRESS:
SetupLen = UsbSetupBuf->wValueL;
break;
case 0x31:
SetupLen = UsbSetupBuf->wValueL;
break;
case 0x30:
break;
case USB_SET_CONFIGURATION:
break;
case USB_GET_STATUS:
len = 2;
endp0RTbuff[0] = 0x01;
endp0RTbuff[1] = 0x00;
SetupLen = 0;
break;
case USB_CLEAR_FEATURE:
switch(UsbSetupBuf->wIndexL){
case 0x82:
USB30_IN_ClearIT( ENDP_2 );
USB30_IN_Set( ENDP_2 , ENABLE , ACK , 1 , 0);
USB30_Send_ERDY( ENDP_2 | IN , 1 );
break;
}
break;
case USB_SET_FEATURE:
break;
case USB_SET_INTERFACE:
break;
default:
len = USB_DESCR_UNSUPPORTED;
SetupReqCode = INVALID_REQ_CODE;
printf(" stall \n");
break;
}
}
return len;
}
/*******************************************************************************
* @fn EP0_IN_Callback
*
* @brief USB3.0 Endpoint 0 IN transaction callback
*
* @return Send length
*/
UINT16 EP0_IN_Callback(void) {
UINT16 len = 0;
switch (SetupReqCode) {
case USB_GET_DESCRIPTOR:
len = SetupLen >= ENDP0_MAXPACK ? ENDP0_MAXPACK : SetupLen;
memcpy(endp0RTbuff, pDescr, len);
SetupLen -= len;
pDescr += len;
break;
}
return len;
}
/*******************************************************************************
* @fn EP0_OUT_Callback
*
* @brief USB3.0 Endpoint 0 OUT transaction callback
*
* @return Length
*/
UINT16 EP0_OUT_Callback() {
UINT32 baudrate;
/* save bauds */
baudrate = endp0RTbuff[ 0 ];
baudrate += ((UINT32)endp0RTbuff[ 1 ] << 8 );
baudrate += ((UINT32)endp0RTbuff[ 2 ] << 16 );
baudrate += ((UINT32)endp0RTbuff[ 3 ] << 24 );
vitrul_buad = baudrate;
CDC_Uart_Init(baudrate);
return 0;
}
/*******************************************************************************
* @fn USB30_Setup_Status
*
* @brief USB3.0 Control transfer status stage callback
*
* @return None
*/
void USB30_Setup_Status(void) {
switch (SetupReqCode) {
case USB_SET_ADDRESS:
USB30_Device_Setaddress(SetupLen); // SET ADDRESS
break;
case 0x31:
break;
}
}
/*******************************************************************************
* @fn USBSS_IRQHandler
*
* @brief USB3.0 Interrupt Handler.
*
* @return None
*/
void USBSS_IRQHandler (void) //USBSS interrupt service
{
USB30_IRQHandler();
}
/*******************************************************************************
* @fn TMR0_IRQHandler
*
* @brief USB3.0 Connection failure timeout processing
*
* @return None
*/
void TMR0_IRQHandler( )
{
R8_TMR0_INTER_EN |= 1;
PFIC_DisableIRQ(TMR0_IRQn);
R8_TMR0_CTRL_MOD = RB_TMR_ALL_CLEAR;
if(Link_Sta == LINK_STA_1 )
{
Link_Sta =0;
PFIC_DisableIRQ(USBSS_IRQn);
PFIC_DisableIRQ(LINK_IRQn);
USB30D_init(DISABLE);
return;
}
if( Link_Sta != LINK_STA_3 )
{
PFIC_DisableIRQ(USBSS_IRQn);
PFIC_DisableIRQ(LINK_IRQn);
USB30D_init(DISABLE);
R32_USB_CONTROL = 0;
PFIC_EnableIRQ(USBHS_IRQn);
USB20_Device_Init(ENABLE);
}
Link_Sta = LINK_STA_1;
return;
}
/*******************************************************************************
* @fn LINK_IRQHandler
*
* @brief USB3.0 Link Interrupt Handler.
*
* @return None
*/
void LINK_IRQHandler() //USBSS link interrupt service
{
if(USBSS->LINK_INT_FLAG & LINK_Ux_EXIT_FLAG) // device enter U2
{
USBSS->LINK_CFG = CFG_EQ_EN | TX_SWING | DEEMPH_CFG | TERM_EN;
USB30_Switch_Powermode(POWER_MODE_0);
USBSS->LINK_INT_FLAG = LINK_Ux_EXIT_FLAG;
}
if(USBSS->LINK_INT_FLAG & LINK_RDY_FLAG) // POLLING SHAKE DONE
{
USBSS->LINK_INT_FLAG = LINK_RDY_FLAG;
if(Tx_Lmp_Port) // LMP, TX PORT_CAP & RX PORT_CAP
{
USBSS->LMP_TX_DATA0 = LINK_SPEED | PORT_CAP | LMP_HP;
USBSS->LMP_TX_DATA1 = UP_STREAM | NUM_HP_BUF;
USBSS->LMP_TX_DATA2 = 0x0;
Tx_Lmp_Port = 0;
}
/*Successful USB3.0 communication*/
Link_Sta = LINK_STA_3;
PFIC_DisableIRQ(TMR0_IRQn);
R8_TMR0_CTRL_MOD = RB_TMR_ALL_CLEAR;
R8_TMR0_INTER_EN = 0;
PFIC_DisableIRQ(USBHS_IRQn);
USB20_Device_Init(DISABLE);
}
if(USBSS->LINK_INT_FLAG & LINK_INACT_FLAG)
{
Link_Sta = 0;
PFIC_EnableIRQ(USBSS_IRQn);
PFIC_EnableIRQ(LINK_IRQn);
PFIC_EnableIRQ(TMR0_IRQn);
R8_TMR0_INTER_EN = RB_TMR_IE_CYC_END;
TMR0_TimerInit( 67000000 );
USB30D_init(ENABLE);
USBSS->LINK_INT_FLAG = LINK_INACT_FLAG;
USB30_Switch_Powermode(POWER_MODE_2);
}
if(USBSS->LINK_INT_FLAG & LINK_DISABLE_FLAG) // GO DISABLED
{
USBSS->LINK_INT_FLAG = LINK_DISABLE_FLAG;
Link_Sta = LINK_STA_1;
USB30D_init(DISABLE);
PFIC_DisableIRQ(USBSS_IRQn);
R8_TMR0_CTRL_MOD = RB_TMR_ALL_CLEAR;
R8_TMR0_INTER_EN = 0;
PFIC_DisableIRQ(TMR0_IRQn);
PFIC_EnableIRQ(USBHS_IRQn);
USB20_Device_Init(ENABLE);
}
if(USBSS->LINK_INT_FLAG & LINK_RX_DET_FLAG)
{
USBSS->LINK_INT_FLAG = LINK_RX_DET_FLAG;
USB30_Switch_Powermode(POWER_MODE_2);
}
if(USBSS->LINK_INT_FLAG & TERM_PRESENT_FLAG) // term present , begin POLLING
{
USBSS->LINK_INT_FLAG = TERM_PRESENT_FLAG;
if(USBSS->LINK_STATUS & LINK_PRESENT)
{
USB30_Switch_Powermode(POWER_MODE_2);
USBSS->LINK_CTRL |= POLLING_EN;
}
else
{
USBSS->LINK_INT_CTRL = 0;
}
}
if(USBSS->LINK_INT_FLAG & LINK_TXEQ_FLAG) // POLLING SHAKE DONE
{
Tx_Lmp_Port = 1;
USBSS->LINK_INT_FLAG = LINK_TXEQ_FLAG;
USB30_Switch_Powermode(POWER_MODE_0);
}
if(USBSS->LINK_INT_FLAG & WARM_RESET_FLAG)
{
USBSS->LINK_INT_FLAG = WARM_RESET_FLAG;
USB30_Switch_Powermode(POWER_MODE_2);
USBSS->LINK_CTRL |= TX_WARM_RESET;
while(USBSS->LINK_STATUS & RX_WARM_RESET);
USBSS->LINK_CTRL &= ~TX_WARM_RESET;
USB30_Device_Setaddress(0);
}
if(USBSS->LINK_INT_FLAG & HOT_RESET_FLAG) //The host may send hot reset,Note the configuration of the endpoint
{
USBSS->USB_CONTROL |= 1 << 31;
USBSS->LINK_INT_FLAG = HOT_RESET_FLAG; // HOT RESET begin
USBSS->UEP0_TX_CTRL = 0;
USB30_IN_Set(ENDP_1, DISABLE, NRDY, 0, 0);
USB30_IN_Set(ENDP_2, DISABLE, NRDY, 0, 0);
USB30_IN_Set(ENDP_3, DISABLE, NRDY, 0, 0);
USB30_IN_Set(ENDP_4, DISABLE, NRDY, 0, 0);
USB30_IN_Set(ENDP_5, DISABLE, NRDY, 0, 0);
USB30_IN_Set(ENDP_6, DISABLE, NRDY, 0, 0);
USB30_IN_Set(ENDP_7, DISABLE, NRDY, 0, 0);
USB30_OUT_Set(ENDP_1, NRDY, 0);
USB30_OUT_Set(ENDP_2, NRDY, 0);
USB30_OUT_Set(ENDP_3, NRDY, 0);
USB30_OUT_Set(ENDP_4, NRDY, 0);
USB30_OUT_Set(ENDP_5, NRDY, 0);
USB30_OUT_Set(ENDP_6, NRDY, 0);
USB30_OUT_Set(ENDP_7, NRDY, 0);
USB30_Device_Setaddress(0);
USBSS->LINK_CTRL &= ~TX_HOT_RESET; // HOT RESET end
}
if(USBSS->LINK_INT_FLAG & LINK_GO_U1_FLAG) // device enter U1
{
USB30_Switch_Powermode(POWER_MODE_1);
USBSS->LINK_INT_FLAG = LINK_GO_U1_FLAG;
}
if(USBSS->LINK_INT_FLAG & LINK_GO_U2_FLAG) // device enter U2
{
USB30_Switch_Powermode(POWER_MODE_2);
USBSS->LINK_INT_FLAG = LINK_GO_U2_FLAG;
}
if(USBSS->LINK_INT_FLAG & LINK_GO_U3_FLAG) // device enter U2
{
USB30_Switch_Powermode(POWER_MODE_2);
USBSS->LINK_INT_FLAG = LINK_GO_U3_FLAG;
}
}
/*******************************************************************************
* @fn EP2_OUT_Callback
*
* @brief USB3.0 endpoint2 out callback.
*
* @return None
*/
void EP2_OUT_Callback()
{
UINT16 rx_len;
UINT8 nump;
UINT8 status;
USB30_OUT_Status(ENDP_2,&nump,&rx_len,&status);
USBByteCount = rx_len;
USB30_OUT_ClearIT(ENDP_2);
USB30_OUT_Set( ENDP_2 , NRDY , 0 );
DownloadPoint2_Busy = 0;
}
/*******************************************************************************
* @fn EP2_IN_Callback
*
* @brief USB3.0 endpoint2 in callback.
*
* @return None
*/
void EP2_IN_Callback()
{
UINT8 nump;
USB30_IN_ClearIT( ENDP_2 );
USB30_IN_Set( ENDP_2 , ENABLE , NRDY , 0 , 0);
UploadPoint2_Busy = 0;
}
/***************Endpointn IN Transaction Processing*******************/
void EP1_IN_Callback()
{
}
void EP3_IN_Callback()
{
}
void EP4_IN_Callback()
{
}
void EP5_IN_Callback()
{
}
void EP6_IN_Callback()
{
}
void EP7_IN_Callback()
{
}
/***************Endpointn OUT Transaction Processing*******************/
void EP1_OUT_Callback()
{
}
void EP3_OUT_Callback()
{
}
void EP4_OUT_Callback()
{
}
void EP5_OUT_Callback()
{
}
void EP6_OUT_Callback()
{
}
void EP7_OUT_Callback()
{
}
/*******************************************************************************
* @fn USB30_ITP_Callback
*
* @brief USB3.0 ITP callback function
*
* @return None
*/
void USB30_ITP_Callback(UINT32 ITPCounter)
{
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan
* PSL v2. You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
* NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the
* Mulan PSL v2 for more details.
*/
/*
* @Note
* Example routine to emulate a simulate USB-CDC Device,Use UART2(PA2/PA3).
*/
#include "xizi.h"
#include "board.h"
#include "shell.h"
#include "CH56x_common.h"
#include "CH56x_usb30.h"
#include "cdc.h"
/*******************************************************************************
* @fn main
*
* @brief main program
*
* @return None
*/
int UsbdCdcTest()
{
KPrintf("UsbdCdcTest start\n");
KPrintf("CH56x USB3.0 & USB2.0 device test(80MHz) !\n");
/* USB initialization */
TMR2_TimerInit1();
R32_USB_CONTROL = 0;
PFIC_EnableIRQ(USBSS_IRQn);
PFIC_EnableIRQ(LINK_IRQn);
PFIC_EnableIRQ(TMR0_IRQn);
R8_TMR0_INTER_EN = 1;
TMR0_TimerInit( 67000000 );
USB30D_init(ENABLE);
KPrintf("UsbdCdcTest USB30D_init OK\n");
while(1)
{
CDC_Uart_Deal();
}
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
UsbdCdcTest, UsbdCdcTest, test usbd cdc);