Asynchronous UART API (DMA) not working like expected on nrf52840

hi,
i am trying to use the async uart api on a nrf52840 for communicating to a quectel bg95 modem.
no matter which timeout or buffer-size i am using, i am experiencing the problem that that some (1-2) bytes of the modem response are not received (or forwarded via the api) when they are arriving ... they are received with delay, when the next response of the modem comes in.

so the usual communication flow to the modem is:
(1) request from nrf -> modem
(2) response from the modem -> nrf (usually ending with "\r\n")
(3) some delay
(4) next request from nrf -> modem
(5) next response from the modem -> nrf

when using the async api it happens very often, that one or both of "\r\n" of (2) are missing as long as the response of (5) is beginning to come in. then the response of (5) is prepended with the missing "\r\n" of (2).

Parents
  • Can you please post some code snippets of how you have initialized the asyn uart and code snippets to show transfers from nrf side.

    Have you already verified on the the modem transmit lines (using logic analyzer of oscilloscope) that modem is sending the data correctly?

  • static void Qud_Init()
    {
        uart_callback_set( Qud_uartDevice, 
                           Qud_DmaUartCallback, 
                           NULL );
    
        uart_rx_enable( Qud_uartDevice,
                        dmaBuffer->data,  
                        sizeof( dmaBuffer->data ), 
                        1000 /* us */ );
    }
    
    
    
    
    static void Qud_DmaUartCallback( const struct device* dev,
                                     struct uart_event*   evt,
                                     void*                user_data)
    {
        switch ( evt->type )
        {
            case UART_RX_RDY:
                {
                    Qud_RxQueueEntry_T e = QUD_RX_QUEUE_ENTRY_INIT;
    
                    e.length = evt->data.rx.len;
                    memcpy( e.data, 
                            &( evt->data.rx.buf[ evt->data.rx.offset ] ),
                            evt->data.rx.len );
    
                    k_msgq_put( &Qud_rxQueue, 
                                &e, 
                                K_NO_WAIT );
                }
                break;
                
            default:
                break;
        }
    }

    There is also a logic analyzer connected. The modem sends the data properly.


    As mentioned in my post before: The data is not lost, but it is received with a more or less big delay .... depending on point when the modem sends the next bytes (usually part of the next command).

    The code is part of a battery-powered device, where the activation time of the modem is quite critical for the overall power-consumption. Therefore we are interested in having as short delays as possible during the modem communication.

    As the uart-callback function is called from an isr-context I tried various different message passing variants. It seemed that all of them did not make any difference for this problem. The one here uses a very simple message queue without any optimizations.

Reply
  • static void Qud_Init()
    {
        uart_callback_set( Qud_uartDevice, 
                           Qud_DmaUartCallback, 
                           NULL );
    
        uart_rx_enable( Qud_uartDevice,
                        dmaBuffer->data,  
                        sizeof( dmaBuffer->data ), 
                        1000 /* us */ );
    }
    
    
    
    
    static void Qud_DmaUartCallback( const struct device* dev,
                                     struct uart_event*   evt,
                                     void*                user_data)
    {
        switch ( evt->type )
        {
            case UART_RX_RDY:
                {
                    Qud_RxQueueEntry_T e = QUD_RX_QUEUE_ENTRY_INIT;
    
                    e.length = evt->data.rx.len;
                    memcpy( e.data, 
                            &( evt->data.rx.buf[ evt->data.rx.offset ] ),
                            evt->data.rx.len );
    
                    k_msgq_put( &Qud_rxQueue, 
                                &e, 
                                K_NO_WAIT );
                }
                break;
                
            default:
                break;
        }
    }

    There is also a logic analyzer connected. The modem sends the data properly.


    As mentioned in my post before: The data is not lost, but it is received with a more or less big delay .... depending on point when the modem sends the next bytes (usually part of the next command).

    The code is part of a battery-powered device, where the activation time of the modem is quite critical for the overall power-consumption. Therefore we are interested in having as short delays as possible during the modem communication.

    As the uart-callback function is called from an isr-context I tried various different message passing variants. It seemed that all of them did not make any difference for this problem. The one here uses a very simple message queue without any optimizations.

Children
No Data
Related