📄 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 + -