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

  • Hi Roland,

    You will still get the APP_USBD_CDC_ACM_USER_EVT_RX_DONE event when using *_read_any as well, so you don't need a timer for polling the buffer size. The event can get triggered even if you haven't filled up the buffer. E.g., you will get the event if you only send a single character.  

            case APP_USBD_CDC_ACM_USER_EVT_RX_DONE:
            {
                ret_code_t ret;
                NRF_LOG_INFO("Bytes waiting: %d", app_usbd_cdc_acm_bytes_stored(p_cdc_acm));
                do
                {
                    
                    /*Get amount of data transfered*/
                    size = app_usbd_cdc_acm_rx_size(p_cdc_acm);
                    NRF_LOG_INFO("%d bytes written to m_rx_buffer", size);
    
                    /* Set up new buffer*/
                    ret = app_usbd_cdc_acm_read_any(&m_app_cdc_acm,
                                                     m_rx_buffer,
                                                     256);
                } while (ret == NRF_SUCCESS);

  • 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?

Related