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

USB event is not triggered every time a data array is being received

Hi,

I am testing the USB CDC with nrf52840  and  I want to receive a predefined array of bytes over USB serial every time I send a specific array of bytes.

Just a simple data transmission from PC to nrf52840 and back. Nothing special

For instance, when I send 0x01 0x93 0x01 (command) through the terminal app (docklight) I want to receive 0x01 0x93 0x00 0x00 0x01 ( or whatever I have defined as answer).

The problem is that when I send the command continuously, every four times, I do not get back the answer from the nrf52840.

Also, I noticed that the event handler is not executed the times I get no response to the command I send

When I use another serial terminal app (terminal by Br@y++)  everything works fine and I get answer every time. So I am a little confused since serial configuration is the same for both terminal applications

Here is an image of  Tx and Rx data every time I send the command with docklight terminal ( the one with the issue)

and here is the code  for cdc_acm_event_handler and main () parts

/**
 * @brief User event handler @ref app_usbd_cdc_acm_user_ev_handler_t (headphones)
 * */
static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst,
                                    app_usbd_cdc_acm_user_event_t event)
{
    app_usbd_cdc_acm_t const * p_cdc_acm = app_usbd_cdc_acm_class_get(p_inst);
 
    switch (event)
    {
        case APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN:   // edw bainei molis anoixeis to serial port
        {
            //bsp_board_led_on(LED_CDC_ACM_OPEN);
            devConnected = true;
            /*Setup first transfer*/
            ret_code_t ret = app_usbd_cdc_acm_read(&m_app_cdc_acm,
                                                   m_rx_buffer,
                                                   READ_SIZE);
            UNUSED_VARIABLE(ret);
            break;
        }
        case APP_USBD_CDC_ACM_USER_EVT_PORT_CLOSE:  // edw bainei molis kleiseis to serial port
            //bsp_board_led_off(LED_CDC_ACM_OPEN);
            devConnected = false;
            break;
        case APP_USBD_CDC_ACM_USER_EVT_TX_DONE:  // edw bainei molis oloklhrw8ei mia apostolh data
            //bsp_board_led_invert(LED_CDC_ACM_TX);
             usbd_tx_complete = true;
            break;
        case APP_USBD_CDC_ACM_USER_EVT_RX_DONE: // edw bainei molis oloklhrw8ei mia lhpsh data
        {
            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_t size = app_usbd_cdc_acm_rx_size(p_cdc_acm);
                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);
            } while (ret == NRF_SUCCESS);
          
            usbd_rx_complete = true;
            //-------------------------------------------------------------------
            // bsp_board_led_invert(LED_CDC_ACM_RX);
            break;
        }
        default:
            break;
    }
}



//--------------------main code-----------------
 while(1)
        {
            while (app_usbd_event_queue_process());
            if( usbd_rx_complete == true)
            {
                m_tx_buffer[0] = 0x01;
                m_tx_buffer[1] = 0x93;
                m_tx_buffer[2] = 0x00;
                m_tx_buffer[3] = 0x00;
                m_tx_buffer[4] = 0x01;
          
                err_code = app_usbd_cdc_acm_write(&m_app_cdc_acm, m_tx_buffer, 5);
                while (app_usbd_event_queue_process()); // wait while event process is complete
                usbd_rx_complete = false;
                RED_INV;
                usbd_tx_complete = false;
//                nrf_delay_ms(50);
            }
             
             //nrf_delay_ms(20); BLUE_INV;
             NRF_WDT->RR[0] = WDT_RR_RR_Reload;  // refresh watchdog
        }

Is there something that I have not taken into account?

Thank you for your time

Parents
  • Hi 

    Most likely the problem here is that your non working terminal is not setting the DTR signal, which is needed by the CDC class to open the serial port. 

    In some terminals this is done automatically, while in others it is not. Some terminals require you to set it manually, as described in this case.

    Do you know if the docklight terminal allows you to set this signal?

    Best regards
    Torbjørn 

  • Hi, yes I explicitly set the DTR signal in both terminal applications including docklight.

    1. Is there something in the code I have posted that may result in this behavior? Because otherwise it doesn't make sense to me...

    2. Also, could you please explain me when should I use while (app_usbd_event_queue_process());

    I don't understand why events from the queue are not processed automaticaly and a function must trigger it

  • Hi

    1. Have you changed the READ_SIZE parameter?

    You say you send your command continuously, how often do you send it?

    2. The app_usbd_event_queue_process() function should be called once every time you go through the main while loop, before you go to sleep normally. You shouldn't have to call it after issuing a write, or anywhere else in the code. 

    The reason this is called from the main loop is to avoid running higher level USB processing in interrupt context, which would block other interrupts from being executed.

    Best regards
    Torbjørn 

Reply
  • Hi

    1. Have you changed the READ_SIZE parameter?

    You say you send your command continuously, how often do you send it?

    2. The app_usbd_event_queue_process() function should be called once every time you go through the main while loop, before you go to sleep normally. You shouldn't have to call it after issuing a write, or anywhere else in the code. 

    The reason this is called from the main loop is to avoid running higher level USB processing in interrupt context, which would block other interrupts from being executed.

    Best regards
    Torbjørn 

Children
Related