STM32-USB鼠标解析(4)

2019-08-30 20:01

//如果出现表示同时TX和RX同时置位。 }

else if ((wEPVal &EP_SETUP) != 0) //我们的程序会执行到这里 {

_ClearEP_CTR_RX(ENDP0);

Setup0_Process();

//主要是调用该程序来处理主机请求。

_SetEPRxStatus(ENDP0, SaveRState);

_SetEPTxStatus(ENDP0, SaveTState);

return; }

else if ((wEPVal & EP_CTR_RX) != 0) //暂时不执行的代码先删除掉。 { } }

}/* if(EPindex == 0) */

后面处理其他端点的代码就先不看了。

}/* while(...) */

(3)Setup0_Process()函数的执行分析

这个函数执行的时候,主机发来的请求数据包已经存在于RxADDR缓冲区了。大部分的标志位已经清除,除了SETUP位,这个味将由下一个令牌包自动清除。 进入处理函数:

pBuf.b = PMAAddr + (u8 *)(_GetEPRxAddr(ENDP0) * 2); //这是取得端点0接收缓冲区的起始地址。

PMAAddr是包缓冲区起始地址,_GetEPRxAddr(ENDP0)获得端点0描述符表里的接收缓冲区地址,为什么要乘以2呢?大概因为描述符表里地址项为16位,使用的是相对偏移。

if (pInformation->ControlState != PAUSE) {

pInformation->USBbmRequestType = *pBuf.b++; //请求类型,表明方向和接收对象(设备、接口还是端点)此时为80,表明设备到主机

pInformation->USBbRequest = *pBuf.b++; /*请求代码,第一次时应该是6,表明主机要获取设备描述符。*/

pBuf.w++;

pInformation->USBwValue = ByteSwap(*pBuf.w++); /* wValue */

pBuf.w++;

//我觉得这里可能有些问题。

pInformation->USBwIndex

= ByteSwap(*pBuf.w++); /* wIndex */

pBuf.w++;

pInformation->USBwLength = *pBuf.w; /* wLength */ }

pInformation->ControlState = SETTING_UP;

if (pInformation->USBwLength == 0) {

NoData_Setup0();

}

else {

Data_Setup0();

//这次是有数据传输的,所以有进入该该函数。 }

return Post0_Process();

(4)Data_Setup0()函数的执行分析

CopyRoutine = NULL; //这是一个函数指针,由用户提供。

wOffset = 0;

if (Request_No == GET_DESCRIPTOR) //如果是获取设备描述符 {

if(Type_Recipient==(STANDARD_REQUEST| EVICE_RECIPIENT)) {

u8 wValue1 = pInformation->USBwValue1;

if (wValue1 == DEVICE_DESCRIPTOR) {

CopyRoutine = pProperty->GetDeviceDescriptor;

} //获取设备描述符的操作由用户提供。

if (CopyRoutine) {

pInformation->Ctrl_Info.Usb_wOffset = wOffset;

pInformation->Ctrl_Info.CopyData = CopyRoutine;

(*CopyRoutine)(0); //这个函数这里调用的目的只是设置了pInformation中需要写入的描述符的长度。

Result = USB_SUCCESS; }

if (ValBit(pInformation->USBbmRequestType, 7)) //此时为80 {

//上面这个语句主要是判断传输方向。如果为1,则是设备到主机

vu32 wLength = pInformation->USBwLength;这个一般是64

if (pInformation->Ctrl_Info.Usb_wLength> wLength) {

//设备描述符长度18

pInformation->Ctrl_Info.Usb_wLength = wLength; }

//有些细节暂时先放着

pInformation->Ctrl_Info.PacketSize = pProperty->MaxPacketSize;

DataStageIn();

//最主要是调用这个函数完成描述符的输出准备 }

(5)DataStageIn()函数的执行分析 以下是主要执行代码:

DataBuffer = (*pEPinfo->CopyData)(Length); //这个是取得用户描述符缓冲区的地址。这里共18个字节

UserToPMABufferCopy(DataBuffer, GetEPTxAddr(ENDP0), Length);//这个函数将设备描述符复制到用户的发送缓冲区。

SetEPTxCount(ENDP0, Length); //设置发送字节的数目、18

pEPinfo->Usb_wLength -= Length;等于0

pEPinfo->Usb_wOffset += Length;偏移到18

vSetEPTxStatus(EP_TX_VALID); //使能端点发送,只要主机的IN令牌包一来,SIE就会将描述符返回给主机。

USB_StatusOut();/*这个实际上是使接收也有效,主机可取消IN。*/ Expect_Status_Out:

pInformation->ControlState = ControlState;

(6)执行流程返回到CTR_LP(void)

_SetEPRxStatus(ENDP0, SaveRState);

_SetEPTxStatus(ENDP0, SaveTState);

//由于vSetEPTxStatus(EP_TX_VALID)实际改变了SaveTState,所以此时端点发送已经使能。 return;

(7)主机的IN令牌包

获取描述符的控制传输进入第二阶段,主机首先发一个IN令牌包,由于端点0发送有效,SIE将数据返回主机。 主机方返回一个ACK后,主机发送数据的CTR标志置位,DIR=0,EP_ID=0,表明主机正确收到了用户发过去的描述符。固件程序由此进入中断。 此时是由IN引起的。

主要是调用In0_Process()完成剩下的工作。

(7)追踪进入函数In0_Process()

此时实际上设备返回描述符已经成功了。

这一次还是调用DataStageIn()函数,但是目的只是期待主机的0状态字节输出了。

if ((ControlState == IN_DATA) || (ControlState ==


STM32-USB鼠标解析(4).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:关于公布保留和废止规范性文件的通知(河北省住房和城乡建设厅

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: