STM32-USB鼠标解析(3)

2019-08-30 20:01

/* Selected interface of current configuration */

u8 Current_AlternateSetting;/* Selected Alternate Setting of current

interface*/

ENDPOINT_INFO Ctrl_Info; //端点信息结构体 }DEVICE_INFO;

最后调用pProperty->Init(),实质就是调用Joystick_init(void)。

在这个函数中,首先获取设备版本,并转换为Unicode存入版本号字符串。

——Get_SerialNum();

设备当前配置置为0。然后调用PowerOn(),这个函数实质上将D+上拉,此时USB设备就能被集线器检测到了。因此分析进入下一个流程。

2、进入设备检测状态

(1)在PowerOn()中执行的情况。

在USB_init()中调用PowerOn(),而它先调用USB_Cable_Config(ENABLE),这个函数实质上将USB连接控制线设置为低电平,然后设备就可以检测到设备了。

当集线器报告设备连接状态,并收到主机指令后,会复位USB总线,这需要一定的时间(这段时间内设备应该准备好处理复位指令)。但是现在设备初始化程序将继续往下进行,因为它还没有使能复位中断。

wRegVal = CNTR_FRES;

_SetCNTR(wRegVal);

//这句话实际上使能了USB模块的电源,因为上电复位时,CNTR寄存器的断电控制为PDWN位是1,模块是断电的。

这句话虽然将强制复位USB模块,但由于复位中断允许位没有使能,不会引起复位中断,而间接上由使PDWN=0,模块开始工作。

_SetCNTR是一个宏,将wRegVal赋值给CNTR寄存器,此时所有的中断被屏蔽。

再接下来两句指令又将清除复位信号。

然后清除所有的状态位。——_SetISTR(0); 接下来是很关键的两句话:

wInterrupt_Mask=CNTR_RESETM| CNTR_SUSPM | CNTR_WKUPM;

_SetCNTR(wInterrupt_Mask);

后面一个语句执行后,复位中断已经被允许,而此时集线器多半已经开始复位端口了。或者说稍微有限延迟,设备固件还能继续初始化一些部件,但已经不会影响整个工作流程了。

所以接下来,分析直接进入复位中断。 (2)复位中断的处理。

当复位中断允许、且总线被集线器复位的时候,固件程序进入USB_LP中断。 中断程序直接调用USB_Istr(void)程序。 接下来讲对中断位进行判断:

if (wIstr & ISTR_RESET & wInterrupt_Mask) {

_SetISTR((u16)CLR_RESET); //先清除复位中断位

Device_Property.Reset();

//进入设备定义的复位过程。实际上是调用JoyStick_Reset()函数进行处理。 }

(3)JoyStick_Reset()函数的处理。 这里将一句句来分析:

void Joystick_Reset(void) {

pInformation->Current_Configuration = 0; //当前配置为0

pInformation->Current_Interface = 0;/当前接口为0

pInformation->Current_Feature = Joystick_ConfigDescriptor[7];

//需要总线供电

SetBTABLE(BTABLE_ADDRESS);//设置包缓冲区地址。

SetEPType(ENDP0, EP_CONTROL); //端点0为控制端点

SetEPTxStatus(ENDP0, EP_TX_STALL);

//端点状态为发送无效,也就是主机IN令牌包来的时候,回送一个STALL。

SetEPRxAddr(ENDP0, ENDP0_RXADDR); //设置端点0描述符表,包括接收缓冲区地址、最大允许接收的字节数、发送缓冲区地址三个量。

SetEPTxAddr(ENDP0, ENDP0_TXADDR); //这是发送缓冲区地址

Clear_Status_Out(ENDP0);

//清除EP_KIND的STATUS_OUT位,如果改位被设置,在控制模式下只对0字节数据包相应。其它的都返回STALL。主要用于控制传输的状态过程。

SetEPRxCount(ENDP0, Device_Property.MaxPacketSize); //接收缓冲区支持64个字节。

SetEPRxValid(ENDP0);

//使能端点0的接收,因为很快就要接收SETUP令牌包后面跟着的数据包了。

SetEPType(ENDP1, EP_INTERRUPT); //端点1为中断端点。

SetEPTxAddr(ENDP1, ENDP1_TXADDR); //设置发送缓冲区地址。

SetEPTxCount(ENDP1, 4); //每次发送四个字节

SetEPRxStatus(ENDP1, EP_RX_DIS);

//接收禁止,只发送Mouse信息,而不从主机接收。

SetEPTxStatus(ENDP1, EP_TX_NAK); //现在发送端点还不允许发送数据。

bDeviceState = ATTACHED;

//连接状态改为已经连接,默认地址状态。

SetDeviceAddress(0); //地址默认为0. }

复位中断执行完成后,开发板的USB接口能够以默认地址对主机来的数据包进行响应了。这个阶段的分析到此结束,下一个阶段就是正式分析代码实现的枚举过程了。

四、USB的“JoyStickMouse”工作过程详细分析 1、枚举第一步:获取设备的描述符 从USB_init()开始

(1)先要允许数据传输完成中断

在poweron()函数后面紧跟着几句话:

PowerOn();

//这句执行完,设备被主机检测到,并且能够响应复位中断了。

_SetISTR(0);

/* clear pending interrupts */

wInterrupt_Mask = IMR_MSK;

_SetCNTR(wInterrupt_Mask); /* set interrupts mask */ //以上这两句话将允许所有的USB中断

bDeviceState = UNCONNECTED;

//设备状态置位为未连接状态。这里我不太理解。这时候即使复位中断未发生,最起码设备已经算是连接入总线了,为什么这个状态还要设置为 “未连接”呢?

(2)主机获取描述符

主机进入控制传输的第一阶段:建立事务,发setup令牌包、发请求数据包、设备发ACK包。

主机发出对地址0、端点0发出SETUP令牌包,首先端点0寄存器的第11位SETUP位置位,表明收到了setup令牌包。 由于此时端点0数据接收有效,所以接下来主机的请求数据包被SIE保存到端点0描述附表的RxADDR里面,收到的字节数保存到RxCount里面。 端点0寄存器的CTR_RX被置位为1,ISTR的CTR置位为1,DIR=1,

EP_ID=0,表示端点0接收到主机来的请求数据。此时设备已经ACK主机,将触发正确传输完成中断,下面就进入中断看一看。

_SetISTR((u16)CLR_CTR); /*首先清除传输完成标志*/

EPindex = (u8)(wIstr & ISTR_EP_ID); //获取数据传输针对的端点号。

if (EPindex == 0)

//如果是端点0,这里的确是端点0

{

SaveRState = _GetEPRxStatus(ENDP0); //保存端点0状态,原本是有效状态。

SaveTState = _GetEPTxStatus(ENDP0);

_SetEPRxStatus(ENDP0, EP_RX_NAK); //在本次数据处理好之前,对主机发来的数据包以NAK回应

_SetEPTxStatus(ENDP0, EP_TX_NAK);

if ((wIstr & ISTR_DIR) == 0) //如果是IN令牌,数据被取走 {

_ClearEP_CTR_TX(ENDP0);

In0_Process();

//调用该程序处理固件数据输出后的工作。

_SetEPRxStatus(ENDP0, SaveRState);

_SetEPTxStatus(ENDP0, SaveTState);

return; }

Else

//DIR=1时,要么是SETUP包,要么是OUT包。 {

//这里先分析SETUP包。

wEPVal = _GetENDPOINT(ENDP0); //获取整个端点0状态

if ((wEPVal & EP_CTR_TX) != 0) //这种情况一般不太可能, {


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

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

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

马上注册会员

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