Тема поднималась милион раз, но никто так и не удосужился запостить пример. Значит буду первым:
Код
#define MASTER_MODE 0x80
void SL811_Init(void)
{
SL811Write(cDATASet, 0xe0); //SOF Timeout Value
SL811Write(cSOFcnt, 0x2e | MASTER_MODE);
SL811Write(CtrlReg, 0x5);
SL811Write(EP0Status, PID_SOF);
SL811Write(EP0Counter, 0); //Set Endpoint Zero
SL811Write(EP0Control, 0x01); //Start the SOF
SL811Write(IntEna, INSERT_REMOVE); //USB-A, Insert/Remove, USB_Resume.
SL811Write(IntStatus, INT_CLEAR); //Clear Interrupt enable status
}
#define NO_ERROR 0
#define ERROR_TIMEOUT 1
#define ERROR_STALL 2
#define ERROR_OVERFLOW 3
#define ERROR_EP0_ERROR 4
#define ERROR_UNKNOWN 5
int SendData(void * pData, int DataSize)
{
unsigned char result, intr, remainder,timeout;
SL811BufWrite(EP0_Buf,pData,DataSize);
SL811Write(EP0Status,(PID_SETUP | 0)); // PID + EP address
SL811Write(EP0Counter,0); // USB address
SL811Write(EP0Address,EP0_Buf); // buffer address, start with "data0"
SL811Write(EP0XferLen,DataSize); // data transfer length
SL811Write(IntStatus,INT_CLEAR); // clear interrupt status
SL811Write(EP0Control,DATA0_WR);
timeout=10;
while(1)
{
do
{
intr = SL811Read(IntStatus); // wait for interrupt to be done
if((intr & USB_RESET) || (intr & INSERT_REMOVE)) //leave if device is removed
return 1;
} while (!(intr & USB_A_DONE)); // interrupt done !!!
SL811Write(IntStatus,INT_CLEAR); // clear interrupt status
result = SL811Read(EP0Status); // read EP0status register
remainder = SL811Read(EP0Counter); // remainder value in last pkt xfer
if (result & EP0_ACK)
return 0;
if (result & EP0_NAK) // NAK Detected
{
SL811Write(IntStatus,INT_CLEAR); // clear interrupt status, need to
SL811Write(EP0Control,DATA0_WR); // re-arm and request for last cmd, IN token
result = 0; // respond to NAK status only
}
if (result & EP0_TIMEOUT) // TIMEOUT Detected
{
if(timeout)
{
timeout--;
}
else
return ERROR_TIMEOUT; // exit on the timeout detected
SL811Write(IntStatus,INT_CLEAR); // clear interrupt status, need to
SL811Write(EP0Control,DATA0_WR); // re-arm and request for last cmd again
}
if (result & EP0_STALL) // STALL detected
return ERROR_STALL; // for unsupported request.
if (result & EP0_OVERFLOW) // OVERFLOW detected
return ERROR_OVERFLOW;
if (result & EP0_ERROR) // ERROR detected
return ERROR_EP0_ERROR;
}
return ERROR_UNKNOWN;
}
int GetReply(void * pData, int DataSize)
{
unsigned char result, intr, remainder,timeout;
SL811Write(EP0Status,(PID_IN | 0)); // PID + EP address
SL811Write(EP0Counter,0); // USB address
SL811Write(EP0Address,EP0_Buf); // buffer address, start with "data0"
SL811Write(EP0XferLen,DataSize); // data transfer length
SL811Write(IntStatus,INT_CLEAR); // clear interrupt status
SL811Write(EP0Control,DATA0_RD);
timeout=10;
while(1)
{
do
{
intr = SL811Read(IntStatus); // wait for interrupt to be done
if((intr & USB_RESET) || (intr & INSERT_REMOVE)) //leave if device is removed
return 1;
} while (!(intr & USB_A_DONE)); // interrupt done !!!
SL811Write(IntStatus,INT_CLEAR); // clear interrupt status
result = SL811Read(EP0Status); // read EP0status register
remainder = SL811Read(EP0Counter); // remainder value in last pkt xfer
if (result & EP0_ACK)
{
if(remainder!=DataSize)
{
SL811BufRead(EP0_Buf, pData, DataSize);
return 0;
}
}
if (result & EP0_NAK) // NAK Detected
{
SL811Write(IntStatus,INT_CLEAR); // clear interrupt status, need to
SL811Write(EP0Control,DATA0_WR); // re-arm and request for last cmd, IN token
result = 0; // respond to NAK status only
}
if (result & EP0_TIMEOUT) // TIMEOUT Detected
{
if(timeout)
{
timeout--;
}
else
return ERROR_TIMEOUT; // exit on the timeout detected
SL811Write(IntStatus,INT_CLEAR); // clear interrupt status, need to
SL811Write(EP0Control,DATA0_WR); // re-arm and request for last cmd again
}
if (result & EP0_STALL) // STALL detected
return ERROR_STALL; // for unsupported request.
if (result & EP0_OVERFLOW) // OVERFLOW detected
return ERROR_OVERFLOW;
if (result & EP0_ERROR) // ERROR detected
return ERROR_EP0_ERROR;
}
return ERROR_UNKNOWN;
}
unsigned char Buffer[0x64];
void testSL811(void)
{
int error;
SetupPKG pkg;
pkg.bmRequest=0x80;
pkg.bRequest=0x06;
pkg.wValue=0x200;
pkg.wIndex=0x00;
pkg.wLength=0xFF00;
SL811ClockInit();
SL811_Init();
error=SendData(&pkg,sizeof(pkg));
if (!error)
{
error=GetReply(Buffer,0x9);
}
}
Код не идеальный, надо доделывать функцию чтения. Он инитит хост в режиме low-speed и позволяет вам послать SETUP пакет GET_DESCRIPTOR и вычитать 9-байтов ответа от Slave устройства. Все нехватающие функции и define есть в cy3662/EZ811 development kit'e. Его можно взять
вот тут