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

questions on usbd_cdc_acm example

Hi,

two days ago I started checking the usbd_cdc_acm example in order to add usb serial comm functionality to my project. and I have some fundamental (newbie) questions.

1. Why nrf_drv_clock_lfclk_request(NULL) is being used outside the usbd library? And how does the program "know" that the lfclck is being used for the usbd functionality since there is no link between those two? I assume that lfclk is used for the usb module  because when I remove this part the USB does not function   :)   

    ret = nrf_drv_clock_init();
    APP_ERROR_CHECK(ret);
    
    nrf_drv_clock_lfclk_request(NULL);

    while(!nrf_drv_clock_lfclk_is_running())
    {
        /* Just waiting */
    }

    ret = app_timer_init();
    APP_ERROR_CHECK(ret);

2. I don't understand the USBD_POWER_DETECTION part. If I place directly the  app_usbd_enable(); and  app_usbd_start(); directly in the code without the if case, the device is recognized as before without issues. So, why does if (USBD_POWER_DETECTION) case  exist? Also from the event handling function I see that the same app_usbd_start()/enable(); functions are being used so what is the difference and why this if/else case is being used in the first place?

 if (USBD_POWER_DETECTION)
    {
        ret = app_usbd_power_events_enable();
        APP_ERROR_CHECK(ret);
    }
    else
    {
        NRF_LOG_INFO("No USB power detection enabled\r\nStarting USB now");

        app_usbd_enable();
        app_usbd_start();
    }

3. If I place an nrf_delay_ms(500)  after the usbd_cdc_acm_write the device appears in the device manager, the terminal app I use is successfully connected to the device ( LED 2 = ON) but data do not appear on the terminal display and LED 4 is always off.

if(m_send_flag)
{
    static int  frame_counter;

    size_t size = sprintf(m_tx_buffer, "Hello USB CDC FA demo: %u\r\n", frame_counter);

    ret = app_usbd_cdc_acm_write(&m_app_cdc_acm, m_tx_buffer, size);
    if (ret == NRF_SUCCESS)
    {
        ++frame_counter;
    }
    nrf_delay_ms(500);    //      <<==================
}

4. If I erase the previous part included in if(m_send_flag)  and I just replace it with the following part to send cntr value (just a counter for test) every 150msec to the PC terminal app

the device is not recognized at all. Why is this happening

size_t size = sprintf(m_tx_buffer, "Counter Value: %u\r\n", cntr);
ret = app_usbd_cdc_acm_write(&m_app_cdc_acm, m_tx_buffer, size);
cntr++;
nrf_delay_ms(150);        
        

Best regards

Thank you for your time!

Parents
  • Hi,

    1. Why nrf_drv_clock_lfclk_request(NULL) is being used outside the usbd library?

    nrf_drv_clock_lfclk_request() is part of the clock driver, and not implemented nor even used by the USB library (though it is used by some of the USB examples). The reason for having this function instead of just starting the LF clock when needed and stopping it when not needed, is that the clock driver use a counter, so that the clock is started when it has been requested, but only stopped after it has been released by all that requested it. This allows multiple modules to use the LF clock and ensures that it only runs when needed, without a risk of one module stopping the clock when another needs it.

    And how does the program "know" that the lfclck is being used for the usbd functionality since there is no link between those two?

    Because the clock driver counts up for any request, and down for any release. The clock is only stopped when the counter goes back to 0. Note that the module does not know which "users" have requested, so it is the callers responsibility to release as needed after requesting. This is a common scheme.

    2. I don't understand the USBD_POWER_DETECTION part. If I place directly the  app_usbd_enable(); and  app_usbd_start(); directly in the code without the if case, the device is recognized as before without issues. So, why does if (USBD_POWER_DETECTION) case  exist?

    USBD_POWER_DETECTION is a configuration define in the USB examples that configure if you should get events for USB detection or not. If your device is always connected to power, then this probably does not make sense. But if you have a battery powered device that can be connected to USB sometimes, you probably want to handle it differently. As you can see from the example code, using USBD_POWER_DETECTION set to true, the examples do not enable USB right away, but wait for the APP_USBD_EVT_POWER_DETECTED.

    4. If I erase the previous part included in if(m_send_flag)  and I just replace it with the following part to send cntr value (just a counter for test) every 150msec to the PC terminal app

    the device is not recognized at all. Why is this happening

    I don't see a significant difference here (other than that you ignore failures to send and still increment the counter, but it should not be related). Perhaps I did not understand all changes you made. Can you make a diff, or shot exactly which changes you did outside the block you have shown?

  • Hi, thank you for your support it really helps me.

    In order to be more easily readable, I include only the while () part, inside main(),  that I basically modified for the test.

     

    while (true)
    {
        while (app_usbd_event_queue_process()); // while an event is under process
        
       
        size_t size = sprintf(m_tx_buffer, "Counter Value: %u\r\n", cntr);
        cntr++;
        ret = app_usbd_cdc_acm_write(&m_app_cdc_acm, m_tx_buffer, size);
        nrf_delay_ms(500);
         
        // if(m_send_flag)
        // {
        //     static int  frame_counter;
        //     size_t size = sprintf(m_tx_buffer, "Hello USB CDC FA demo: %u\r\n", frame_counter);
        //     ret = app_usbd_cdc_acm_write(&m_app_cdc_acm, m_tx_buffer, size);
        //     if (ret == NRF_SUCCESS)
        //     {
        //         ++frame_counter;
        //     }
        // }  
       //nrf_cli_process(&m_cli_uart);
    
       //UNUSED_RETURN_VALUE(NRF_LOG_PROCESS());
        /* Sleep CPU only if there was no interrupt since last loop processing */
       //__WFE();          
    }
    

    Thank you!

  • Hi,

    I see. The problem is that the USB event queue is not processed in time. You could make it work by reducing the delay to e.g. 5 ms instead of 500 ms. But in any case this should just be something you play with, as using busy waiting like this is not good for several reasons.

  • Hi, the maximum delay I can put is 150msec. I created a counter that sends data to USB every N times (where N = 500000 for example)   so the rest of the system will not have to wait and it works fine now

  • One more question. Now that I have begun to implement the USBD module into my project , can I leave this post open for upcoming questions regarding usb implementation or should I close this and  I create a new post?

    Thank you

Reply Children
Related