The information on using ASF4 with USB is somewhere between sparse and non-existent as far as I can tell. I actually have my USB CDC virtual COM port working. However, I am not sure why it working. I had to add some code that does not make sense to me. That bothers me. I am hoping someone here can enlighten me. I based my code on the USB CDC Echo example provided in ASF4 generated by Atmel Start on a SAMV71.
My application clears a flag when it writes to the USB. When the transmit callback says the transmit is done, the flag is cleared.
Otherwise, another call to cdcdf_acm_write() will overwrite the buffer in the middle of transmission with bad results. When calling my
write function, if the flag is true, the application sets the flag = false and calls the USB write. If the flag is false, the data is put into a transmit FIFO for transmission later.
I modified the code in usb_start.c .
** Transmit Callback (usb_device_cb_bulk_in(()) **
On the Transmit callback, I set a flag bDataXmittedFlag so that I know when the transmit has completed.
However, I have found that I need to do a cdcdf_acm_read() call in the transmit callback, or the USB channel will hang.
Why do I need to do a read in the transmit function?
** Receive Callback (usb_device_cb_bulk_out()) **
On the receive callback, I copy the data bytes into my recieve FIFO (call_CopyUsbDataToFifo(count) so that I can process them later fromthe main routine.
However, I have found that the USB channel hangs unless I do a write of 0 bytes (cdcdf_acm_write((uint8_t *)usbd_cdc_buffer, 0);
during the receive callback. Why do I need to do this? Without this line, the USB channel hangs.
I don't like to have code in my programs that I don't understand even it is working. If someone can explain why this works I would
appreciate it. Or maybe someone can tell me a better way to do this?
Here is code I modified in usb_start.c
------------------------------------------------------------------------------------------
volatile bool bDataXmittedFlag = true; ///< When true, data has been transmitted
extern bool call_CopyUsbDataToFifo(uint32_t ui32Count);
/**
* \brief Callback invoked when bulk OUT data received RCV
*/
static bool usb_device_cb_bulk_out(const uint8_t ep, const enum usb_xfer_code rc, const uint32_t count)
{
/* No error. */
call_CopyUsbDataToFifo(count); // Get USB data into my RxFIFO
cdcdf_acm_write((uint8_t *)usbd_cdc_buffer, 0); // Write 0 bytes to end transaction ????
return false;
}
/**
* \brief Callback invoked when bulk IN data received XMIT
*/
static bool usb_device_cb_bulk_in(const uint8_t ep, const enum usb_xfer_code rc, const uint32_t count)
{
cdcdf_acm_read((uint8_t *)usbd_cdc_buffer, sizeof(usbd_cdc_buffer)); //????
bDataXmittedFlag = true;
return false;
}
/**
* \brief Callback invoked when Line State Change
*/
static bool usb_device_cb_state_c(usb_cdc_control_signal_t state)
{
if (state.rs232.DTR) {
/* Callbacks must be registered after endpoint allocation */
cdcdf_acm_register_callback(CDCDF_ACM_CB_READ, (FUNC_PTR)usb_device_cb_bulk_out);
cdcdf_acm_register_callback(CDCDF_ACM_CB_WRITE, (FUNC_PTR)usb_device_cb_bulk_in);
/* Start Rx */
cdcdf_acm_read((uint8_t *)usbd_cdc_buffer, sizeof(usbd_cdc_buffer));
}
/* No error. */
return false;
}
---------------------------------------------------------------------------------------------