阅读:1372回复:4
usbxfer程序,请lxb_gd指点,欢迎讨论!
先将程序贴上来,源程序来自己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,在程序中是否要自己加上? |
|
沙发#
发布于:2003-12-24 10:16
EP0,EP1其实是两组控制寄存器,他们的定义和功能都是一样的,用哪一组都一样,例子中是用EP0,但两个也可以同时使用,可以提高速度!
|
|
板凳#
发布于:2003-12-24 10:36
不是Data0对应EP0,Data1对应EP1么,那么我这样理解:程序中只用了EP0,没有用EP1。但是if(bData1)
cmd |= 0x40; // 在命令中置Data1位;又用到了EP1呀,怎么解释? |
|
地板#
发布于:2003-12-24 10:44
data0,data1是usb协议中的数据序列触发位,用于数据分组同步。不要和EP0,EP1-- SL811HS控制寄存器混淆!
|
|
地下室#
发布于:2003-12-24 11:05
多谢提点,茅塞顿开呀!
|
|