Hi Ray
I got the point and I was investigating further to implement a full asynchronous communications. Let me try to explain what it is happening and if you have any doubt please let me know it.
First of all, the problem here is that you are using same USB Class callback that VCOM example but, in this example, loopback is requiered to get this demo to work fine.
It starts requesting for data, once it receives them, it sends a package with received data ('echo' procedure) and once it has been sent successfully, in the USB_DEV_EVENT_SEND_COMPLETE event, you request for more data and cycle is repeated. So every request either for sending or receiving is completed succesfully.
In your case, you started requesting for data and then you are sending data periodically. Once periodically data has been sent, in USB_DEV_EVENT_SEND_COMPLETE event in USB class callback you request for more data eventhough you didn't received any data before, so this request queues (using one xD entry) and cycle is repeated. It causes xD to be all used and no further requests could be made. In other words, every time a SEND_COMPLETE event is gotten, you request to receive more data eventhough you haven't received it.
I have changed some logic on it and it seems to work as you want to, it uses one bool variable to signal when data has been received and serves to schedule next request.
static bool received_data = TRUE;
VCom_USB_App_Class_Callback function schedules next recv data (Only when data has been received before and send complete is reached )
case USB_DEV_EVENT_SEND_COMPLETE:
{
if ((size != NULL) && (*size != 0) && !(*size % g_bulk_in_max_packet_size))
{
/* If the last packet is the size of endpoint, then send also zero-ended packet,
** meaning that we want to inform the host that we do not have any additional
** data, so it can flush the output.
*/
USB_Class_CDC_Send_Data(*g_cdc_vcom_ptr, DIC_BULK_IN_ENDPOINT, NULL, 0);
}
else if ((start_app == TRUE) && (start_transactions == TRUE))
{
if ((*data != NULL) || ((*data == NULL) && (*size == 0)))
{
/* User: add your own code for send complete event */
/* has data been received? */
if (received_data == TRUE) {
/* Schedule buffer for next receive event */
received_data = FALSE;
USB_Class_CDC_Recv_Data(handle, DIC_BULK_OUT_ENDPOINT,
g_curr_recv_buf, g_bulk_out_max_packet_size);
}
}
}
}
break;
In Virtual_Com_App, signal when data has been received.
void Virtual_Com_App(void)
{
int c;
int received = 0;
/* User Code */
if ((0 != g_recv_size) && (0xFFFFFFFF != g_recv_size))
{
int32_t i;
for (i = 0; i < g_recv_size; i++)
{
usb_if_vcom_put(g_curr_recv_buf[i]);
}
g_recv_size = 0;
/* This flag serves to send NULL package or data package */
received = 1;
/* This flag inform about a receive event, trigger next request */
received_data = TRUE;
}
g_send_size = 0;
while ((c = usb_if_vcom_get()) != -1)
{
g_curr_send_buf[g_send_size++] = c;
if (g_send_size == DATA_BUFF_SIZE)
{
// buffer is full, send it and
// more bytes can be picked up on the next pass
break;
}
}
if (g_send_size)
{
uint8_t error;
uint32_t size = g_send_size;
g_send_size = 0;
error = USB_Class_CDC_Send_Data(*g_cdc_vcom_ptr, DIC_BULK_IN_ENDPOINT, g_curr_send_buf, size);
if (error != USB_OK)
{
/* Failure to send Data Handling code here */
}
}
else if (received == 1)
{
// Tell driver there is no data so it can flush output
USB_Class_CDC_Send_Data(*g_cdc_vcom_ptr, DIC_BULK_IN_ENDPOINT, NULL, 0);
}
return;
}
this time, you only request for new data when you have recevied data before. This way state machine in USB completes all its request and communications works well.
Note: You schedule another USB_Class_CDC_Recv in send_complete event due when you received a data, you either send a NULL package or send data package and both transactions will end in USB_DEV_EVENT_SEND_COMPLETE event.
I hope this can help you.
Best Regards
Isaac
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------