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

📄 sl811.c

📁 CPRESS SL811 驱动代码
💻 C
字号:

/*******************************************************************************
** 文件创建人  :LTY
** 文件创建日期: 2006年11月19日
** 文件功能描述: CYPRESS的SL811HS USB主控制器芯片底层驱动函数
********************************************************************************/

#include "Main.h"

STUSBDEV gstUSBDev;  //保存最近一个设备的信息
U8  gszSLBuf[1024];
STRTPACK gstRTPack;  //发送接收组织包

STDEVSIGN  stDevSign;
/******************************************************************
功能: 读写寄存器
*******************************************************************/
U8 SL811_Read(U8 addr)
{  
	U8 ucVal;
	SL811_ADDR=addr;
	ucVal=SL811_DATA;
	return ucVal;
}

void SL811_Write(U8 addr, U8 ucVal)
{  
	SL811_ADDR=addr;
	SL811_DATA=ucVal;
}
void SL811_ReadStr(U8 addr, U8 *pOutData,U8 ucNum)
{	
	unsigned char i;
	SL811_ADDR=addr;
	for(i=0;i<ucNum;i++)
	{
		*pOutData++ =SL811_DATA;		
	}
}

void SL811_WriteStr(U8 addr, U8 *pInData,U8 ucNum)
{	
	SL811_ADDR=addr;
	while (ucNum--)
	{
		SL811_DATA = *pInData++;		
	}
}

/******************************************************************
功能: 功能函数
*******************************************************************/
//SL811 初始化
void SL811_Init(void)
{	
	SL811_Write(RSLSOFANDMS,0xae);	 			//设置为主控制器
	SL811_Write(RSLSOFLOW,0xe0);
	SL811_Write(RSLCTRL,0x08);		 			//复位USB控制器
	//Delay_us(70000);		
	SL811_Write(RSLCTRL,0x05);		 			//使能SOF
	SL811_Write(REP0PIDEP,0x50);	 			//?
	SL811_Write(REP0DEVADDR,0);			 		//设置设备地址为0
	SL811_Write(REP0CTRL,0x01);		 			//?	
	//Delay_us(25000);
	SL811_Write(RSLIRQENABLE,INSERT_REMOVE);    // 允许设备插入拔开中断
	SL811_Write(RSLIRQSTATUS,INT_CLEAR);		// 清除所有中断
	stDevSign.ucDevInsert=FALSE;
	stDevSign.ucMasDev=FALSE;
}

//读控制器版本号
U8 SL811_ReadRevsion(void)
{
	return SL811_Read(RSLREVSION);
}

//USB复位
void USB_BusReset(void)
{
	U8 temp;
    temp=SL811_Read(RSLCTRL);
    temp=temp&0xe7;   
 	SL811_Write(RSLCTRL,temp|0x08);
	//Delay_us(500000);		
    SL811_Write(RSLCTRL,temp);    
}

void SLCheck_SlaveInserRemove(void)
{
	U8 ucStat;
	ucStat = SL811_Read(RSLIRQSTATUS);
	if(ucStat & USB_DETECT)
	{
		if(stDevSign.ucDevInsert ==TRUE)
		{		   	
		   	stDevSign.ucDevInsert =FALSE;
		   	stDevSign.ucMasDev=FALSE;
		}   
	}
	else
	{
		if(stDevSign.ucDevInsert ==FALSE)
		{		   	
		   	stDevSign.ucDevInsert =TRUE;
		} 
	}
	SL811_Write(RSLIRQSTATUS,INT_CLEAR);
}
/*****************************************************************************************
//函数功能 : 发送接收数据
// 传输正确返回 TRUE 否则返回FALSE
*****************************************************************************************/
U8 SL811_RWPack(PSTRTPACK pstRTPack)
{
	U8 ucLen,ucCmd,ucReLen;//
	U8 ucData0,ucData1;
	U8 ucRetStat,ucAddr,ucSaveLen;
	U8 ucTimeOut;
	ucAddr=ucData0=EP0_BUF;
	ucData1=EP0_BUF+pstRTPack->ucMaxPackLen;
	ucTimeOut=ucSaveLen=0;
	SL811_Write(REP0PIDEP,((pstRTPack->ucEndPoint&0x0F)|pstRTPack->ucPid));	// PID + EP address
	SL811_Write(REP0DEVADDR,pstRTPack->ucUsbAddr);							// 设备地址
	while(1) //
	{		
		//打包数据
		if(pstRTPack->usRXLen<pstRTPack->ucMaxPackLen)
			ucLen=pstRTPack->usRXLen;  //每包数据长度
		else
			ucLen=pstRTPack->ucMaxPackLen;			
		if(pstRTPack->ucPid==PID_IN)	//IN 包
		{
			ucCmd=SLDATA_RD;			
			if(pstRTPack->ucDataTog) 					// 轮循读DATA0 和DATA1 数据
			{
				ucCmd|=0x40;
				ucAddr=ucData1;
				pstRTPack->ucDataTog=0;	
			}
			else
			{
				ucAddr=ucData0;
				pstRTPack->ucDataTog=1;	
			}
		}
		else if(pstRTPack->ucPid==PID_OUT) //OUT 包
		{
			ucCmd=SLDATA_WR;
			if(pstRTPack->ucDataTog) 					// 轮循读DATA0 和DATA1 数据
			{
				ucCmd|=0x40;
				ucAddr=ucData1;
				pstRTPack->ucDataTog=0;	
			}
			else
			{
				ucAddr=ucData0;
				pstRTPack->ucDataTog=1;	
			}
			if(ucLen)
			{
				SL811_WriteStr(ucAddr,pstRTPack->pucDataBuf,ucLen);
			}
		}
		else								//SETUP 包
		{
			ucAddr=ucData0;					//SETUP包一定用 DATA0 发送 
			if(ucLen)
			{
				SL811_WriteStr(ucAddr,(U8*)(&pstRTPack->stSetup),ucLen);
			}
			ucCmd=SLDATA_WR;	
		}	
			
		//if(pstRTPack->ucEndPoint == 0 && pstRTPack->ucPid != PID_SETUP) 	// for Ep0's IN/OUT token
			// ucCmd|=0x40;
		//启动一个事件 	
		SL811_Write(REP0DATAADDR,ucAddr);					// 传输的数据指针
		SL811_Write(REP0DATALEN,ucLen);					    // 传输的数据长度
		SL811_Write(RSLIRQSTATUS,INT_CLEAR); 				// 清除状态寄存器
RETSTART:			
		SL811_Write(REP0CTRL,ucCmd);						// 启动传输		
		//接收到的 数据包
		if(ucSaveLen)//IN 包 接收数据										
		{	
			SL811_ReadStr(ucAddr,pstRTPack->pucDataBuf,ucSaveLen);
			pstRTPack->pucDataBuf += ucSaveLen;
			ucSaveLen=0;								
		}
		//等待传输完成	
		while(1)
		{														
			ucRetStat = SL811_Read(RSLIRQSTATUS);								
			if((ucRetStat & USB_DETECT)|| (ucRetStat & INSERT_REMOVE))//设备拔除
			{										
				return FALSE;									
			}													
			if(USB_DETECT & USB_A_DONE)	 		//传输完成							
				break;											
		}
		SL811_Write(RSLIRQSTATUS,INT_CLEAR); 	// 清除状态寄存器
		ucRetStat  = SL811_Read(REP0STATUS);	//读EP0状态寄存器
		ucReLen  = SL811_Read(REP0REMAINCNT);	//上次传输剩余字节数据
		//下面返回处理
		if(ucRetStat & EP0_ACK)					//正确返回ASK
		{
			if(pstRTPack->ucPid == PID_SETUP)	//设置包完成该次 传输 退出
				break;			
			else if(pstRTPack->ucPid==PID_OUT)  //OUT祯,未发完就继续发送
			{
				pstRTPack->usRXLen-=ucLen;
				pstRTPack->pucDataBuf+= ucLen;	//更新数据指针
				if(!pstRTPack->usRXLen)
				{						
					break;
				}					
			}
			else if(pstRTPack->ucPid == PID_IN)
			{													
				pstRTPack->usRXLen-=ucLen;
				if(ucReLen==ucLen)								// 检测缓存有没有实据
					ucSaveLen = 0;								// 数据为0
				else											
					ucSaveLen = ucLen;							// 数据为ucLen 
				if(ucReLen || !pstRTPack->usRXLen)           //接收数据完成
				{					
					if(ucSaveLen)										
					{	
						SL811_ReadStr(ucAddr,pstRTPack->pucDataBuf,ucSaveLen);
						pstRTPack->pucDataBuf += ucSaveLen;								
					}
					break;
				}
			}				
		}
		
		if (ucRetStat & EP0_NAK)					//否认返回
		{														
			if(pstRTPack->ucEndPoint==0||pstRTPack->ucPid ==PID_OUT)//一般是发生在速度慢的设备												
				goto RETSTART ;                                   
			else										
				break; //出错跳出
		}
		
		if (ucRetStat & EP0_TIMEOUT)	      		//超时错误
		{														
			if(pstRTPack->ucEndPoint==0)			// 发生于枚举HUB设备时
			{
				if(++ucTimeOut >= TIMEOUT_RETRY)
				{	
					break;										
				}
				goto RETSTART ;  					
			}
			else												
			{													
				if(pstRTPack->ucPid==PID_OUT)
					goto RETSTART ;  		
				 else
				 	break;
			}													
		}
		
		if (ucRetStat & EP0_STALL)  								
			return TRUE;
		if (ucRetStat & EP0_OVERFLOW)
			break;
		if (ucRetStat & EP0_ERROR)
			break;
	}  
	if (ucRetStat & EP0_ACK) 				//  传输正确
		return TRUE;		
	return FALSE;							//  传输失败
}

//端点0 发送控制事务
U8 SL811_EP0Eevent(void)
{
	gstRTPack.ucEndPoint=0;							//
	gstRTPack.ucPid=PID_SETUP;
	gstRTPack.usRXLen=8;
	if(!SL811_RWPack(&gstRTPack))   				//控制包 
		return FALSE;
				
	gstRTPack.ucPid=PID_IN;	
	gstRTPack.usRXLen=gstRTPack.stSetup.usLength; 	//传输数据长度
	gstRTPack.ucDataTog=1;							//第一项数据一定是DATA1
	if(gstRTPack.usRXLen) 							//数据 包
	{
		if(gstRTPack.stSetup.ucRequestType&0x80) 	//读数据 
		{
			gstRTPack.ucPid=PID_IN;	
			if(!SL811_RWPack(&gstRTPack))				
				return FALSE;
			gstRTPack.ucPid=PID_OUT;	 			//状态包和数据包相反			
		}
		else										//写数据 						
		{
			gstRTPack.ucPid=PID_OUT;	
			if(!SL811_RWPack(&gstRTPack))				
				return FALSE;
			gstRTPack.ucPid=PID_IN;	 				//状态包和数据包相反			
		}	
	}
	gstRTPack.usRXLen=0;
	gstRTPack.ucDataTog=1;							//状态 包一定是DATA1
	if(!SL811_RWPack(&gstRTPack))				
			return FALSE;
	return TRUE;
				
}

//请求描述符
U8 SL811_GetDesc(void)
{ 	
	gstRTPack.stSetup.ucRequestType=0x80;
	gstRTPack.stSetup.ucRequest=GET_DESCRIPTOR;
	gstRTPack.ucMaxPackLen=gstUSBDev.ucMaxLen0;
	return SL811_EP0Eevent();
}
//设置地址 
U8 SL811_SetAddress(U8 addr)
{
	gstRTPack.stSetup.ucRequestType=0;
	gstRTPack.stSetup.ucRequest=SET_ADDRESS;
	gstRTPack.stSetup.usValue=addr;
	gstRTPack.stSetup.usIndex=0;
	gstRTPack.stSetup.usLength=0;
	gstRTPack.ucUsbAddr=0;			//没有分配地址之前用0地址
	return SL811_EP0Eevent();
}

U8 SL811_SetConfiguration(U8 ucVal)
{
	gstRTPack.stSetup.ucRequestType=0;
	gstRTPack.stSetup.ucRequest=SET_CONFIG;
	gstRTPack.stSetup.usValue=ucVal;
	gstRTPack.stSetup.usIndex=0;
	gstRTPack.stSetup.usLength=0;
	return SL811_EP0Eevent();
}

unsigned char SL811_SetInterface(void)
{
	gstRTPack.stSetup.ucRequestType=1;
	gstRTPack.stSetup.ucRequest=SET_INTERFACE;
	gstRTPack.stSetup.usValue=0;
	gstRTPack.stSetup.usIndex=0;
	gstRTPack.stSetup.usLength=0;
	return SL811_EP0Eevent();
}

//枚举设备
U8 SL811_EnumUsbDev(U8 ucAddr)
{  
	U8 i,tmp,ucSign;
	PSTDEVDESC  pDev;	
	PSTCFGDESC  pCfg;
	PSTINTFDESC pIfc;
	PSTEPDESC   pEnp;	
	USB_BusReset();
	
	Delay(10000000);
	
	gstUSBDev.ucMaxLen0=64; 					//初始化 端点0最大缓存64

	gstRTPack.pucDataBuf=gszSLBuf;
	gstRTPack.stSetup.usValue=DEVICE<<8;  		//高位是设备描述种类
	gstRTPack.stSetup.usIndex=0;
	gstRTPack.stSetup.usLength=18;
	gstRTPack.ucUsbAddr=0;						//没有分配地址之前用0地址
	if (!SL811_GetDesc())						//召设备描述 符	
		return FALSE;	
	pDev=(PSTDEVDESC)(gszSLBuf);	
	gstUSBDev.ucMaxLen0=pDev->bMaxPacketSize0; //端点0实际大小 
	
	if(!SL811_SetAddress(ucAddr))
		return FALSE;	

	gstRTPack.ucUsbAddr=ucAddr;
	gstRTPack.stSetup.usValue=CONFIGURATION<<8;
	gstRTPack.stSetup.usIndex=0;
	gstRTPack.stSetup.usLength=9;
	if (!SL811_GetDesc())						//重新 召设备描述 符	
		return FALSE;
	
	pCfg =(PSTCFGDESC)gszSLBuf;				//可以增加保存设备信息的函数
	gstRTPack.stSetup.usValue=CONFIGURATION<<8;
	gstRTPack.stSetup.usIndex=0;
	gstRTPack.stSetup.usLength=pCfg->wLength;				//????
	if (!SL811_GetDesc())						//
		return FALSE;
		
	
	pIfc = (PSTINTFDESC)(gszSLBuf + 9);  		//接口描述表	
	gstUSBDev.ucClass=pIfc->iClass;
	gstUSBDev.ucNunEps=((pIfc->bEndPoints <= MAX_EP) ? pIfc->bEndPoints : MAX_EP);

	if(gstUSBDev.ucClass!=0x08)return FALSE;	//不是U盘	
	
	if(!SL811_SetConfiguration(pCfg->bCV))
		return FALSE;
	if(!SL811_SetInterface())
		return FALSE;
		
	tmp = 0;
	ucSign=0;
	for (i=1; i<=gstUSBDev.ucNunEps; i++)						// For each data endpoint
	{
		pEnp = (PSTEPDESC)(gszSLBuf + 9 + 9 + tmp);	   			// point to Endpoint Descp(non-HID)
		if(pEnp->bAttr==0x2)
		{
		    if(pEnp->bEPAdd&0x80)
		    {
		    	if(!(ucSign&0x01))
		    	{
		    		gstUSBDev.ucEPBulkIn=pEnp->bEPAdd&0x0f;
		    		gstUSBDev.ucInMaxLen=pEnp->wPayLoad;
					ucSign|=0x01;
		    	}		    	
		    }
		    else
		    {
		    	if(!(ucSign&0x02))
		    	{
		    		gstUSBDev.ucEPBulkOut=pEnp->bEPAdd&0x0f;
		    		gstUSBDev.ucOutMaxLen=pEnp->wPayLoad;
					ucSign|=0x02;
		    	}
		    }
		}
		tmp += 7;		
	}	
	gstUSBDev.ucInDataTog  = 0; 								// init data toggle	
	gstUSBDev.ucOutDataTog = 0;
	if(ucSign==0x03)    			           	
		return TRUE;
	else
		return FALSE;

}

void USB_Check(void)
{
	SLCheck_SlaveInserRemove();	
	if(stDevSign.ucDevInsert)
	{
		if(SL811_EnumUsbDev(1))
		{
			stDevSign.ucMasDev=TRUE;
		}	
	}
	if(stDevSign.ucMasDev&&stDevSign.ucDevInsert)//U盘插入并枚举成功
	{
	
	
	}		   	

}








⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -