This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

USBD high level API usage question

Hello,.

I have a question about using app_usbd_cdc_acm_read and app_usbd_cdc_acm_read_any in SDK15.2.0,

I am not sure I fully understand the description in reference of app_usbd_cdc_acm_read call:

According to this description, when there is not enough data in internal buffer can fill user buffer, the call will return a NRF_ERROR_IO_PENDING, so what will happen to the data stored in internal buffer now? will the data be copied to user buffer or just stay there waiting for enough data arrived ? if the data is copied to user buffer, then will APP_USBD_CDC_ACM_USER_EVT_RX_DONE will be raised at this point? 

However, if the data is not copied to user buffer, then what will happen if, the expected receiving size if larger than internal buffer size, say, 256bytes or even larger? won't the data in internal buffer overwritten by coming bytes?

thank your for your help!

/Roland

Parents
  • Hi Roland,

    According to this description, when there is not enough data in internal buffer can fill user buffer, the call will return a NRF_ERROR_IO_PENDING, so what will happen to the data stored in internal buffer now? will the data be copied to user buffer or just stay there waiting for enough data arrived ? if the data is copied to user buffer, then will APP_USBD_CDC_ACM_USER_EVT_RX_DONE will be raised at this point? 

    RX data is continuously written to the user buffer. APP_USBD_CDC_ACM_USER_EVT_RX_DONE is signaled to the application once the provided buffer(s) are full (i.e, received bytes == length). The code below will for instance trigger the RX event after receiving 256 bytes. In other words, the data will be copied to the user buffer while receiving, but RX done event will come after receiving all 256 bytes. 

    ret = app_usbd_cdc_acm_read(&m_app_cdc_acm,
                                                      m_rx_buffer,
                                                      256);

  • Thank you Vidar.

    I am considering using wether app_usbd_cdc_acm_read or app_usbd_cdc_acm_read_any. The problem about app_usbd_cdc_acm_read is in case host activity is un-predictable then I have no idea how long I need to wait before 256 bytes buffer is filled. As you explained, it seems I have no way to poll the double buffer to access the bytes already received before APP_USBD_CDC_ACM_USER_EVT_RX_DONE is raised.

    Using  app_usbd_cdc_acm_read_any instead, however, getting out of my expectation. In my experiment I setup a timer, say , every 1 second, to fire app_usbd_cdc_acm_read_any call. Host keeps sending characters to device at baud rate 57600. So I am expecting when each timer fires app_usbd_cdc_acm_read_any will return with at least few characters received, not 1 byte. In real testing however, app_usbd_cdc_acm_read_any always return 1 byte is read. This will be no difference than using app_usbd_cdc_acm_read with buffer size of 1, which is I am trying to avoid to use. 

    I am not sure what I was doing wrong, or that is just how app_usbd_cdc_acm_read_any behave? That is why I am asking the extended question in previous post.

    /Roland

  • Thanks Vidar.

    I did know that APP_USBD_CDC_ACM_USER_EVT_RX_DONE is trigged even buffer not full when using app_usbd_cdc_acm_read_any. 

    What I am trying to find out is what size will app_usbd_cdc_acm_read_any return, is it always 1 bytes?

    I do not want to receive data one bytes per polling, as this seems quite low efficient and interrupts other tasks too often.

    Consider a typical setup: the device called app_usbd_cdc_acm_read_any and wait for incoming bytes, and host start to send, say, 32bytes in one packet. So will app_usbd_cdc_acm_read_any return size of 1 as soon as first byte is received and repeat for 32 times,  or 32 after complete packet received?

  • What I am trying to find out is what size will app_usbd_cdc_acm_read_any return, is it always 1 bytes?

    In the code above, app_usbd_cdc_acm_rx_size() will return anything between 1-256 depending on how fast the data is being received. "Size" corresponds to the actual number of bytes stored to the user buffer (m_rx_buffer in this case). It will not return 1 If you received a larger chunk of data.

    Consider a typical setup: the device called app_usbd_cdc_acm_read_any and wait for incoming bytes, and host start to send, say, 32bytes in one packet. So will app_usbd_cdc_acm_read_any return size of 1 as soon as first byte is received and repeat for 32 times,  or 32 after complete packet received?

    In this case, APP_USBD_CDC_ACM_USER_EVT_RX_DONE  should occur once, and app_usbd_cdc_acm_rx_size should return 32. 

  • Thanks for the explanation Vidar.

    I will check my test further to see if anything wrong, as I always get 1 byte in my side.

    Besides, I actually more prefer timer based polling using app_usbd_cdc_acm_read_any. The code example you gave above keeps CPU busy receiving data. In case host is continuously sending data to device this will occupy CPU time too long for other tasks.

    A timer based polling mode is better as CPU can share the load between all tasks, as long as buffer size properly selected.

    Do you think app_usbd_cdc_acm_read_any still work as you explained in timer based polling mode? 

  • I'm not sure why you only receive one byte. Here are the changes I made in SDK 15.3.0 example:

    diff --git a/examples/peripheral/usbd_cdc_acm/main.c b/examples/peripheral/usbd_cdc_acm/main.c
    index 51e6a3f..a87c3cd 100644
    --- a/examples/peripheral/usbd_cdc_acm/main.c
    +++ b/examples/peripheral/usbd_cdc_acm/main.c
    @@ -129,7 +129,7 @@ APP_USBD_CDC_ACM_GLOBAL_DEF(m_app_cdc_acm,
                                 APP_USBD_CDC_COMM_PROTOCOL_AT_V250
     );
     
    -#define READ_SIZE 1
    +#define READ_SIZE 256
     
     static char m_rx_buffer[READ_SIZE];
     static char m_tx_buffer[NRF_DRV_USBD_EPSIZE];
    @@ -150,9 +150,9 @@ static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst,
                 bsp_board_led_on(LED_CDC_ACM_OPEN);
     
                 /*Setup first transfer*/
    -            ret_code_t ret = app_usbd_cdc_acm_read(&m_app_cdc_acm,
    -                                                   m_rx_buffer,
    -                                                   READ_SIZE);
    +            ret_code_t ret = app_usbd_cdc_acm_read_any(&m_app_cdc_acm,
    +                                                       m_rx_buffer,
    +                                                       READ_SIZE);
                 UNUSED_VARIABLE(ret);
                 break;
             }
    @@ -173,9 +173,9 @@ static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst,
                     NRF_LOG_INFO("RX: size: %lu char: %c", size, m_rx_buffer[0]);
     
                     /* Fetch data until internal buffer is empty */
    -                ret = app_usbd_cdc_acm_read(&m_app_cdc_acm,
    -                                            m_rx_buffer,
    -                                            READ_SIZE);
    +                ret = app_usbd_cdc_acm_read_any(&m_app_cdc_acm,
    +                                                m_rx_buffer,
    +                                                READ_SIZE);
                 } while (ret == NRF_SUCCESS);
     
                 bsp_board_led_invert(LED_CDC_ACM_RX);
    

    And here is the log output I got (notice that it receives up to 64 bytes in this case - baudrate set to 115200):

    Can you try the same?

  • I did some other testing about the 840 USBD interface from a MACBook using ttyusbxxxx interface, with a piece of code running on MAC that read/write from/to 840. 

    According to the few test results so far,  this time the result looks the same as you advised.Thanks a lot for your support. I will do further more testings to look into the details.

    BTW, I am still using timer on 840 side to fire USB_READ_ANY operations, as I assume this way CPU can share more idle time with other tasks.

Reply
  • I did some other testing about the 840 USBD interface from a MACBook using ttyusbxxxx interface, with a piece of code running on MAC that read/write from/to 840. 

    According to the few test results so far,  this time the result looks the same as you advised.Thanks a lot for your support. I will do further more testings to look into the details.

    BTW, I am still using timer on 840 side to fire USB_READ_ANY operations, as I assume this way CPU can share more idle time with other tasks.

Children
No Data
Related