/*
============================================================================
Name : ch56x_usb1dev372.c
Author : CC
Version :
Copyright : Your copyright notice
Description : USB1 Device mode, simulate a device of CH372
============================================================================
*/
#include <stdio.h>
#include <nds32_isr.h>
#include <nds32_intrinsic.h>
#include "CH568SFR.H"
#include "MYdebug.H"
#include "ch56x_usb1dev372.h"
//------ 设备模式 USB1
// 设备描述符
const UINT8 MyDevDescr[] = { 0x12, 0x01, 0x00, 0x02, 0xFF, 0x80, 0x37, THIS_ENDP0_SIZE,
0x48, 0x43, 0x37, 0x55, /* 厂商ID和产品ID */
0x00, 0x01, 0x01, 0x02, 0x00, 0x01
};
// 配置描述符
const UINT8 MyCfgDescr[] = { 0x09, 0x02, 0x4a, 0x00, 0x01, 0x01, 0x00, 0x80, 0x32, //配置描述符
0x09, 0x04, 0x00, 0x00, 0x08, 0xFF, 0x80, 0x37, 0x00, //接口描述符
0x07, 0x05, 0x84, 0x02, 0x00, 0x02, 0x00, //端点描述符,
0x07, 0x05, 0x04, 0x02, 0x00, 0x02, 0x00,
0x07, 0x05, 0x83, 0x02, 0x00, 0x02, 0x00,
0x07, 0x05, 0x03, 0x02, 0x00, 0x02, 0x00,
0x07, 0x05, 0x82, 0x02, 0x00, 0x02, 0x00,
0x07, 0x05, 0x02, 0x02, 0x00, 0x02, 0x00,
0x07, 0x05, 0x81, 0x02, 0x00, 0x02, 0x0A,
0x07, 0x05, 0x01, 0x02, 0x00, 0x02, 0x0A,
};
// 语言描述符
const UINT8 MyLangDescr[] = { 0x04, 0x03, 0x09, 0x04 };
// 厂家信息
const UINT8 MyManuInfo[] = { 0x0E, 0x03, 'w', 0, 'c', 0, 'h', 0, '.', 0, 'c', 0, 'n', 0 };
// 产品信息
const UINT8 MyProdInfo[] = { 0x0C, 0x03, 'C', 0, 'H', 0, '5', 0, '6', 0, 'x', 0 };
__attribute__ ((aligned(4)))UINT8 Ep0Buffer[64 + 512*2] ; // EP1+EP4 OUT&IN, must 4字节对齐
__attribute__ ((aligned(4)))UINT8 Ep1Buffer[512*2] ; // EP1 IN+OUT, must 4字节对齐
__attribute__ ((aligned(4)))UINT8 Ep2Buffer[512*2] ; // EP2 IN+OUT, must 4字节对齐
__attribute__ ((aligned(4)))UINT8 Ep3Buffer[512*2] ; // EP3 IN+OUT, must 4字节对齐
#define UsbSetupBuf ((PUSB_SETUP_REQ)Ep0Buffer)
#define UsbEp1OUTBuf ((PUINT8)&Ep1Buffer[0])
#define UsbEp1INBuf ((PUINT8)&Ep1Buffer[512])
#define UsbEp2OUTBuf ((PUINT8)&Ep2Buffer[0])
#define UsbEp2INBuf ((PUINT8)&Ep2Buffer[512])
#define UsbEp3OUTBuf ((PUINT8)&Ep3Buffer[0])
#define UsbEp3INBuf ((PUINT8)&Ep3Buffer[512])
#define UsbEp4OUTBuf ((PUINT8)&Ep0Buffer[64])
#define UsbEp4INBuf ((PUINT8)&Ep0Buffer[64+512])
UINT16 SetupLen; /* USB控制传输传输长度 */
UINT8V SetupReqCode; /* USB控制传输命令码 */
UINT8V UsbInterCfg; /* USB设备接口配置 */
PUINT8 pDescr; /* 上传指针 */
UINT8 DevAddr; /* 设备地址 */
UINT8 UsbConfig = 0; // USB配置标志
/*******************************************************************************
* Function Name : USB1DeviceInit
* Description : USB1 设备模式初始化
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void USB1DeviceInit( void ) // 初始化USB设备
{
/* 全局寄存器 */
R8_USB1_CTRL = bUC_CLR_ALL; //清空中断标志和FIFO
R8_USB1_CTRL = UCST_HS | bUC_INT_BUSY |bUC_DMA_EN; //设备模式,高速,
R8_USB1_SUSPEND = 0; //不挂起
R8_USB1_DEV_AD = 0x00; //设备地址0
R8_USB1_INT_FG = 0xff; //清除中断标志
R8_USB1_INT_EN = bUIE_FIFO_OV | bUIE_SUSPEND | bUIE_TRANSFER | bUIE_BUS_RST; //中断使能
R8_UEP4_1_MOD1 = 0;
R8_UEP2_3_MOD1 = 0;
/* 设备端点设置 */
//ENDP0
R8_UEP0_TX_CTRL1 = UEP_T_RES_NAK;
R8_UEP0_RX_CTRL1 = UEP_R_RES_ACK;
R16_UEP0_MAX_LEN1 = THIS_ENDP0_SIZE; //端点0接收包的最大长度为64字节
R16_UEP0_DMA1 = (UINT32)Ep0Buffer;
//ENDP1
R8_UEP1_TX_CTRL1 = UEP_T_RES_NAK | bUEP_AUTO_TOG;
R8_UEP1_RX_CTRL1 = UEP_R_RES_ACK| bUEP_AUTO_TOG;
R8_UEP4_1_MOD1 |= bUEP1_TX_EN | bUEP1_RX_EN;
R16_UEP1_MAX_LEN1 = 512;
R16_UEP1_DMA1 = (UINT32)Ep1Buffer;
//ENDP2
R8_UEP2_TX_CTRL1 = UEP_T_RES_NAK| bUEP_AUTO_TOG;
R8_UEP2_RX_CTRL1 = UEP_R_RES_ACK| bUEP_AUTO_TOG;
R8_UEP2_3_MOD1 |= bUEP2_RX_EN | bUEP2_TX_EN;
R16_UEP2_MAX_LEN1 = 512;
R16_UEP2_DMA1 = (UINT32)Ep2Buffer;
//ENDP3
R8_UEP3_TX_CTRL1 = UEP_T_RES_NAK | bUEP_AUTO_TOG;
R8_UEP3_RX_CTRL1 = UEP_R_RES_ACK| bUEP_AUTO_TOG;
R8_UEP2_3_MOD1 |= bUEP3_RX_EN | bUEP3_TX_EN;
R16_UEP3_MAX_LEN1 = 512;
R16_UEP3_DMA1 = (UINT32)Ep3Buffer;
//ENDP4
R8_UEP4_TX_CTRL1 = UEP_T_RES_NAK; //不支持自动翻转
R8_UEP4_RX_CTRL1 = UEP_R_RES_ACK;
R8_UEP4_1_MOD1 |= bUEP4_RX_EN | bUEP4_TX_EN;
R16_UEP4_MAX_LEN1 = 512;
R8_USB1_CTRL |= bUC_DEV_PU_EN; //设备连接
}
/*******************************************************************************
* Function Name : USB1DevIntDeal
* Description : USB1 设备中断处理
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void USB1DevIntDeal(void)
{
UINT8 intstatus;
UINT16 i, l;
if ( R8_USB1_INT_FG & UIF_TRANSFER ) // USB传输完成
{
if ( R8_USB1_INT_ST & bUIS_IS_NAK ) //接收到主机IN包
{
printf("NAK\n");
}
else
{
intstatus = R8_USB1_INT_ST & (MASK_UIS_TOKEN | MASK_UIS_ENDP);
if(intstatus == (UIS_TOKEN_OUT|4)) /* endpoint 4 下传 */
{
if(R8_USB1_INT_ST&bUIS_TOG_OK)
{
R8_UEP4_RX_CTRL1 = R8_UEP4_RX_CTRL1 ^ 0x08; //手动翻转
l = R16_USB1_RX_LEN;
for(i=0; i<l; i++)
UsbEp4INBuf[i] = ~UsbEp4OUTBuf[i]; //按位取反上传
R16_UEP4_T_LEN1 = l;
R8_UEP4_TX_CTRL1 = (R8_UEP4_TX_CTRL1 & ~ MASK_UEP_T_RES) | UEP_T_RES_ACK;
}
}
if(intstatus == (UIS_TOKEN_OUT|3)) /* endpoint 3 下传 */
{
if(R8_USB1_INT_ST&bUIS_TOG_OK)
{
//R8_UEP3_RX_CTRL1 = R8_UEP3_RX_CTRL1 ^ 0x08; //翻转
l = R16_USB1_RX_LEN;
for(i=0; i<l; i++)
UsbEp3INBuf[i] = ~UsbEp3OUTBuf[i]; //按位取反上传
R16_UEP3_T_LEN1 = l;
R8_UEP3_TX_CTRL1 = (R8_UEP3_TX_CTRL1 & ~ MASK_UEP_T_RES) | UEP_T_RES_ACK;
}
}
if(intstatus == (UIS_TOKEN_OUT|2)) /* endpoint 2 下传 */
{
if(R8_USB1_INT_ST&bUIS_TOG_OK)
{
//R8_UEP2_RX_CTRL1 = R8_UEP2_RX_CTRL1 ^ 0x08; //翻转
l = R16_USB1_RX_LEN;
for(i=0; i<l; i++)
UsbEp2INBuf[i] = ~UsbEp2OUTBuf[i]; //按位取反上传
R16_UEP2_T_LEN1 = l;
R8_UEP2_TX_CTRL1 = (R8_UEP2_TX_CTRL1 & ~ MASK_UEP_T_RES) | UEP_T_RES_ACK;
}
}
if(intstatus == (UIS_TOKEN_OUT|1)) /* endpoint 1 下传 */
{
if(R8_USB1_INT_ST&bUIS_TOG_OK)
{
//R8_UEP1_RX_CTRL1 = R8_UEP1_RX_CTRL1 ^ 0x08; //翻转
l = R16_USB1_RX_LEN;
for(i=0; i<l; i++)
UsbEp1INBuf[i] = ~UsbEp1OUTBuf[i]; //按位取反上传
R16_UEP1_T_LEN1 = l;
R8_UEP1_TX_CTRL1 = (R8_UEP1_TX_CTRL1 & ~ MASK_UEP_T_RES) | UEP_T_RES_ACK;
}
}
if(intstatus == (UIS_TOKEN_IN|4)) /* endpoint 4 上传 */
{
R8_UEP4_TX_CTRL1 = R8_UEP4_TX_CTRL1 ^ 0x08; //手动翻转
R8_UEP4_TX_CTRL1 = (R8_UEP4_TX_CTRL1 & ~ MASK_UEP_T_RES) | UEP_T_RES_NAK;
}
if(intstatus == (UIS_TOKEN_IN|3)) /* endpoint 3 上传 */
{
R8_UEP3_TX_CTRL1 = (R8_UEP3_TX_CTRL1 & ~ MASK_UEP_T_RES) | UEP_T_RES_NAK;
}
if(intstatus == (UIS_TOKEN_IN|2)) /* endpoint 2 上传 */
{
R8_UEP2_TX_CTRL1 = (R8_UEP2_TX_CTRL1 & ~ MASK_UEP_T_RES) | UEP_T_RES_NAK;
}
if(intstatus == (UIS_TOKEN_IN|1)) /* endpoint 1 上传 */
{
R8_UEP1_TX_CTRL1 = (R8_UEP1_TX_CTRL1 & ~ MASK_UEP_T_RES) | UEP_T_RES_NAK;
}
if(intstatus == (UIS_TOKEN_SETUP)) /* endpoint 0# SETUP */
{
USB1Dev_EDP0_Setup_Deal();
}
if(intstatus == (UIS_TOKEN_IN)) /* endpoint 0# IN */
{
USB1Dev_EDP0_IN_Deal();
}
if(intstatus == (UIS_TOKEN_OUT)) /* endpoint 0# OUT */
{
USB1Dev_EDP0_OUT_Deal();
}
}
R8_USB1_INT_FG = UIF_TRANSFER;
}
else if ( R8_USB1_INT_FG & UIF_SUSPEND ) // USB总线挂起/唤醒完成
{
R8_USB1_INT_FG = UIF_SUSPEND;
printf("Suspend\n");
}
else if( R8_USB1_INT_FG & UIF_BUS_RST ) //USB设备复位
{
R8_UEP0_TX_CTRL1 = UEP_T_RES_NAK;
R8_UEP0_RX_CTRL1 = UEP_R_RES_ACK;
R8_UEP1_TX_CTRL1 = UEP_T_RES_NAK | bUEP_AUTO_TOG;
R8_UEP1_RX_CTRL1 = UEP_R_RES_ACK | bUEP_AUTO_TOG;
R8_UEP2_TX_CTRL1 = UEP_T_RES_NAK | bUEP_AUTO_TOG;
R8_UEP2_RX_CTRL1 = UEP_R_RES_ACK | bUEP_AUTO_TOG;
R8_UEP3_TX_CTRL1 = UEP_T_RES_NAK | bUEP_AUTO_TOG;
R8_UEP3_RX_CTRL1 = UEP_R_RES_ACK | bUEP_AUTO_TOG;
R8_UEP4_TX_CTRL1 = UEP_T_RES_NAK;
R8_UEP4_RX_CTRL1 = UEP_R_RES_ACK;
R8_USB1_DEV_AD = 0;
DevAddr = 0;
R8_USB1_INT_FG = UIF_BUS_RST;
printf("Reset!\n");
}
else if( R8_USB1_INT_FG & UIF_FIFO_OV ) //FIFO溢出中断
{
R8_USB1_INT_FG = UIF_FIFO_OV;
printf("FIFOOV!\n");
}
}
/*******************************************************************************
* Function Name : USB1Dev_EDP0_Setup_Deal
* Description : USB1 设备模式端点0 setup处理
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void USB1Dev_EDP0_Setup_Deal(void)
{
UINT16 len;
UINT8 status, i;
UINT8 buf[8];
/* 获取SETUP包 */
len = R16_USB1_RX_LEN;
if ( len == sizeof( USB_SETUP_REQ ) )
{
// for(i=0; i<8; i++) printf("%02x ", Ep0Buffer[i]); printf("\n");
SetupLen = (UINT16)(UsbSetupBuf->wLengthH)<<8|(UsbSetupBuf->wLengthL); //请求数据长度
SetupReqCode = UsbSetupBuf->bRequest; //命令码
/* 分析并处理当前的SETUP包 */
len = 0; // 默认为成功并且上传0长度
status = 0;
if (( UsbSetupBuf->bRequestType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD ) /* 非标准请求 */
{
status = 0xFF; // 操作失败
}
else /* 标准请求 */
{
switch( SetupReqCode ) // 请求码
{
case USB_GET_DESCRIPTOR:
switch( UsbSetupBuf->wValueH )
{
case 0x01: // 设备描述符
pDescr = (PUINT8)( &MyDevDescr[0] );
len = sizeof( MyDevDescr );
break;
case 0x02: // 配置描述符
pDescr = (PUINT8)( &MyCfgDescr[0] );
len = sizeof( MyCfgDescr );
break;
case 0x03: // 字符串描述符
switch( UsbSetupBuf->wValueL )
{
case 1: //厂商字符串描述符
pDescr = (PUINT8)( &MyManuInfo[0] );
len = sizeof( MyManuInfo );
break;
case 2: //产品字符串描述符
pDescr = (PUINT8)( &MyProdInfo[0] );
len = sizeof( MyProdInfo );
break;
case 0: //语言描述符
pDescr = (PUINT8)( &MyLangDescr[0] );
len = sizeof( MyLangDescr );
break;
default:
status = 0xFF; // 不支持的字符串描述符
break;
}
break;
default:
status = 0xFF; // 不支持的描述符类型
break;
}
break;
case USB_SET_ADDRESS:
DevAddr = UsbSetupBuf->wValueL; // 暂存USB设备地址
break;
case USB_GET_CONFIGURATION:
buf[0] = UsbConfig;
pDescr = buf;
if ( SetupLen >= 1 ) len = 1;
break;
case USB_SET_CONFIGURATION:
UsbConfig = UsbSetupBuf->wValueL;
break;
case USB_CLEAR_FEATURE:
if ( ( UsbSetupBuf->bRequestType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP ) // 清除端点
{
switch( UsbSetupBuf->wIndexL ) //复位同步触发位,清除STALL
{
case 0x82:
R8_UEP2_TX_CTRL1 = R8_UEP2_TX_CTRL1 & ~ ( MASK_UEP_T_RES ) | UEP_T_RES_NAK;
break;
case 0x02:
R8_UEP2_RX_CTRL1 = R8_UEP2_RX_CTRL1 & ~ ( MASK_UEP_R_RES ) | UEP_R_RES_ACK;
break;
case 0x81:
R8_UEP1_TX_CTRL1 = R8_UEP1_TX_CTRL1 & ~ ( MASK_UEP_T_RES ) | UEP_T_RES_NAK;
break;
case 0x01:
R8_UEP1_RX_CTRL1 = R8_UEP1_RX_CTRL1 & ~ ( MASK_UEP_R_RES ) | UEP_R_RES_ACK;
break;
default:
status = 0xFF; // 不支持的端点
break;
}
}
else if (( UsbSetupBuf->bRequestType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_DEVICE) //清除设备
{
/* 设备休眠 */
}
else status = 0xFF; // 不是端点不支持
break;
case USB_SET_FEATURE:
if ( ( UsbSetupBuf->bRequestType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP ) // 设置端点
{
switch((UINT16)(UsbSetupBuf->wIndexH)<<8|(UsbSetupBuf->wIndexL)) //复位同步触发位,清除STALL
{
case 0x82:
R8_UEP2_TX_CTRL1 |= UEP_T_RES_STALL;
break;
case 0x02:
R8_UEP2_RX_CTRL1 |= UEP_T_RES_STALL;
break;
case 0x81:
R8_UEP1_TX_CTRL1 |= UEP_T_RES_STALL;
break;
case 0x01:
R8_UEP1_RX_CTRL1 |= UEP_T_RES_STALL;
break;
default:
status = 0xFF; // 不支持的端点
break;
}
}
else if (( UsbSetupBuf->bRequestType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_DEVICE) //设置设备
{
/* 设备唤醒 */
}
else status = 0xFF; // 不是端点不支持
break;
case USB_SET_INTERFACE:
UsbInterCfg = UsbSetupBuf->wIndexL;
break;
case USB_GET_INTERFACE:
buf[0] = UsbInterCfg;
pDescr = buf;
if ( SetupLen >= 1 ) len = 1;
break;
case USB_GET_STATUS:
if (( UsbSetupBuf->bRequestType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP ) // 获取端点状态
{
switch((UINT16)(UsbSetupBuf->wIndexH)<<8|(UsbSetupBuf->wIndexL))
{
case 0x82:
buf[0] = ((R8_UEP2_TX_CTRL1&0x11) == UEP_T_RES_STALL) ? 0x01 : 0x00 ;
break;
case 0x02:
buf[0] = ((R8_UEP2_RX_CTRL1&0x11) == UEP_T_RES_STALL) ? 0x01 : 0x00 ;
break;
case 0x81:
buf[0] = ((R8_UEP1_TX_CTRL1&0x11) == UEP_T_RES_STALL) ? 0x01 : 0x00 ;
break;
case 0x01:
buf[0] = ((R8_UEP1_RX_CTRL1&0x11) == UEP_T_RES_STALL) ? 0x01 : 0x00 ;
break;
default:
status = 0xFF; // 不支持的端点
break;
}
buf[1] = 0x00;
pDescr = buf;
len = 2;
}
else if (( UsbSetupBuf->bRequestType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_DEVICE ) // 获取设备状态
{
buf[0] = 0x00; //填充当前设备状态
buf[1] = 0x00;
pDescr = buf;
len = 2;
}
break;
default:
status = 0xFF; // 操作失败
break;
}
}
}
else
{
status = 0xFF; // SETUP包长度错误
}
if ( status == 0xFF ) // 操作失败
{
SetupReqCode = 0xFF;
R8_UEP0_RX_CTRL1 = UEP_DATA1 | UEP_R_RES_STALL;
R8_UEP0_TX_CTRL1 = UEP_DATA1 | UEP_T_RES_STALL;
}
else
{
SetupLen = (SetupLen<len) ? SetupLen : len; //这次传输上传数据长度
if(SetupLen)
{
if(UsbSetupBuf->bRequestType & 0x80) //上传数据
{
len = (SetupLen<THIS_ENDP0_SIZE) ? SetupLen : THIS_ENDP0_SIZE; //本次数据上传长度
memcpy( Ep0Buffer, pDescr, len ); /* 加载上传数据 */
R16_UEP0_T_LEN1 = len;
R8_UEP0_TX_CTRL1 = UEP_DATA1 | UEP_T_RES_ACK; // 默认数据包是DATA1
SetupLen -= len;
pDescr += len;
}
else //下传数据
{
R16_UEP0_T_LEN1 = 0; // 虽然尚未到状态阶段,但是提前预置上传0长度数据包以防主机提前进入状态阶段
R8_UEP0_RX_CTRL1 = UEP_DATA1 | UEP_R_RES_ACK; // 默认数据包是DATA1
}
}
else
{
R16_UEP0_T_LEN1 = 0;
R8_UEP0_TX_CTRL1 = UEP_DATA1 | UEP_T_RES_ACK; //状态阶段
}
}
}
/*******************************************************************************
* Function Name : USB1Dev_EDP0_IN_Deal
* Description : USB1 设备模式端点0 IN处理
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void USB1Dev_EDP0_IN_Deal(void)
{
UINT16 len;
switch(SetupReqCode)
{
case USB_GET_DESCRIPTOR:
len = (SetupLen<THIS_ENDP0_SIZE) ? SetupLen : THIS_ENDP0_SIZE; //本次数据上传长度
memcpy( Ep0Buffer, pDescr, len ); /* 加载上传数据 */
R16_UEP0_T_LEN1 = len;
R8_UEP0_TX_CTRL1 ^= UEP_DATA1; // 翻转
SetupLen -= len;
pDescr += len;
break;
case USB_SET_ADDRESS:
R16_UEP0_T_LEN1 = 0;
R8_UEP0_TX_CTRL1 = UEP_DATA0 | UEP_T_RES_NAK;
R8_USB1_DEV_AD = DevAddr;
break;
default:
R16_UEP0_T_LEN1 = 0;
R8_UEP0_TX_CTRL1 = UEP_DATA0 | UEP_T_RES_NAK;
R8_UEP0_RX_CTRL1 = UEP_DATA0 | UEP_R_RES_ACK;
break;
}
}
/*******************************************************************************
* Function Name : USB1Dev_EDP0_OUT_Deal
* Description : USB1 设备模式端点0 OUT处理
* Input : None
* Output : None
* Return : None
*******************************************************************************/
UINT16 USB1Dev_EDP0_OUT_Deal(void)
{
UINT16 len;
len = R16_USB1_RX_LEN;
return (len);
}
2. 对代码进行了格式化,使用4个空格代替代码中的 Tab