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 Reply Children
  • 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!

  • I cannot express how grateful that this thread exists and I have stumbled on it.  We have a nrf52 design that interfaces with a nrf91.  We observed minor uart corruption at 115200 baud.  This was a red flag because I've done enough designs to know that at a trace length of 16mm for TX and RX, there should be ZERO uart corruption if both sides are implemented correctly.

    We spent 2+ weeks of debugging and refactoring asynchronous uart reception code on both the nrf52 and the nrf91.  We also spent serious resources debugging our PCB for potential noise issues being injected into the uart lines.  Nothing fruitful from those efforts.

    Finally today we realized that turning off BLE advertisements yielded significantly reduced uart corruption but we sill saw corruption at higher baud rates (which should be easily electrically supported).

    And today I found this gem of a thread and we are running at 1MBPS uart with megabytes of tested CRC32 checksum data with not a single bit error:

    CONFIG_SERIAL=y
    CONFIG_UART_ASYNC_API=y
    CONFIG_UART_0_NRF_HW_ASYNC=y
    CONFIG_UART_0_NRF_HW_ASYNC_TIMER=2

    Friendly feedback to Nordic: Pretty please make this concern front and center in the UART tutorial.  Or better yet, make hardware byte counting the default for all projects you can.  And where you can't assign the timer or PPI instance because they are used/unavailable, explicitly warn users data transfers over UART may be unreliable.

Related