AnsweredAssumed Answered

usb odd even buffer descriptors

Question asked by Salman Razzaq on Aug 14, 2018
Latest reply on Aug 14, 2018 by Fang Li

Hi,

I am sending data stream from usb bulk endpoint. I am reading the data but it is not in right order. Sometimes i am getting two ODD or EVEN buffers simultaneously. It should be EVEN then ODD, then EVEN again etc. I don't know what i have done wrong. Here is the code.


// BULK Endpoint TX interrupt handler
static void bulk_ep_handler( BYTE stat )
{
volatile BUF_DESC *buf_desc;
bool odd;

odd = ODD_STAT(stat);

// Next alternate buffer
EndPoint[EP1].tx_evenBD = (BYTE)(odd ^ BD_ODD);

// OWN the buffer descriptor on which we received the
// data transfer acknowledgement
buf_desc = TX_BUF_DESC( EP1, odd );
buf_desc->Stat._byte = 0;
}

void usb_write_stream(BYTE *buf, DWORD buf_len)
{
volatile BUF_DESC *buf_desc;
BYTE status;
BYTE next_buf;

status = get_ep1_tx_transfer_status();
if( status == USB_STATUS_IDLE )
{
next_buf = select_ep1_tx_buffer_desc();

buf_desc = TX_BUF_DESC( EP1, next_buf );
buf_desc->Count = TO_LE16( ((WORD)buf_len) );
buf_desc->Addr = TO_LE32( ((DWORD)buf) );

ready_tx_buffer( EP1, next_buf );

// Toggle DATA0/1 flag on the endpoint
EndPoint[EP1].tx_DTS ^= DATA1_DTS;
}
}


static BYTE get_ep1_tx_transfer_status()
{
BYTE ep_ctl;
volatile BUF_DESC *even_desc;
volatile BUF_DESC *odd_desc;
BYTE status = USB_STATUS_IDLE;

ep_ctl = MCF_USB_OTG_ENDPT( EP1 );

if( (ep_ctl & (MCF_USB_OTG_ENDPT_EP_TX_EN | MCF_USB_OTG_ENDPT_EP_RX_EN)) == 0 )
{
status = USB_STATUS_DISABLED;
}
else if( ep_ctl & MCF_USB_OTG_ENDPT_EP_STALL )
{
status = USB_STATUS_STALLED;
}
else
{
even_desc = TX_BUF_DESC( EP1, BD_EVEN );
odd_desc = TX_BUF_DESC( EP1, BD_ODD );

if( (even_desc->Stat.SieCtlBit.OWN == 1) || (odd_desc->Stat.SieCtlBit.OWN == 1) )
{
status = USB_STATUS_TRANSFER_IN_PROGRESS;
}
}

return status;
}


static BYTE select_ep1_tx_buffer_desc()
{
volatile BUF_DESC *buf_desc;
BYTE buf;
DWORD ctl;

/* Find out which buffer shall be used. */
buf_desc = TX_BUF_DESC( EP1, BD_EVEN );
ctl = buf_desc->Stat._byte & _SIE_OWN;

buf_desc = TX_BUF_DESC( EP1, BD_ODD );
ctl |= ((buf_desc->Stat._byte & _SIE_OWN) << 1);

switch( ctl )
{
case 0:
{
/* No buffer is used by the USB module. Fill the one
we think is the next. */
buf = EndPoint[EP1].tx_evenBD;
EndPoint[EP1].tx_evenBD ^= BD_ODD;
}
break;

case _SIE_OWN:
{
/* Buffer 0 is used by the USB. */
buf = BD_ODD;
EndPoint[EP1].tx_evenBD = BD_EVEN;
}
break;

case (_SIE_OWN << 1):
{
/* Buffer 1 is used by the USB. */
buf = BD_EVEN;
EndPoint[EP1].tx_evenBD = BD_ODD;
}
break;

default:
buf = BD_UNKNOWN;
break;
}

return buf;
}

 

 


Thanks in advance.

Regards.

Outcomes