UART is not working consistently

Hey,

I am in the process of testing the UART peripheral. Currently we are developing an application for which we need the nrf9160 and the nrf52840 chipset. We have decided to use UART communication between the two chips. However, after testing the UART on the nrf52840 DK and the nrf9160 DK, I have noticed some inconsistencies between the data sent and received.

I made a small test where I connected the RX and TX together. For this purpose I used the UART 1 peripehral. When I press button 1, an interrupt is generated which calls uart_tx() to send a trivial string from the TX to the RX. This calls the uart callback function in the code for the RX receive event and sends the data to the console (UART 0). After the first attempt, the entire message is sent to the console. However, after that, the message is only partially received on the console when I press button 1.

Below you can see a picture of the console and the graphical window of the logic analyzer:

I am always sending the same data. This can be seen in the on the left side of the snipped where the logic analyzer is. However, different chunk of the data is being shown in the serial terminal.

Why is this the case? 

I have added the whole project in the below zip file:

 6560.fund_less5_exer1_solution_1.zip

Basically, I took the example from the Nordic Academy and adapted it to my needs.

OS: Windows

SDK: 2.3.0-rc1

IDE: Visual Studio Code

Hardware: nRF52840 DK

  • Hi,

      

    1. your nrf9160dk_nrf9160_ns.overlay seems to switch TX and RX wrt. what is routed on the nRF9160-DK itself. TX=P0.01 and RX=P0.00 on the VCOM2 interface.

    2. You should add a pull-resistor to the button. As it is active low, a pull-up is recommended:

    ret = gpio_pin_configure_dt(&button, GPIO_INPUT | GPIO_PULL_UP);

     

    Is the issue only present in the "Serial terminal" or do you see similar issues with for instance realterm/putty/teraterm?

     

    PS: Ideally, you want interrupt functions to be short, with no blocking functions.

    A button handler is effectively a interrupt handler, and calling a function with no timeout can cause issues further down the development path.

      

    Kind regards,

    Håkon

  • ur nrf9160dk_nrf9160_ns.overlay seems to switch TX and RX wrt. what is routed on the nRF9160-DK itself. TX=P0.01 and RX=P0.00 on the VCOM2 interface.

    At the beginning I connect the RX of the nrf52840-DK to the TX of the nrf9160-DK and vice versa to make a roundtrip for a UART message to test it. I found that both UARTs behave the same strange behaviour as explained above. Afterwards, I used only one DK and connected the RX and TX together. I simplified my tests (the more devices involved, the more potential errors can occur).

    2. You should add a pull-resistor to the button. As it is active low, a pull-up is recommended:

    Yes, you are right, and that is a good point to have in the code. Luckily, I have not experienced any sporadic button interrupts.I was more concetrated on the UART communication then on the button handling configuration. I will update the code. Thanks!

    PS: Ideally, you want interrupt functions to be short, with no blocking functions.

    A button handler is effectively a interrupt handler, and calling a function with no timeout can cause issues further down the development path.

    In production code I probably wouldn't call a function in an interrupt handler, as you said this introduces a lot of problems (overhead of nested interrutps, code smells like tight-coupling)

    But for the quick and dirty prototyping approach that I will never use again afterwards, I will become a sinner. 

    Is the issue only present in the "Serial terminal" or do you see similar issues with for instance realterm/putty/teraterm?

    After some additional testing and playing around, I found out that the RX buffer is a ring buffer. This is probably the best approach to avoid buffer problems.

    However, I sometimes get extra zeros in the temp buffer, which can cause the log function to display only an empty message. (I copy the data from the RX buffer with the offset into the temp buffer, but still get zeros in it).

    In between the buffer elements I get some strange values, for example on the 10th element, like '('. This is something I don't quite understand. I checked if there is something wrong with the wires. The logic analyzer can read the signal clearly and it looks really good, like in the picture above. I don't think it's a hardware problem. Here is how I connected the nrf52840-DK (pretty simple):

    Is it possible to reset the write head of the ring buffer with the nrf function? When I read the message, I want the UART to write at the first element of the buffer and not where it ended at the last message.

    What would cause these strange values in the buffer?

  • Hi,

     

    Are you certain that you're receiving 25 bytes each time?

    You are not checking the received length (evt->data.rx.len)

     

    Kind regards,

    Håkon

  • Hi,

    Sorry for the late replay.

    I am sending 26 bytes/characters. I have updated my project where I show the length of the message and also the buffer can be updated with a button. If the message fits completely in the buffer then I have no side effects. If the buffer is slightly different size then the callback function gets some weird data. Below you can see a snapshot of nrf5240:

    I also tested it on the nrf9160 and it also had the same side effect:

    Here is the project:

    UART_test_2.zip

    What could be the issue here? I also tested it with Putty and I am getting the same results.

    Thanks for the help.

  • Hi,

     

    Could you try relaxing the define RECEIVE_TIMEOUT? Please note that this input is in microseconds, not milliseconds.

    Try to set it a bit higher, as the uart transmission itself takes approx. 8.7 us per bit transmitted.

     

    Kind regards,

    Håkon

Related