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

How to emulate synchronize UART communication with libuarte?

I'm working on a simple project based on the USB CDC ACM and libuarte example, the chip is nrf52840.

A function is redirect the USB VCP data  to another MCU via UART, just like what FTDI's FT232RL do.

When a large packet (6k bytes+) comes from USB,  the CDC part split it to 64 bytes packets, then use nrf_libuarte_async_tx function to transfer one by one, the tx queue got full rapidly and data lost.

My question is: how to tx data in synchronize mode?

The related codes:

        case APP_USBD_CDC_ACM_USER_EVT_RX_DONE:
        {
            ret_code_t ret;
            size_t iSize = app_usbd_cdc_acm_bytes_stored(p_cdc_acm);
            int byteIndex = 0;
            do
            {
                /*Get amount of data transfered*/
                size_t size = app_usbd_cdc_acm_rx_size(p_cdc_acm);
                uart_txBuffer[byteIndex++] = m_rx_buffer[0];

                /* Fetch data until internal buffer is empty */
                ret = app_usbd_cdc_acm_read(&m_app_cdc_acm,
                                            m_rx_buffer,
                                            1);

            } while (ret == NRF_SUCCESS);
            wifi_txBuff(&uart_txBuffer[0], byteIndex); 
            nrf_delay_us(87*iSize); //HAVE TO WAIT SOME US TO SENT, LOST DATA WITHOUT THIS DELAY
            NRF_LOG_INFO("USB received: %d %s", byteIndex, (char*)&uart_txBuffer[0]);
            nrf_gpio_pin_toggle(LED_CDC_ACM_OPEN);
            break;
        }

void wifi_txBuff(char *buff, size_t len)
{
    ret_code_t ret = nrf_libuarte_async_tx(&libuarte, buff, len);
    
    if(ret == NRF_ERROR_BUSY)
    {
        buffer_t buf = {
            .p_data = buff,
            .length = len,
        };
        nrf_queue_push(&m_buf_queue, &buf);
        NRF_LOG_INFO("uart is busy, queue it.");
    }
}

PLS: Tried to use libserial example, TX is ok, but  NRF_SERIAL_EVENT_RX_DATA event never triggered for some reason.

Parents
  • I think you should look into change the implementation such that you don't call app_usbd_cdc_acm_read() unless you know that the queue can handle the size (e.g. use nrf_queue_available_get()) of the data received by app_usbd_cdc_acm_read(). I believe not calling app_usbd_cdc_acm_read() will stall the communication on USB, which should not be a problem, it should just cause a delay until queue is ready to receive more data. So the do{}while() should not run more times than nrf_queue_available_get() says it can handle.

    Kenneth

Reply
  • I think you should look into change the implementation such that you don't call app_usbd_cdc_acm_read() unless you know that the queue can handle the size (e.g. use nrf_queue_available_get()) of the data received by app_usbd_cdc_acm_read(). I believe not calling app_usbd_cdc_acm_read() will stall the communication on USB, which should not be a problem, it should just cause a delay until queue is ready to receive more data. So the do{}while() should not run more times than nrf_queue_available_get() says it can handle.

    Kenneth

Children
No Data
Related