UART even parity error on nRF52832

Hey guys,

I just came up with an error I can't explain with my current zephyr knowledge and I really can't workaround because the other MCU isn't programmable and needs its requirements.

I tried to get a UART Transmission with even parity working on a nRF52832, but even if the config I write in the overlay file also is built into the zephyr.dts from the build folder, it doesn't seem to transfer the UART messages with an even parity afterwards (I'm using Async API as recommended in the DevAcademy chapter for UART communication).

The baudrate is easily changeable and is also changed on electrical level, but the parity doesn't seem to care of my configuration.

You can have a look at the following screenshot, where only with "Parity: None" the "Testbuffer!" print is readable.

Thank you in advance!

Best regards

Linus

Parents
  • Hi Linus,

    This was indeed interesting. I learned a couple of things when looking at this topic. I have used the echo_bot example to verify my findings.

    When you are testing this, are you testing with:

    1. The SEGGER J-Link Virtual COM (USB-CDC) that you get when you connect the development board through USB

    or:

    2. An external USB to TTL serial adapter and some pins on the MCU

    ?

    The reason why I am asking is that if you use alternative 1 it turns out that all settings are not forwarded. 

    Here I start miniterm without parity bit and it works as expected:

    $ python3 -m serial.tools.miniterm /dev/serial/by-id/usb-SEGGER_J-Link_000683653420-if00 115200
     *** Booting nRF Connect SDK v2.9.0-7787b2649840 ***
     *** Using Zephyr OS v3.7.99-1f8f3dc29142 ***
    Hello! I'm your echo bot.
    Tell me something and press enter:

    But. If we start miniterm with parity set to Even we expect garbage. But it turns out that we get the same result:

    $ python3 -m serial.tools.miniterm /dev/serial/by-id/usb-SEGGER_J-Link_000683653420-if00 115200 --parity E
     *** Booting nRF Connect SDK v2.9.0-7787b2649840 ***
     *** Using Zephyr OS v3.7.99-1f8f3dc29142 ***
    Hello! I'm your echo bot.
    Tell me something and press enter:

    If we change the echo_bot firmware to use a different baud rate we do get garbage which is expected.

    But, if we change the parity bit configuration in the firmware we still does not get any garbage! That is not expected. This is perhaps what you have observed as well.

    Now, let us connect an external USB to TTL serial adapter instead. On my nRF52840-DK I used the following overlay file (inspired by some other Zephyr example and this link: https://docs.zephyrproject.org/latest/boards/nordic/nrf52840dk/doc/index.html)

    /*
     * Copyright (c) 2023 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    / {
    	chosen {
    		zephyr_shell_uart = &uart1;
    	};
    };
    
    &pinctrl {
       uart1_default_alt: uart1_default_alt {
          group1 {
             psels = <NRF_PSEL(UART_TX, 0, 14)>,
                     <NRF_PSEL(UART_RX, 0, 16)>;
          };
       };
       /* required if CONFIG_PM_DEVICE=y */
       uart1_sleep_alt: uart1_sleep_alt {
          group1 {
             psels = <NRF_PSEL(UART_TX, 0, 14)>,
                     <NRF_PSEL(UART_RX, 0, 16)>;
             low-power-enable;
          };
       };
    };
    
    &uart1 {
      pinctrl-0 = <&uart1_default_alt>;
      /* if sleep state is not used, use /delete-property/ pinctrl-1; and
       * skip the "sleep" entry.
       */
      pinctrl-1 = <&uart1_sleep_alt>;
      pinctrl-names = "default", "sleep";
      status = "okay";
      parity = "even";
    };
    

    I connect my USB to TTL serial adapter to pins 0.14 and 0.16. I run miniterm again, setting the parity to Even:

    # python3 -m serial.tools.miniterm /dev/serial/by-id/usb-Prolific_Technology_Inc._USB-Serial_Controller-if00-port0 115200 --parity E
    
    ␀HY��!J�mʽu.*�h␋␒�t�
    U�lj� ���t+�g
    �d��e��e��r�H

    Now. I get a bit frustrated. I look around a bit in the source code, especially the file `zephyr/drivers/serial/uart_nrfx_uarte.c`. In that file we can see a very relevant configuration parameter named `CONFIG_UART_##idx##_NRF_PARITY_BIT`.

    So, by adding the following to my `prj.conf` file:

    CONFIG_UART_1_NRF_PARITY_BIT=y

    And trying again with parity set to Even when launching miniterm:

    $ python3 -m serial.tools.miniterm /dev/serial/by-id/usb-Prolific_Technology_Inc._USB-Serial_Controller-if00-port0 115200 --parity E
    Hello! I'm your echo bot.
    Tell me something and press enter:
    

    Success!

    I hope this helps you in making progress on your project. Good luck!

  • Hello again.

    I am afraid my last post may lead to some confusion. However. The key takeaways are:

    1. You cannot trust how the USB to serial converters handle the missing or wrong parity bits. I got some garbage at some point, but I might have been lucky or unlucky, depending on how you see it.

    2. You need to set the CONFIG_UART_x_NRF_PARITY_BIT to Y, where x is the UART# you want to enable parity bits for.

    As  pointed out, the best is to use a Logic Analyzer.

    Signal D0 is attached to the P0.6 pin which UART0 is configured to use as TX on my board.

    With CONFIG_UART_0_NRF_PARITY_BIT=n the initial output ("Echo") from the echo_bot example looks like this:

    CONFIG_UART_0_NRF_PARITY_BIT=n

    By setting CONFIG_UART_0_NRF_PARITY_BIT=y we can see the parity bit:

    parity="even", CONFIG_UART_0_NRF_PARITY_BIT=y, decoder is not expecting parity bits

    The decoder reports frame errors because the stop bits are not as expected. However, if we choose to ignore that, we can still actually read the data. This is probably what many USB to serial adapters do.

    By telling the decoder that there is a parity bit, it gets happier:

    parity="even", CONFIG_UART_0_NRF_PARITY_BIT=y, decoder correctly configured

    It seems that it does not matter what I set the parity setting to in the overlay file. It seems like Even parity is used for transmission when CONFIG_UART_0_NRF_PARITY_BIT=y and no parity bit is transmitted otherwise.

Reply
  • Hello again.

    I am afraid my last post may lead to some confusion. However. The key takeaways are:

    1. You cannot trust how the USB to serial converters handle the missing or wrong parity bits. I got some garbage at some point, but I might have been lucky or unlucky, depending on how you see it.

    2. You need to set the CONFIG_UART_x_NRF_PARITY_BIT to Y, where x is the UART# you want to enable parity bits for.

    As  pointed out, the best is to use a Logic Analyzer.

    Signal D0 is attached to the P0.6 pin which UART0 is configured to use as TX on my board.

    With CONFIG_UART_0_NRF_PARITY_BIT=n the initial output ("Echo") from the echo_bot example looks like this:

    CONFIG_UART_0_NRF_PARITY_BIT=n

    By setting CONFIG_UART_0_NRF_PARITY_BIT=y we can see the parity bit:

    parity="even", CONFIG_UART_0_NRF_PARITY_BIT=y, decoder is not expecting parity bits

    The decoder reports frame errors because the stop bits are not as expected. However, if we choose to ignore that, we can still actually read the data. This is probably what many USB to serial adapters do.

    By telling the decoder that there is a parity bit, it gets happier:

    parity="even", CONFIG_UART_0_NRF_PARITY_BIT=y, decoder correctly configured

    It seems that it does not matter what I set the parity setting to in the overlay file. It seems like Even parity is used for transmission when CONFIG_UART_0_NRF_PARITY_BIT=y and no parity bit is transmitted otherwise.

Children
No Data
Related