wqs_79
驱动牛犊
驱动牛犊
  • 注册日期2003-11-27
  • 最后登录2009-09-25
  • 粉丝0
  • 关注0
  • 积分13分
  • 威望31点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
阅读:1372回复:4

usbxfer程序,请lxb_gd指点,欢迎讨论!

楼主#
更多 发布于:2003-12-24 09:29
先将程序贴上来,源程序来自己Cepress,汉字注释是我读的时候写的:
//*****************************************************************************************
// usbXfer:
// 参数:usbaddr:设备地址,endpoint:端点号,pid:包标识符,iso:同步传送标识
//      wPayload:有效数据,wLen:1111长度,*buffer:数据缓冲区地址
// 传输成功,返回TRUE
// 传输失败,返回FALSE
//*****************************************************************************************
int usbXfer(BYTE usbaddr, BYTE endpoint, BYTE pid, BYTE iso, WORD wPayload, WORD wLen, BYTE *buffer)
{  
 BYTE cmd, result, timeout, intr; //控制指令,返回状态,超时值,中断值
 BYTE xferLen, bufLen, data0, data1, dataX, addr; //片内缓冲长度,缓冲长度,端点0地址,端点1地址,端点切换,地址

 bufLen = dataX = timeout = 0; //reset all
 data0 = EP0_Buf; // DATA0 buffer address
 data1 = data0 + (BYTE)wPayload; // DATA1 buffer address
 DATA_STOP = TIMEOUT_ERR = FALSE; // 设置缺省值

 if (wLen >= wPayload)   // 选择适当的Payload值
   xferLen = wPayload;
 else
   xferLen = wLen;

 if(pid==PID_IN) // 为输入包
  {
   if(FULL_SPEED) cmd = sDATA0_RD; // 全速或在HUB上的全速设备,同步SOF
   else cmd = DATA0_RD; // 低速设备,不用同步SOF
   if(HUB_DEVICE && usbaddr!=HUB_ADDR) // HUB上的传输, USB addr #0, #2..#5 only
    {
     if(uHub.bPortSpeed[usbaddr]) // 如果是低速设备,且前一个包是
       cmd = psDATA0_RD; // 设置包且当前为输入包,不用同步
    }
  }
 else if(pid==PID_OUT) // 输出包
  {  
   if(xferLen) // 有数据需要传输
     SL811BufWrite(data0,buffer,xferLen); //
   if(FULL_SPEED)
     cmd = sDATA0_WR; // FS/FS on Hub, sync to sof
   else // LS, no sync to sof for OUT
     cmd = DATA0_WR;
   if(HUB_DEVICE && usbaddr!=HUB_ADDR) // Transfer on Hub, USB addr #0, #2..#5 only
    {
     if(uHub.bPortSpeed[usbaddr]) // If transfer of LS on Hub, previous is
       cmd = psDATA0_WR; // SETUP & current is IN, no sync to sof,
    }
   bData1 = uDev[usbaddr].bData1[endpoint]; // 选择数据缓冲区0/1
   uDev[usbaddr].bData1[endpoint] = (uDev[usbaddr].bData1[endpoint] ? 0 : 1);
   if(bData1)
   cmd |= 0x40;                               // 在命令中置Data1位
  }
 
 else // 当前设置/输出包
  {
   if(xferLen) // only when there are
     SL811BufWrite(data0,buffer,xferLen); // data to transfer on USB

   if(FULL_SPEED)
     cmd = sDATA0_WR; // FS/FS on Hub, sync to sof
   else // LS, no sync to sof for OUT
     cmd = DATA0_WR;
   if(HUB_DEVICE && usbaddr!=HUB_ADDR) // Transfer on Hub, USB addr #0, #2..#5 only
    {
     if(uHub.bPortSpeed[usbaddr]) // If transfer of LS on Hub, previous
       cmd = psDATA0_WR;
    }
  }
//以上都是确定要发送的控制命令的值cmd
 if(iso)
   cmd |= ISO_BIT;                     // 需要设为同步模式
//确定端点号。
 if(endpoint == 0 && pid != PID_SETUP) // 当为端点0的输入输出包时,从端点1开始
   cmd |= 0x40;
//初始化控制寄存器,为什么只有端点0而没有端点1
 SL811Write(EP0Status,((endpoint&0x0F)|pid)); // PID + EP address
 SL811Write(EP0Counter,usbaddr); // USB address
 SL811Write(EP0Address,data0); // buffer address, start with \"data0\"
 SL811Write(EP0XferLen,xferLen); // data transfer length
 SL811Write(IntStatus,INT_CLEAR); // clear interrupt status
 SL811Write(EP0Control,cmd); // Enable ARM and USB transfer start here

 while(TRUE)
  {  
   //等下游设备的返回码
   while(TRUE) // 在全部过程中应确认请求设备一直接入,然后
    { // 要等待中断发生,并处理从从设备传输来的分析结果
     intr = SL811Read(IntStatus); //
     if((intr & USB_RESET) || (intr & INSERT_REMOVE)) //
      { //
       DATA_STOP = TRUE; // 如果设备已经移除,应当停止传输
       return FALSE; //
      } //
     if(intr & USB_A_DONE)
       break; // 中断完成
    }

   SL811Write(IntStatus,INT_CLEAR); // 清除中断状态
   //读取状态寄存器结果和计数器值并保存
   result = SL811Read(EP0Status); // 读取状态寄存器值
   remainder = SL811Read(EP0Counter); // 保存本次传输计数值
   //判断返回状态
   //有应答
   if (result & EP0_ACK) // Transmission ACK
    {
     if(pid == PID_SETUP) // do nothing for SETUP/OUT token
       break; // exit while(1) immediately
     else if(pid == PID_OUT)
       break;
     else if(pid == PID_IN)
      { // 只有为输入包时
       wLen -= (WORD)xferLen; // 更新剩余的长度值
       cmd  ^= 0x40;     // 使用的缓冲区切换 DATA0/DATA1
       dataX++; // dataX 也进行切换
       if(remainder==xferLen) // 如果检测到空数据
bufLen = 0; // 则不覆盖前一数据
       else // reset bufLen to zero
bufLen = xferLen; // update previous buffer length
       if(!remainder && wLen) // remainder==0 when last xferLen
{ // was all completed or wLen!=0
         addr   =(dataX & 1) ? data1:data0; // select next address for data
xferLen=(BYTE)(wLen>=wPayload)?wPayload:wLen; // get data length required
if (FULL_SPEED) // sync with SOF transfer
cmd |= 0x20; // always sync SOF when FS, regardless
SL811Write(EP0XferLen, xferLen); // select next xfer length
SL811Write(EP0Address, addr);           // data buffer addr
SL811Write(IntStatus,INT_CLEAR); // is a LS is on Hub.
SL811Write(EP0Control,cmd); // Enable USB transfer and re-arm
}
       if(bufLen)
{
SL811BufRead(((dataX&1)?data0:data1), buffer, bufLen);
buffer += bufLen;
}
       if(remainder || !wLen)
break;
      }
    }
   //无应答
   if (result & EP0_NAK) // NAK Detected
    {
     if(endpoint==0) // on ep0 during enumeration of LS device
      { // happen when slave is not fast enough,
       SL811Write(IntStatus,INT_CLEAR); // clear interrupt status, need to
       SL811Write(EP0Control,cmd); // re-arm and request for last cmd, IN token
       result = 0;                                     // respond to NAK status only
      }
     else // normal data endpoint, exit now !!! , non-zero ep
       break; // main loop control the interval polling
    }
   //超时
   if (result & EP0_TIMEOUT) // TIMEOUT Detected
    {
     if(endpoint==0) // happens when hub enumeration
      {
       if(++timeout >= TIMEOUT_RETRY)
        {
         timeout--;
         break; // exit on the timeout detected
}
       SL811Write(IntStatus,INT_CLEAR); // clear interrupt status, need to
       SL811Write(EP0Control,cmd); // re-arm and request for last cmd again
      }
     else
      { // all other data endpoint, data transfer
       TIMEOUT_ERR = TRUE; // failed, set flag to terminate transfer
       break; // happens when data transfer on a device
      } // through the hub
    }
   //迟延
   if(result & EP0_STALL)   // STALL detected
     return TRUE; // for unsupported request.
   //溢出
   if (result & EP0_OVERFLOW)   // OVERFLOW detected
     break;
   //错误
   if(result & EP0_ERROR)   // ERROR detected
     break;
  }
 if (result & EP0_ACK) // on ACK transmission
   return TRUE; // return OK
 return FALSE; // fail transmission
}

请教:1.各变量的作用. 2.为什么初始化寄存器只有EP0没有EP1,在程序中是否要自己加上?
lxb_gd
驱动太牛
驱动太牛
  • 注册日期2002-01-16
  • 最后登录2018-06-02
  • 粉丝0
  • 关注0
  • 积分72408分
  • 威望362391点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
  • 社区居民
沙发#
发布于:2003-12-24 10:16
EP0,EP1其实是两组控制寄存器,他们的定义和功能都是一样的,用哪一组都一样,例子中是用EP0,但两个也可以同时使用,可以提高速度!
wqs_79
驱动牛犊
驱动牛犊
  • 注册日期2003-11-27
  • 最后登录2009-09-25
  • 粉丝0
  • 关注0
  • 积分13分
  • 威望31点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2003-12-24 10:36
不是Data0对应EP0,Data1对应EP1么,那么我这样理解:程序中只用了EP0,没有用EP1。但是if(bData1)
cmd |= 0x40; // 在命令中置Data1位;又用到了EP1呀,怎么解释?
lxb_gd
驱动太牛
驱动太牛
  • 注册日期2002-01-16
  • 最后登录2018-06-02
  • 粉丝0
  • 关注0
  • 积分72408分
  • 威望362391点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
  • 社区居民
地板#
发布于:2003-12-24 10:44
data0,data1是usb协议中的数据序列触发位,用于数据分组同步。不要和EP0,EP1-- SL811HS控制寄存器混淆!
wqs_79
驱动牛犊
驱动牛犊
  • 注册日期2003-11-27
  • 最后登录2009-09-25
  • 粉丝0
  • 关注0
  • 积分13分
  • 威望31点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2003-12-24 11:05
多谢提点,茅塞顿开呀!
游客

返回顶部