⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sl811.c

📁 使用单片机C51实现的USB1.1通信的文件协议层
💻 C
📖 第 1 页 / 共 3 页
字号:
//				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 + -