Uart: wrong offset after buffer overflow

Hi, hello_world_UART_rx_test.zip

I am trying to use the UART on my nRF9160DK board.

In my program I have 2 uarts in use. uart0 is used for printk output and uart1 is used to receive data in async mode.

I have both connected to the vcom ports on the dev kit (the "usb" port) and have 2 instances of tera term open on windows; one for the printk output, one for the chars i want to send.

Now the problem:

when sending single chars, everything is ok, but if I send a sequence of chars, that would overflow the buffer i have given the uart_rx_enable() or the uart_rx_buf_rsp() function ( eg pasting "abcdef" into the "uart1" terminal when there are already a few bytes in the buffer), I get the free and the request buffer events. after that, I get another rx event.

lets say the buffer is pretty full and I send "abcdef". Then "abc" still fits into the first buffer, I get the rx event for 3 bytes of data. everything ok. free event and request buffer event follow, new buffer is given. Then I immediately get the rx event with the new buffer. in the new buffer is "def", and I get offset=0 (which is ok), but len=1 (which is NOT ok) from the evt parameter in the callback function -> I am not getting notified for the 'e' and 'f' !!
When I send a single new char now, it gets placed after the "def", so on an offset of 3, but in the evt parameter it says offset of 1 (because it ignored the 'e' and 'f' before).

I am surely using the functionality wrong. please take a look at the attached FW, because can't figure out what I am doing wrong from documentation alone.

Thank you!

Parents
  • Hello, 

    I will have a look at the provided project. What version of the nRF Connect SDK are you running? 

    Kind regards,

    Øyvind

  • Hi,
    thank you for looking over it.

    I am using SDK 1.8.0

    Edit: I have just tested my sample program and it shows the same behaviour with SDK 1.9.0

  • I think that the issue is with driver configuration and rx byte counting. By default software tries to count bytes but it fails when interrupt is not handled on time. That results in missing rx events (eventually you will get event on the buffer boundary). Alternative is to use hw byte counting but that requires kconfig setup and dedicating one TIMER peripheral instance like in the example below where TIMER2 is used for that:

    CONFIG_UART_1_NRF_HW_ASYNC=y
    CONFIG_UART_1_NRF_HW_ASYNC_TIMER=2

    github.com/.../nrf9160dk_nrf9160.conf

  • Hello, sorry for the late answer.

    This seems to indeed have fixed the issue of the wrong offset, thank you a TON! Unfortunately I have discovered another issue, which might be known/intended/tolerated, but it sure isn't intuitive for me.

    The Uart async driver has DMA buffers, which are to be provided. if you fill up both those buffers at once, the FW just hard faults. I again have made a video and linked a FW. please also look into this.



    hello_world_UART_rx_test_2.zip

    PS: note for the video: I have 32 byte for the example where I paste the numbers. it obviously also crashes when you use more than that. you dont have to fill them up exactly. Please try it out with divfferent lengths, to find strange behaviour.

  • The second issue (which I cannot edit the reply of for some reason), I tested with NCS 1.8.0.

    The hard fault seems to be gone in 1.9.1, but some strange behaviour still persists.

    Here I alternated pasting lower and upper case alphabet, so beginning with

    abcdefghijklmnopqrstuvwxyz then ABCDEFGHIJKLMNOPQRSTUVWXYZ then lower case again, until the uart stopped with seemingly no error.
    As you can well see, thedata that is (seemingly) received is not in line with what I sent to the uart1.
    As I said, I encourage you to experiment eith this as well. If I should open another issue for this, please tell me so and I will.
  • So hardfault is gone on 1.9.1? That's good.

    Regarding unexpected behavior with data being overwritten. It is a feature not a bug. There is a DMA linking setup between the buffers, meaning that ENDRX event triggers STARTRX. This works well as long as you handle next buffer request before current transfer ends.

    So basically, to have reliable reception you must provide new buffer on time. By increasing buffer size you increase that accepted latency. Unfortunately, there is no means in the driver to detect that you didn't provide the buffer on time. In your case, you see this issue because you are printk from that interrupt handler which blocks interrupt for significant amount of time. If you would store somewhere info and print it from thread context issue would go away.

  • Hello,
    Well, spending too much time in the interrupt handler was very much a rookie mistake on my part. Good to know though, that "excess data" doesn't just get lost, but overwrites existing data by design, in case the new buffer does not get given on time. Definitely something to keep in mind.

    Of course I adjusted my test FW and it now works fine. 

    Thank you all so much!

Reply Children
No Data
Related