USB function driver on freescale MXl
- From: "dchung" <daeinchung@xxxxxxxxx>
- Date: 20 Nov 2006 10:55:07 -0800
hello folks,
I'm developing a USB function driver (CDC-ACM class) on iMXl.
Everything went smooth until I found there were a problem when device
tried sending the configuration descriptor to a host. I realized that
when the device want to send the data through EP0 more than 32 bytes,
then it stop sending it and reset by the host. The firmware
implementation is very straightforward as you can see from below. Right
after it sees the Get_Descriptor request with configuration option, it
start send that corresponding descriptor which is 67 bytes total.
Because maximum size of EP0 FIFO is 32 bytes, I chopped the whole data
into three consecutive transfers. I believe there should be something
between each transfer to guarantee that each transfer is successful.
Happy Thanksgiving.....
Thanks in Advance,
Daein
++++++++++++++++++++++++
case CONFIGURATION: // 0x02
p = (unsigned char*)&ConfigDescSet;
//len = (U8) MIN_H(sizeof(Std_Config_descriptor),_gUsbDevReq[6]);
len = (U8) MIN_H(67,_gUsbDevReq[6]);
// Send the reply data.
iterate = (len / 32);
(len%32)?(iterate++):iterate;
while(iterate != 0)
{
fnSendEP0Data(p, len, &sentLen);
if (sentLen != 0) // if data were sent
successfully.
{
p += sentLen;
len -= sentLen;
iterate--;
}
// TESTING +++
//else
// break;
// TESTING ---
}
break;
-----------------------------------------
void fnSendEP0Data(unsigned char *pVoid, int length, int *sentLen)
{
int i, j;
int nNumPacket = length / EP0Len;
int tLen = 0;
int nRemaind=0;
unsigned char *pBuf = (unsigned char*)pVoid;
*sentLen = 0;
if(length==0)
return;
if(length % EP0Len)
nNumPacket++;
// USB FIFO data write is in big-endian format.
for(i=0; i<nNumPacket; i++)
{
// check how many bytes are left in EP0 FIFO
if ((((USB_EP0_STAT & (0x7F << 16)) >> 16) + EP0Len) > 32)
{
// check EOF
if (!(USB_EP0_INTR & (1<<2)))
{
continue;
}
else
{
*sentLen = tLen;
return;
}
}
if( ((pVoid-pBuf)+length) >= EP0Len)
{
USB_EP0_FDAT =
((*pBuf)<<24)|(*(pBuf+1)<<16)|(*(pBuf+2)<<8)|(*(pBuf+3));
USB_EP0_FCTRL |= 0x20000000; // next write is last one of
packet
USB_EP0_FDAT =
(*(pBuf+4)<<24)|(*(pBuf+5)<<16)|(*(pBuf+6)<<8)|(*(pBuf+7));
pBuf+=8;
tLen += 8;
}
else
// Packet size is less than EP0Len (8 bytes)
{
nRemaind = (pVoid-pBuf) + length;
if(nRemaind>=sizeof(U32))
{
if(nRemaind==sizeof(U32))
{
USB_EP0_FCTRL |= 0x20000000; // next write is last
one of packet
}
USB_EP0_FDAT=((*pBuf)<<24)|(*(pBuf+1)<<16)|(*(pBuf+2)<<8)|(*(pBuf+3));
pBuf+=4;
tLen += 4;
}
nRemaind=(pVoid-pBuf)+length;
for(j=0; j<nRemaind; j++)
{
if(j==(nRemaind-1))
{
USB_EP0_FCTRL |= 0x20000000; // next write is last
one of packet
}
*((volatile U8 *)((U32)&USB_EP0_FDAT+3)) = (U8)*pBuf;
pBuf++;
tLen += 1;
}
}
*sentLen = tLen;
}
//Checck if need to end with a zero length packet
if((!(length % EP0Len)) && (length != 8))
{
//SET_BITS(pEP0->STAT, USB_EPn_STAT_ZLPS, 1);
USB_EP0_STAT |= ZLPS_MASK; // next one is a zero length
packet
}
// Turn on SOF interrupt to signal CMD_OVER bit
//SET_BITS(pUSBDReg->USB_MASK, USB_MASK_SOF, 0);
if (length != 32)
USB_MASK &= ~(1<<6);
}
++++++++++++++++++++++++++++++++++++
.
- Prev by Date: Re: Device standalone + eVC
- Next by Date: Re: check image version
- Previous by thread: check image version
- Next by thread: Falcon BSP in Wince 4.0
- Index(es):
Relevant Pages
|