My ASF4 USB CDC Virtual Comm port works, but Why? (SOLVED)

Go To Last Post
3 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

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;
}

---------------------------------------------------------------------------------------------
 

This topic has a solution.
Last Edited: Thu. Oct 1, 2020 - 08:47 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The "echo" function of the example is causing a lot of confusion, it's not usual to have the send and receive depend on each other.

You can do one cdcdf_acm_read in main before your main loop and the next and following read calls can be in usb_device_cb_bulk_out. Similar for the send side, additional cdcdf_acm_write calls can be made in usb_device_cb_bulk_in.

/Lars

 

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the reply.   I added  tthe following to my Initalize() function:

 

    cdcdf_acm_write((uint8_t *)usbd_cdc_buffer, 0);             // Write 0 bytes to initialize
    cdcdf_acm_read((uint8_t *)usbd_cdc_buffer, sizeof(usbd_cdc_buffer));

Now I was able to get ride of those extra read and write command to to the callbacks. Everything works and the code now makes sense. Thanks.