UART RX timing with external device

Hello, 

I wanted to reach out about the issue I've been running into regarding the UART Async API. I am having trouble narrowing down what the cause could be. 

I am using an nRF9161 DK and the v2.9 SDK. The communication below is using UART2.

Right now I have the 9161 connected to an external device (pin pad / card reader). I can successfully send data over the TX line and receive data over the RX line, but there are times when when no data comes back over the RX line. Specifically when a card is presented rather than a key pressed. 

TX timeout - SYS_FOREVER_MS

RX timeout - 16000 micro seconds (I have tried ranges from 2000 to 16000)

The sequence of events is as follows:

A button on the pin pad is pressed.

The 9161 is triggered via an interrupt pin.

An ISR puts a operation into the work queue. 

UART ASYNC API is called to enable TX pin (uart_tx).

UART_TX_DONE enables the RX buffer (uart_rx_enable).  
_________ (only works part of the time)__________
UART_RX_RDY submits a message queue to process the data.
I seem to have a timing error with receiving data. Again, this works pretty consistently with the pin, but never with the card. I was hoping you could provide a little detail with how the UART_ASYNC_API handles RX data (delays and timeouts). I have a feeling the RX pin is getting enabled too late as pressing a button has a longer "action window" than presenting a card. 
Please let me know if you need more detail, 
Thank you, 
Jack


  • Hello,

    Can you just go over once the description of receiving from the uart.h driver if some may apply in your case?
    https://github.com/nrfconnect/sdk-zephyr/blob/v3.7.99-ncs2/include/zephyr/drivers/uart.h#L163 

    For instance I want to check if it's possible you have a UART_RX_STOPPED condition due to:
    https://github.com/nrfconnect/sdk-zephyr/blob/v3.7.99-ncs2/include/zephyr/drivers/uart.h#L44 

    In such case you should for instance start to receive again, or handle it in some other way depending on what you want.

    Kenneth

  • Hi Kenneth, 

    Thank you for getting back to me. There are three scenarios that happen:

    First, TX data is sent and RX data comes back in full (roughly 45 bytes). 

    Second, TX data is sent and no data comes back UART_RX_RDY is not triggered. 

    Third, TX data is sent and partial data comes back UART_RX_RDY is triggered. 

    In all of these scenarios the UART_RX_STOPPED condition happens. Based on the RX timeout there are more or less of the UART_RX_STOPPED condition.  The optimal RX timeout (for this application) seems to be 1500 - 2500 ms. 

    I have a meeting with the manufacturer of the external device later this week. They might be able to give some clues as well. I am also going to test the interrupt API to see what findings i get there. 

    Thank you, 

    Jack

  • Try to find out what caused the UART_RX_STOPPED conditions by checking the uart_rx_stop_reason.

    I suspect that it's a mismatch in the baudrate and that is causing e.g. framing error. If that is the case, then I suspect the main cause may be that you have not started the external high frequency clock.

    But you can try to increase the buffers to see if that helps, and make sure you are double buffering by calling uart_rx_buf_rsp() while current buffer is being filled up, see existing examples on how to do this. From the link I shared it says for instance:

    * If uart_rx_buf_rsp is not called before current buffer
    * is filled up, receiving will stop.
    */
    UART_RX_BUF_REQUEST,

    Kenneth

  • Hi Kenneth, 

    Thank you for the details. I dug into the UART_RX_STOPPED condition and it looks like there are two errors. One being a UART_BREAK, and the second being a UART_ERROR_FRAMING. They are both present in a single RX event. 

    I turned on the HFCLK, but it looks like the issue is still present. I am guessing the serial break condition and the framing condition are closely tied. 

    There is an idle line delay (minimum 2 bytes) from the manufacture of the external keypad. Do you have any suggestions on dealing with the serial break condition? 

    Thank you, 

    Jack 

  • Hi Jack,

    I think it would help if you could toggle a pin on UART_RX_STOPPED, and at the same time perform a logic analyzer trace, so we can see the last 3-4bytes that triggered the issue when the pin toggles. I suspect that would help a lot to understand the issue.

    Can I assume you have used the samples/peripheral/lpuart example as guide here, and you for instance are 100% sure you are double buffering by providing a buffer every time on UART_RX_BUF_REQUEST event?

    Also it would be interesting to understand what buffer size and numbers of buffers you have provided, ref the lpuart example:

    #define BUF_SIZE 64
    static K_MEM_SLAB_DEFINE(uart_slab, BUF_SIZE, 3, 4); 

    I don't know the baudrate here or the amount of data, but if you have very high baudrate (e.g. 115200 or more) I would consider increasing BUF_SIZE  by 2x every time the baudrate doubles.

    I would expect the default value of 10000us for the timeout to be a good value.

    Kenneth

Related