Content originally posted in LPCWare by pra18 on Wed Feb 11 03:37:59 MST 2015
Hi,
Thank you for replying to my problem.
I have tried to explain below what is happening and also code which I use . I sent descriptors earlier.
Case1:
when I use my device in ModBus mode, this function gets repeatedly called by the protocol to request USB to send a block of data
This is where I am seeing that the problem is
My function to Transmit a block of data is as below.
int SendBlockOfData(const unsigned char *UsbData,unsigned int NrOfBytes, void (*cb)(void))
{
int rc = 0;
/*signal via hook */
CompleteHook = cb;
/*make safe copy*/
(void)memcpy(UsbTxBuff, UsbData, NrOfBytes);
/*flag Tx */
UsbTxBusy |= USB_TX_BUSY;
/* enter critical section */
NVIC_DisableIRQ(LPC_USB_IRQ);
rc = USBD_API->hw->WriteEP(UsbdHandle, USB_CDC_IN_EP,(uint8_t *) UsbTxBuff, NrOfBytes);
/* enter critical section */
NVIC_EnableIRQ(LPC_USB_IRQ);
return rc;
}
In this function argument, There is a callback TxHook which is used to notify higher protocol layer that physical layer USB Tx is complete.
Problem observed:
There are timeouts seen on the Host side when the PC program requests large block of data from the device.
For Data with small frames there is no problem. no delay and response is quick.
for data having larger frame size while sending blocks of data, the timeout occurs on the Host PC Program with WBVAL(64) in descriptors while with WBVAL(1C)
it works correctly and no timeouts, though very rare.
Case2 : ASCII mode
when I use the device in ASCII mode this function gets called
int SendDataUSB(unsigned char Data)
{
/* not transmitting a block of data in which case assign this hook to NULL*/
CompleteHook = NULL;
/* write Tx */
if((UsbWrite(&Data,1))== 1)
return (int)Data;
return (-1);
}
I dont see any problem in ASCII mode even with WBVAL(64) or if I change it to WBVAL(64). Everything works fine.
I feel it does not affect ASCII mode of transmission.
Below are my IN and OUT Handlers
ErrorCode_t INHandler(USBD_HANDLE_T UsbdHandle, void *Data, uint32_t Event)
{
Data = Data ;
if (Event == USB_EVT_IN)
{
/* allow next send */
UsbTxBusy &= ~USB_TX_BUSY;
/* call registered hook
if(CompleteHook != NULL)
{
CompleteHook();
CompleteHook = NULL;
}
}
return LPC_OK;
}
volatile uint16_t BytesCount = 0;
ErrorCode_t OUTHandler(USBD_HANDLE_T UsbdHandle, void *Data, uint32_t Event)
{
int i;
(void )&Data;
switch (Event)
{
case USB_EVT_OUT:
BytesCount = USBD_API->hw->ReadEP(UsbdHandle, USB_CDC_OUT_EP, &RxHelper[0]);
if(LocalBytesCount != 0)
{
/* reset to 0 */
RxBusy = 0;
}
for(i = 0; i <BytesCount; i++)
{
RxRing = RxHelper;
}
break;
case USB_EVT_OUT_NAK:
if (RxBusy == 0)
/* we've not queued the Rx buffer, so handle this NAK event. */
{
/* queue free buffer for RX and send DMA request */
USBD_API->hw->ReadReqEP(UsbdHandle, USB_CDC_OUT_EP, &RxHelper[0], RX_BUFFER);
/* Flag RX buffer as busy and allow base handler to queue the buffer. */
RxBusy = 1;
}
else
{
/* we've already queued the Rx buffer, so ignore this NAK event. */
return LPC_OK;
}
break;
default:
break;
}
return LPC_OK;
}
Here is my Write routine
int Write(uint8_t *Buf, uint32_t Len)
{
int rc = 0;
if (UsbTxBusy & USB_TX_CONNECTED)
{
while(( UsbTxBusy & USB_TX_BUSY) != 0);
UsbTxBusy |= USB_TX_BUSY;
/* enter critical section */
rc = USBD_API->hw->WriteEP(UsbdHandle, USB_CDC_IN_EP, (uint8_t *)Buf, Len);
/* exit critical section */
}
return rc;
}
Regards,