我在翻阅手册和学习Demo程序的时候,有以下几点问题。
当我设置UEP0_DMA=Ep0Buffer之后,是否就代表了当UIF_TRANSFER成功且进入UIS_TOKEN_SETUP,则其默认把FIFO中的8字节Setup包填入了Ep0Buffer中了?如果是的话,请问在不设置DMA的情况下,我是否可以通过什么方法自己读取FIFO中的数据?如果不是的话是哪里我理解错了。
当发送hid请求SetReport的时候,HID描述符我设置数据包大小是256,处理流程是否是这样,处理SETUP(识别指令)->循环处理OUT(在DMA地址或者FIFO中不断拿数据)->结束。
当发送hid请求GetReport的时候,HID描述符设置包大小256,则处理流程是否是,处理SETUP(识别指令)->循环处理IN(在DMA地址或者FIFO中把需要写的数据写入) ->结束。
我现在碰到的这个问题比较奇怪,我抄的官方HID的demo,但是始终无法走通第一条报文,系统总是下发Get_Descriptor,问我要设备描述符,可是我走串口调试,确实已经发过去了,可是系统依然不停向我发请求设备描述符,不知道问题在哪里。
另外,本例只使用低速模式和端点0,其他端点一律禁用。
start
host: 80 6 0 1 0 0 40 0
is dev scr,18,64
12 1 10 1 0 0 0 8
send..
11 11 22 22 3 1 0 0
send..
0 1
send..
host: 0 5 22 0 0 0 0 0
host: 80 6 0 1 0 0 40 0
is dev scr,18,64
12 1 10 1 0 0 0 8
send..
11 11 22 22 3 1 0 0
send..
0 1
send..
host: 0 5 23 0 0 0 0 0
根据log来看,第二次主机下发的数据怎么变成乱码了,不知道哪里出问题了
#include "CH552.H"
#include
#include
#include "usb_func.h"
#include "Debug.H"
UINT8X Ep0Buffer[THIS_ENDP0_SIZE + 2] _at_ 0x0000; //端点0 OUT&IN缓冲区,必须是偶地址
//UINT8X g_transbuf[256];
UINT8X SetupReq; //setup指令
UINT8X Ready, UsbConfig;
PUINT8 data_ptr; //要发送的数据指针
UINT16X data_len; //要接收或者发送的数据长度
UINT16X setup_len; //主机下发指令需要的长度
//USB_SETUP_REQ SetupReqBuf; //暂存Setup包
#define UsbSetupBuf ((PUSB_SETUP_REQ)Ep0Buffer)
/*设备描述符*/
UINT8C DevDesc[] = {0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, THIS_ENDP0_SIZE,
0x11, 0x11,
0x22, 0x22,
0x03, 0x01, //BCD 发行版本号
0x00, //厂商信息索引
0x00, //产品信息索引
0x00, //序列号索引
0x01}; //配置文件数
UINT8C CfgDesc[] =
{
0x09, 0x02, 27, 0x00, 0x01, 0x01, 0x04, 0x80, 0x19, //配置描述符
0x09, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, //接口描述符
0x09, 0x21, 0x00, 0x01, 0x00, 0x01, 0x22, 60, 0x00, //HID类描述符
};
/*字符串描述符 略*/
/*HID类报表描述符*/
UINT8C HIDRepDesc[] =
{
0x06, 0x00, 0xFF,
0x09, 0x01,
0xA1, 0x01,
0x06, 0x00, 0xFF,
0x09, 0x01,
0xA1, 0x01,
0x85, 0x01,
0x06, 0x01, 0xFF,
0x09, 0x02,
0x15, 0x00,
0x25, 0xFF,
0x96, 0x00, 0x01, //256
0x75, 0x08,
0xB1, 0x02,
0xC0,
0x06, 0x00, 0xFF,
0x09, 0x01,
0xA1, 0x01,
0x85, 0x02,
0x06, 0x02, 0xFF,
0x09, 0x02,
0x15, 0x00,
0x25, 0xFF,
0x96, 0x00, 0x01, //256
0x75, 0x08,
0xB1, 0x02,
0xC0,
0xC0};
/*******************************************************************************
* Function Name : usb_init()
* Description : USB设备模式配置,设备模式启动,收发端点配置,中断开启
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void usb_init()
{
IE_USB = 0;
USB_CTRL = 0x00; // 先设定USB设备模式
UDEV_CTRL = bUD_PD_DIS; // 禁止DP/DM下拉电阻
UDEV_CTRL |= bUD_LOW_SPEED; //选择低速12M模式
USB_CTRL |= bUC_LOW_SPEED;
UEP0_DMA = Ep0Buffer; //端点0数据传输地址
//UEP4_1_MOD &= ~(bUEP4_RX_EN | bUEP4_TX_EN); //端点0单64字节收发缓冲区
UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK; //OUT事务返回ACK,IN事务返回NAK
USB_DEV_AD = 0x00;
USB_CTRL |= bUC_DEV_PU_EN | bUC_INT_BUSY | bUC_DMA_EN; // 启动USB设备及DMA,在中断期间中断标志未清除前自动返回NAK
UDEV_CTRL |= bUD_PORT_EN; // 允许USB端口
USB_INT_FG = 0xFF; // 清中断标志
USB_INT_EN = bUIE_TRANSFER | bUIE_BUS_RST;
IE_USB = 1;
}
//处理usb standard setup请求
void usb_setup_standard_process()
{
UINT8X process_len;
process_len = 0;
printf("host: ");
outputdebug(Ep0Buffer , 8);
switch (UsbSetupBuf->bRequest)
{
case USB_GET_DESCRIPTOR:
switch (UsbSetupBuf->wValueH)
{
case USB_DESCR_TYP_DEVICE: //设备描述符
data_ptr = DevDesc;
data_len = sizeof(DevDesc);
printf("is dev scr,%d,%d\n", data_len, setup_len);
break;
case USB_DESCR_TYP_CONFIG: //配置描述符
printf("conf scr\n");
data_ptr = CfgDesc;
data_len = sizeof(CfgDesc);
break;
case USB_DESCR_TYP_REPORT: //报表描述符(HID)
printf("hid scr\n");
data_ptr = HIDRepDesc;
data_len = sizeof(HIDRepDesc);
break;
default:
printf("err scr\n");
data_len = 0;
data_ptr = DevDesc;
break;
}
process_len = (data_len >= THIS_ENDP0_SIZE ? THIS_ENDP0_SIZE : data_len);
if (process_len > 0)
{
memcpy(Ep0Buffer, data_ptr, process_len);
outputdebug(Ep0Buffer, process_len);
data_len -= process_len;
data_ptr += process_len;
}
UEP0_T_LEN = process_len;
UEP0_CTRL = bUEP_R_TOG | bUEP_T_TOG | UEP_R_RES_ACK | UEP_T_RES_ACK; //返回应答ACK
break;
default:
break;
}
return;
}
//处理usb setup请求
void usb_setup_process()
{
if (8 != USB_RX_LEN) //接收到的setup长度不对,则返回STALL不支持
{
UEP0_CTRL = bUEP_R_TOG | bUEP_T_TOG | UEP_R_RES_STALL | UEP_T_RES_STALL; //STALL
return;
}
//开始处理setup请求
setup_len = UsbSetupBuf->wLengthH << 8;
setup_len += UsbSetupBuf->wLengthL;
if ((UsbSetupBuf->bRequestType & USB_REQ_TYP_MASK) == USB_REQ_TYP_STANDARD) //处理标准USB请求
{
usb_setup_standard_process();
}
return;
}
//主机要拿数据
void usb_inbuf_process()
{
UINT8X process_len;
process_len = (data_len >= THIS_ENDP0_SIZE ? THIS_ENDP0_SIZE : data_len);
memcpy(Ep0Buffer, data_ptr, process_len);
data_len -= process_len;
data_ptr += process_len;
UEP0_T_LEN = process_len;
UEP0_CTRL ^= bUEP_T_TOG; //同步标记位翻转
printf("send..\n");
outputdebug(Ep0Buffer, process_len);
return;
}
//主机发来数据
void usb_outbuf_process()
{
}
/*******************************************************************************
* Function Name : usb_interrupt()
* Description : CH559USB中断处理函数
*******************************************************************************/
void usb_interrupt(void) interrupt INT_NO_USB //USB中断服务程序,使用寄存器组1
{
if (UIF_TRANSFER) //USB传输完成标记
{
switch (USB_INT_ST & MASK_UIS_TOKEN)
{
case UIS_TOKEN_SETUP:
usb_setup_process();
break;
case UIS_TOKEN_IN:
usb_inbuf_process();
break;
case UIS_TOKEN_OUT:
usb_outbuf_process();
break;
default:
break;
}
UIF_TRANSFER = 0; //写0清空中断
}
else if (UIF_BUS_RST)
{
UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
USB_DEV_AD = 0x00;
UIF_SUSPEND = 0;
UIF_TRANSFER = 0;
UIF_BUS_RST = 0; //清中断标志
}
return;
}