📄 sl811.c
字号:
// cmd^=0x40; // toggle DATA0/DATA1
// cmd&=0xdf;
// addr=bData1?0x50:0x10; // select next address for data
// xferLen=(BYTE)(wLen>=0x40)?0x40:wLen; // get data length required
// buffer+=bufLen;
// SL811BufWrite(addr,buffer,xferLen); // data to transfer on USB
// 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
// }
// else
// break;
// }
// //-------------------------NAK----------------------------
// if (result & EP0_NAK) // NAK Detected
// break; // main loop control the interval polling
// //-----------------------TIMEOUT--------------------------
// if (result&EP0_TIMEOUT) // TIMEOUT Detected
// {
// TIMEOUT_ERR=TRUE; // failed, set flag to terminate transfer
// break; // happens when data transfer on a device
// }
// //-----------------------STALL----------------------------
// if (result&EP0_STALL) // STALL detected
// return TRUE; // for unsupported request.
// //----------------------OVEFLOW---------------------------
// if (result&EP0_OVERFLOW) // OVERFLOW detected
// break;
// //-----------------------ERROR----------------------------
// if (result&EP0_ERROR) // ERROR detected
// break;
// } // end of While(1)
// if (result&EP0_ACK) // on ACK transmission
// return TRUE; // return OK
// return FALSE; // fail transmission
// }
//*****************************************************************************************
// usbXfer:
// successful transfer = return TRUE
// fail transfer = return FALSE
//*****************************************************************************************
bit usbXfer(uchar usbaddr,uchar endpoint,uchar pid,uint wPayload,uint wLen,uchar *buffer) //完成所有的数据传输才退出
{
idata uchar remainder;
idata uchar xferLen,cmd,result,intr;
idata uchar bufLen,data0,data1,addr,timeout;
bit dataX; //切换PINGPONG用的标志
//------------------------------------------------
// Default setting for usb trasnfer
//------------------------------------------------
dataX=bufLen=timeout=0; //初始化基本参数
TIMEOUT_ERR=DATA_STOP=FALSE;
data0=EP0_Buf; // DATA0 buffer address,设定第1缓冲首地址
data1=data0+(uchar)wPayload; // DATA1 buffer address ,设定第2缓冲首地址
//------------------------------------------------
// Define data transfer payload
//------------------------------------------------
if (wLen>=wPayload) // select proper data payload //判断实际要求传送的长度
xferLen=wPayload; // limit to wPayload size //最大不能超过负载,超过部分下次再传
else // else take < payload len
xferLen=wLen;
// For IN token
if (pid==PID_IN) // for current IN tokens //当前的任务是要读取数据
cmd = DATA0_RD; // FS/FS on Hub, sync to sof 作为新的一帧传送
// For OUT token
else if(pid==PID_OUT) // for OUT tokens //当前的任务是要写入数据
{
if(xferLen) // only when there are,把需要加载的数据转移到811
SL811BufWrite(data0,buffer,xferLen); // data to transfer on USB
cmd=DATA0_WR; //将写命令的控制字准备好
bData1=uDev.bData1[endpoint]; //得到当前的切换状况
uDev.bData1[endpoint]=!(uDev.bData1[endpoint]); // DataToggle,翻转,为下次准备
if(bData1)
cmd|=0x40; // Set Data1 bit in command,根据状况修改命令字
}
// For SETUP/OUT token
else // for current SETUP/OUT tokens
{
if(xferLen) // only when there are
SL811BufWrite(data0,buffer,xferLen); // data to transfer on USB
cmd = DATA0_WR; // FS/FS on Hub, sync to sof
}
//------------------------------------------------
// For EP0's IN/OUT token data, start with DATA1
// Control Endpoint0's status stage.
// For data endpoint, IN/OUT data, start ????
//------------------------------------------------
if (endpoint==0&&pid!=PID_SETUP) // for Ep0's IN/OUT token
cmd|=0x40; // always set DATA1
//------------------------------------------------
// Arming of USB data transfer for the first pkt,准备数据,送到SIE待传
//------------------------------------------------
SL811Write(EP0Status,((endpoint&0x0F)|pid)); // PID + EP address
SL811Write(EP0Counter,usbaddr); // USB address
SL811Write(EP0Address,data0); // buffer address, start with "data0",首次传送的地址,一定从DATA0开始
SL811Write(EP0XferLen,xferLen); // data transfer length,本次传送的长度
SL811Write(IntStatus,INT_CLEAR); // clear interrupt status,清除中断
SL811Write(EP0Control,cmd); // Enable ARM and USB transfer start here,开始传送
//------------------------------------------------
// Main loop for completing a wLen data trasnfer
//------------------------------------------------
while(TRUE)
{
//---------------Wait for done interrupt------------------
while(TRUE) // always ensure requested device is
{ // inserted at all time, then you will
intr=SL811Read(IntStatus); //读取中断标志
if((intr&USB_RESET)||(intr&INSERT_REMOVE)) // proceed to parse result from slave
{ // device.设备被重置了要退出传送并给出标志
DATA_STOP=TRUE; // if device is removed, set DATA_STOP
return FALSE; // flag true, so that main loop will
} // know this condition and exit gracefully
if(intr& USB_A_DONE) //本次传送完毕
break; // interrupt done !!!
}
SL811Write(IntStatus,INT_CLEAR); // clear interrupt status,清除中断标志
result=SL811Read(EP0Status); // read EP0status register,得到传送结果
remainder=SL811Read(EP0Counter); // remainder value in last pkt xfer,得到剩余字节的数量
//----------------ACK----------------------------
if (result&EP0_ACK) // Transmission ACK,如果接收正确
{
// OUT TOKEN
if(pid==PID_OUT)
{
wLen-=(uint)xferLen; // update remainding wLen value,得到剩余要传字节的数量
buffer+=xferLen;
if(!wLen)
break; //上次已经传掉的数量
if (wLen >= wPayload) // select proper data payload
xferLen = wPayload; // limit to wPayload size
else // else take < payload len
xferLen = wLen;
//如果还有数据要传送
bData1=uDev.bData1[endpoint];
uDev.bData1[endpoint]=!(uDev.bData1[endpoint]); // DataToggle,把标志切换到下一个
cmd^=0x40; // toggle DATA0/DATA1
// cmd&=0xdf;
addr=bData1?data1:data0; // select next address for data
SL811BufWrite(addr,buffer,xferLen); // data to transfer on USB
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);
}
else if(pid==PID_IN) // IN TOKEN
{
wLen-=(uint)xferLen;
cmd^=0x40;
dataX=!dataX;
//------------------------------------------------
// If host requested for more data than the slave
// have, and if the slave's data len is a multiple
// of its endpoint payload size/last xferLen. Do
// not overwrite data in previous buffer.
//------------------------------------------------
if(remainder==xferLen) // empty data detected
bufLen = 0; // do not overwriten previous data
else // reset bufLen to zero
bufLen = xferLen; // update previous buffer length
//------------------------------------------------
// Arm for next data transfer when requested data
// length have not reach zero, i.e. wLen!=0, and
// last xferlen of data was completed, i.e.
// remainder is equal to zero, not a short pkt
//------------------------------------------------
if(!remainder&&wLen) // remainder==0 when last xferLen
{ // was all completed or wLen!=0
addr=dataX?data1:data0; // select next address for data
xferLen=(uchar)(wLen>=wPayload)?wPayload:wLen; // get data length required
// cmd |= 0x20; // always sync SOF when FS, regardless
// cmd&=0xdf;
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
}
//------------------------------------------------
// Copy last IN token data pkt from prev transfer
// Check if there was data available during the
// last data transfer
//------------------------------------------------
if(bufLen)
{
SL811BufRead((dataX?data0:data1),buffer,bufLen);
buffer+=bufLen;
}
//------------------------------------------------
// Terminate on short packets, i.e. remainder!=0
// a short packet or empty data packet OR when
// requested data len have completed, i.e.wLen=0
// For a LOWSPEED device, the 1st device descp,
// wPayload is default to 64-byte, LS device will
// only send back a max of 8-byte device descp,
// and host detect this as a short packet, and
// terminate with OUT status stage
//------------------------------------------------
if(remainder||!wLen)
break;
}
// SETUP TOKEN
else if(pid==PID_SETUP) // do nothing for SETUP/OUT token
break; // exit while(1) immediately
}
//-------------------------NAK----------------------------
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);
DelayMs(50); // re-arm and request for last cmd, IN token
result=0; // respond to NAK status only
}
else
{
epst=EP0_NAK; // normal data endpoint, exit now !!! , non-zero ep
break; // main loop control the interval polling
}
}
//-----------------------TIMEOUT--------------------------
if (result&EP0_TIMEOUT) // TIMEOUT Detected
{
if(endpoint==0) // happens when hub enumeration
{
if(++timeout>=TIMEOUT_RETRY)
{
timeout--;
epst=EP0_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
epst=EP0_TIMEOUT;
break; // happens when data transfer on a device
} // through the hub
}
//-----------------------STALL----------------------------
if (result&EP0_STALL) // STALL detected
{
epst=EP0_STALL;
return TRUE; // for unsupported request.
}
//----------------------OVEFLOW---------------------------
if (result&EP0_OVERFLOW) // OVERFLOW detected
{
epst=EP0_OVERFLOW;
break;
}
//-----------------------ERROR----------------------------
if (result&EP0_ERROR) // ERROR detected
{
epst=EP0_ERROR;
break;
}
} // end of While(1)
if (result&EP0_ACK) // on ACK transmission
{
epst=EP0_ACK;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -