原创 U盘实现流程跟踪分析02

2010-4-30 19:19 4912 14 14 分类: MCU/ 嵌入式

<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 

 


 


二、追踪USB大容量设备的实现流程


 


5、主机发命令READ FORMAT CATPACITIES


再次分析一次命令执行的流程


1)首先在批量输出端点2产生RX中断


在中断中调用Mass_Storage_Out ()


在处理过程中先将接收缓冲区的数据、长度保存。


由于此时,命令处理状态机处于BOT_IDLE状态,所以调用命令解码函数CBW_Decode()


 


2)解码函数所做的工作


把接收到的数据先赋值给命令封包结构CBW。同时开始准备填充命令状态封包结构CSW


switch (CBW.CB[0]),根据命令操作码进行命令处理散转。


 


3)操作码0x23,进入相应处理函数SCSI_ReadFormatCapacity_Cmd()


这个命令处理主要是填充用户返回的容量数据结构体,然后调用另外一个函数Transfer_Data_Request()来完成数据的传输。


 


这个函数接收发送数据缓冲区的起始地址、长度,首先把数据复制到数据输出批量端点1


  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; //填充命令状态封包。


 


接下来主机会连发两个“IN第一次将容量数据结构体返回


然后在端点1输入中断中,又将命令状态封包结构复制到批量端点1输出缓冲区。主机的第二个“IN“将取走这个数据。


在第二次输入中断处理程序中,命令状态重新回到“BOT_IDLE”,于是又可以接收新的命令。


 


 


6、读容量命令


这个跟上个命令返回的数据差不多,具体什么区别,等到移植调试的时候再看。


 


7READ10)命令


这是一个非常重要的命令,我们获取U盘的文件主要就靠它了。


1)前面的过程忽略,直接进入读命令解码SCSI_Read10_Cmd()


处理中,主要存在两种情况:


BOT_IDLE时:


    if ((CBW.bmFlags & 0x80) != 0)


    {


      Bot_State = BOT_DATA_IN;


      Read_Memory();


    }


BOT_DATA_IN时:


直接 Read_Memory();


 


2)进入Read_Memory()处理函数。


void Read_Memory(void)


{


  if (!Block_Read_count)


  { //读入一个扇区512字节,但是一次只能发送64个字节。


    MSD_ReadBlock(Data_Buffer, Memory_Offset, 512);


    UserToPMABufferCopy(Data_Buffer, ENDP1_TXADDR, BULK_MAX_PACKET_SIZE);


    Block_Read_count = 512 - BULK_MAX_PACKET_SIZE;


    Block_offset = BULK_MAX_PACKET_SIZE;


  }


  else


  {


    UserToPMABufferCopy(Data_Buffer + Block_offset, ENDP1_TXADDR, BULK_MAX_PACKET_SIZE);


    Block_Read_count -= BULK_MAX_PACKET_SIZE;


    Block_offset += BULK_MAX_PACKET_SIZE;


  }


 


  SetEPTxCount(ENDP1, BULK_MAX_PACKET_SIZE);


  SetEPTxStatus(ENDP1, EP_TX_VALID);


 


  Memory_Offset += BULK_MAX_PACKET_SIZE;


  Transfer_Length -= BULK_MAX_PACKET_SIZE; //剩下的需要传输的字节数。


  CSW.dDataResidue -= BULK_MAX_PACKET_SIZE;


  Led_RW_ON();


}


这里不清楚的是主机是一次把512字节读完,还是每次发一个命令读取64字节。我觉得应该是发一次读命令,8次“IN”读取一个扇区,再发一个“IN”读取命令状态封包。


 


8、写命令WRITE10


这个命令的处理过程跟读命令的处理差不多,只是最后它会调用Write_Memory()进行处理


 


  i = 0;


  for (; Counter < temp; Counter++)


  {


    Data_Buffer[Counter] = Bulk_Data_Buff;


    i++;


  }


从接受缓冲区得到的数据总是先放到用户缓冲区,这个缓冲区有512个字节。


  if (!(Transfer_Length % 512))


  {


    Counter = 0;


    MSD_WriteBlock(Data_Buffer, Memory_Offset - 512, 512);


  }


每次收到512字节的时候,写入SD卡。


 


9u盘文件系统的实现


从这个U盘的实现过程来看,设备端只需完成 SD卡扇区的读写工作,所以与文件系统相关的工作都是由主机方完成的。


至于文件系统的详细实现,前面在FatFs的分析过程中已经涉及,这里就不再叙述了。


 


 

文章评论0条评论)

登录后参与讨论
我要评论
0
14
关闭 站长推荐上一条 /2 下一条