植物生长补光:U盘实现流程跟踪分析01
来源:百度文库 编辑:中财网 时间:2024/05/24 00:44:56
一、追踪USB大容量设备的实现流程 1、从main.c开始(1)main函数的执行流程 Set_System(); //设置时钟、端口等。 Set_USBClock(); //设置usb的时钟 USB_Interrupts_Config(); //设置中断 Led_Config(); //设置所使用的到的灯。 MSD_Init(); //SD卡初始化 Get_Medium_Characteristics(); //获取SD块总数、每块字节数。 USB_Init(); //USB_init.c提供的初始化函数。从这里开始USB设备被主机检测到。 while (1) { //USB的工作都是在中断中完成的,主执行流程什么也没做。 }(2)与鼠标例程不同的地方在中断配置中,使能了USB高优先级中断。 NVIC_InitStructure.NVIC_IRQChannel= USB_HP_CAN_TX_IRQChannel; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); 用到了几个灯指示,这个我的开发板上用不到,就不详细看了。 MSD_Init(),是对SD卡进行初始化。该函数在msd.c中,我看了一下它的SD卡实现的代码,比我的SD函数代码齐整多了。以后有时间要把我的USB驱动好好的整理一下。不过现在就先不管了。 接下来这个函数获取SD卡的容量,这样的函数我在SD卡驱动中也实现了,改变一下调用方式就行了。 USB_Init()函数在usb_init.c库函数中,但它最终会调用user_prop.c宏的用户初始化例程。下面就追踪进去看一看。 (3)大容量存储设备的初始化void MASS_init(){ pInformation->Current_Configuration = 0; PowerOn(); 连接电缆主机很快发总线复位。 _SetISTR(0); wInterrupt_Mask = IMR_MSK; _SetCNTR(wInterrupt_Mask); 开启复位和传输中断。 pInformation->Current_Feature = MASS_ConfigDescriptor[7]; while (pInformation->Current_Configuration == 0) { NOP_Process(); } bDeviceState = CONFIGURED; //这句执行完成后,设备处于已配置状态。我先在这里加一句调试语句。#if usb_debugUart_PutString(“设备已配置”);#endif} 2、进入复位中断(1)先列出中断处理代码发生总线复位中断以后,处理是在usb_prop.c的Mass_Reset()函数中完成的。void MASS_Reset(){ Device_Info.Current_Configuration = 0; SetBTABLE(BTABLE_ADDRESS); SetEPType(ENDP0, EP_CONTROL); //端点0控制端点 SetEPTxStatus(ENDP0, EP_TX_NAK); //不响应IN SetEPRxAddr(ENDP0, ENDP0_RXADDR); //设置接收缓冲区(OUT) SetEPRxCount(ENDP0, Device_Property.MaxPacketSize); 接收长度。 SetEPTxAddr(ENDP0, ENDP0_TXADDR); //发送缓冲区(IN) Clear_Status_Out(ENDP0); SetEPRxValid(ENDP0); //使能端点0的接收。 SetEPType(ENDP1, EP_BULK); //端点1批量模式 SetEPTxAddr(ENDP1, ENDP1_TXADDR); //设置发送缓冲区(IN) SetEPTxStatus(ENDP1, EP_TX_NAK); 发送不响应。 SetEPRxStatus(ENDP1, EP_RX_DIS); //接收无效。对OUT无效 SetEPType(ENDP2, EP_BULK); //端点2批量模式 SetEPRxAddr(ENDP2, ENDP2_RXADDR); //设置接收缓冲区OUT SetEPRxCount(ENDP2, Device_Property.MaxPacketSize); SetEPRxStatus(ENDP2, EP_RX_VALID); SetEPTxStatus(ENDP2, EP_TX_DIS); //发送无效,对IN无效 SetDeviceAddress(0); //使能USB接口模块。 CBW.dSignature = BOT_CBW_SIGNATURE; Bot_State = BOT_IDLE; //命令状态机初始化为空闲状态}在这里没有我没有看到将批量端点设置为双缓冲模式的迹象,难道这个例程没有用它? 3、进入枚举过程因为在鼠标例程中已经详细分析过枚举过程,这里主要是大容量设备枚举过程中不同的地方做一下分析。(1)获取设备描述符、设置地址。(2)获取配置描述符(3)获取配置描述符集合,这里主要讲接口描述符分析一下。 0x09, /* bLength: Interface Descriptor size */ 0x04, /* bDescriptorType: */ 0x00, /* bInterfaceNumber: Number of Interface */ 0x00, /* bAlternateSetting: Alternate setting */ 0x02, /* bNumEndpoints*/ 使用两个端点 0x08, /* bInterfaceClass: MASS STORAGE Class,大容量存储类 */ 0x06, /* bInterfaceSubClass : SCSI transparent,SCSI传输*/ 0x50, /* nInterfaceProtocol ,仅批量传输*/ 4, /* iInterface: */ (4)获取字符串描述符(5)类请求实现:类获取逻辑盘:一般返回0类请求复位: ClearDTOG_TX(ENDP1); ClearDTOG_RX(ENDP2); CBW.dSignature = BOT_CBW_SIGNATURE; Bot_State = BOT_IDLE; (6)设置配置在用户设置的回调函数中,又调用void Mass_Storage_SetConfiguration(void){ if (pInformation->Current_Configuration) { ClearDTOG_TX(ENDP1); ClearDTOG_RX(ENDP2); Bot_State = BOT_IDLE; }}这个工作前面已经做过了。 4、主机发命令INQUIRY(1)首先进入批量输出中断该中断的回调函数调用Mass_Storage_Out()进行处理。 (2)追踪进入Mass_Storage_Out()void Mass_Storage_Out (void){ u8 CMD; CMD = CBW.CB[0]; // Data_Len = GetEPRxCount(ENDP2); PMAToUserBufferCopy(Bulk_Data_Buff,ENDP2_RXADDR, Data_Len); switch (Bot_State) { case BOT_IDLE: CBW_Decode(); //第一次收到命令肯定调用这个解码函数。 break; //它的作用应该是填充CBW命令块封包结构 case BOT_DATA_OUT: if (CMD == SCSI_WRITE10) { SCSI_Write10_Cmd(); break; }} (3)追踪进入CBW_Decode()这个函数的代码较长,我就不列举在这里了,我就分析一下本次的主要工作。首先将用户缓冲区的数据复制到命令封包结构里面。然后准备好状态封包结构: CSW.dTag = CBW.dTag; //这个标志由主机生成,可以用于检查设备是否正确收到该命令。 CSW.dDataResidue = CBW.dDataLength; 然后主要是根据命令操作码,调用相应的SCSI命令处理函数。 switch (CBW.CB[0]) { case SCSI_REQUEST_SENSE: SCSI_RequestSense_Cmd (); break; case SCSI_INQUIRY: SCSI_Inquiry_Cmd(); break;我这里就列出了两项,实际的命令是很多的。本次主要是查询处理。 (4)追踪进入SCSI_Inquiry_Cmd()以上函数是在usb_bot.c里面,现在跳转到usb_scsi.c里面。 这个函数的主要工作是调用Transfer_Data_Request(Inquiry_Data, Inquiry_Data_Length)来完成。这个Inquiry_Data = Standard_Inquiry_Data,后面这个Standard_Inquiry_Data是scsi_data.c里面定义的一个数据结构,专门用于inquiry命令的返回。u8 Standard_Inquiry_Data[] = { 0x00, /* Direct Access Device */ 0x80, /* RMB = 1: Removable Medium */ 0x02, /* Version: No conformance claim to standard */ 0x02, //这里圈圈的书上说应该为 0x01 36 - 4, //这里圈圈的书上说应该为 31 0x00, 0x00, 0x00, /* SCCS = 1: Storage Controller Component */ 'S', 'T', 'M', ' ', ' ', ' ', ' ', ' ',//厂商信息 'S', 'T', 'R', ' ', ' ', 'F', 'l', 'a', 's', 'h', ' ', 'D', 'i', 's', 'k', ' ',//产品信息 '1', '.', '0', ' ' //版本信息。 };(5)追踪进入Transfer_Data_Request () void Transfer_Data_Request(u8* Data_Pointer, u16 Data_Len){ UserToPMABufferCopy(Data_Pointer, ENDP1_TXADDR, Data_Len); SetEPTxCount(ENDP1, Data_Len); SetEPTxStatus(ENDP1, EP_TX_VALID); Bot_State = BOT_DATA_IN_LAST; CSW.dDataResidue -= Data_Len; CSW.bStatus = CSW_CMD_PASSED; //设置好命令状态封包信息。} (6)接下来,主机会发IN,取走查询信息。并进入批量输入中断。在该中断中,将调用函数Mass_Storage_In (void) void Mass_Storage_In (void){ switch (Bot_State) { case BOT_CSW_Send: case BOT_ERROR: Bot_State = BOT_IDLE; SetEPRxStatus(ENDP2, EP_RX_VALID);/* enable the Endpoint to recive the next cmd*/ break; case BOT_DATA_IN_LAST: Set_CSW (CSW_CMD_PASSED, SEND_CSW_ENABLE); SetEPRxStatus(ENDP2, EP_RX_VALID); break; default: break; }}然后设备的命令状态机状态变为Set_CSW()这个函数所设置的状态,一般为BOT_CSW_Send。 (7)追踪进入Set_CSW()在该函数中:void Set_CSW (u8 CSW_Status, u8 Send_Permission){ CSW.dSignature = BOT_CSW_SIGNATURE; CSW.bStatus = CSW_Status; //命令状态封包数据已经准备好 UserToPMABufferCopy((&CSW),ENDP1_TXADDR, DATA_LENGTH); SetEPTxCount(ENDP1, CSW_DATA_LENGTH); Bot_State = BOT_ERROR; if (Send_Permission) { Bot_State = BOT_CSW_Send; SetEPTxStatus(ENDP1, EP_TX_VALID); } }然后,主机再次发IN令牌包,取走命令状态封包。case BOT_ERROR: Bot_State = BOT_IDLE; SetEPRxStatus(ENDP2, EP_RX_VALID);端点2的接收又被使能,重新进入接收命令状态。
本文来源于电气自动化技术网 转载注明出处http://www.dqjsw.com.cn/dianqi/danpianji/13143.html
本文来源于电气自动化技术网 转载注明出处http://www.dqjsw.com.cn/dianqi/danpianji/13143.html
Bug跟踪流程是什么?
”PM分析流程”是什么意思?
U盘安装xp可否实现
GPS系统如何实现货物的跟踪与调度?
大虾帮忙!!分析PLL的调相信号跟踪能力
Google Analytics(分析)跟踪代码怎么用?
Google Analytics(分析)跟踪代码怎么用?
如何在批处理内实现安全删除U盘?
请问608装上TF卡,如何实现U盘功能?
C# 编程实现限制U盘的使用
98系统如何实现所有U盘自动识别
U盘自身坏的原因的分析
我希望跟踪某个问题,在百度知道吧里面如何实现?
如何在word中实现目录按住ctrl键并单击鼠标进行跟踪链接
如何实现U盘的自动运行(像光盘的autorun)?
怎样实现电脑从U盘启动并进入纯DOS?请高手赐教!
哪种情况下可通过U盘启动计算机?如何实现?启动的效果如何?
哪种情况下可通过U盘启动计算机?如何实现?启动效果如何?
我想锁住电脑后用U盘当钥匙打开,不知道怎么实现?
vb编程实现播音录音,波形分析
SQL语句实现月总额分析
怎样用MTALAB实现层次分析法?
快乐U啤swot分析矩阵
某企业内部供应链流程的时间分析