Framing error and noisy data when using UARTE at high baud rate

Hello, in my zephyr application, I have uart1 configured as receive only using uarte at 921600 baud rate. Below is the description node:

&uart1 {
	compatible = "nordic,nrf-uarte";
	label = "data_uart";
	current-speed = <921600>;
	status = "okay";
	rx-pin = <30>;
};
 

I have a device sending a uart packet every 50ms and although I can see the right number of bytes being received, the data itself is corrupted (some bytes are correct but some are not) and I get a framing error thrown by the IRQ for every packet. I scoped the signal and it is very clean. I have also connected a terminal software (minicom) and I was able to receive the expected data while nrf52833 cannot. I do have another uart running on the same SoC (uart0) and that one is working fine but it is running at 115200 baud rate. I am not sure if I have to do anything special due to the high baud rate. I thought the DMA should help and I have allocated a timer for the byte processing. Here are my config statements:

#uart
CONFIG_SERIAL=y
CONFIG_UART_ASYNC_API=y
CONFIG_UART_0_ASYNC=y
CONFIG_UART_0_NRF_HW_ASYNC=y
CONFIG_UART_0_NRF_HW_ASYNC_TIMER=2
CONFIG_UART_0_NRF_ASYNC_LOW_POWER=y
CONFIG_UART_1_ASYNC=y
CONFIG_UART_1_NRF_HW_ASYNC=y
CONFIG_UART_1_NRF_HW_ASYNC_TIMER=4
CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y 
CONFIG_CLOCK_CONTROL_NRF_K32SRC_20PPM=y

I thought maybe it is a clock issue but my understanding is the system automatically enables the HFCLK. The datasheet mentions a note about the pin drive strength for high baud rate but since I am not transmitting, I don't think this is related to my case. Please let me know if I am missing anything. Thank you.

Parents
  • which file are you referring to? I found UARTE_BAUDRATE_BAUDRATE_Baud921600 in nrf_uarte.h located in modules/hal/nordic/nrfx/hal but I can't find the file that defines it. Also, how did you calculate the new value?

    Finally, I was able to solve the problem by enabling HFXO without changing any register values. Do you still think it is related to this definition value?

  • I wouldn't bother; the original post said the HFCLK was running but if HFCLK was not running that has a much greater effect.

    I posted the link to my detailed code to calculate baud rate register values in my first answer. baud-rate-generator

  • I actually didn't know it is needed but now I know. An issue has been created to update the zypher UART driver to enable HFXO automatically when needed. 

    However, I am just wondering if I need to do any extra calculations and update the base register like you did. I will look into and see if that is needed. 

  • Take care in turning off the HFCLK as if not correctly handled it can consume significant power when sleeping for long periods; not an issue if there is plenty of power available, but a coin cell killer. This is covered in multiple posts over the years.

  • Just for completeness, I check datasheet v1.7 for nRF52832 and get the following (Edit - updated % errors on both quoted and calculated baud rates, needs review):

    //  ---------------Documentation---------------  --------Calculated----------
    //  Register    Required   Actual  Error   Ok?   Register      Actual Error
    //  =========== ======== ======== =======  ====  =========== ======== =======
    //  0x0004F000,    1200,    1205, +0.416%,   -,  0x0004F000,    1205, +0.416%
    //  0x0009D000,    2400,    2396, -0.166%,   -,  0x0009D000,    2395, -0.208%
    //  0x0013B000,    4800,    4808, +0.166%,   -,  0x0013B000,    4806, +0.125%
    //  0x00275000,    9600,    9598, -0.020%,   -,  0x00275000,    9597, -0.031%
    //  0x003AF000,   14400,   14401, +0.006%,  No,  0x003B0000,   14404, +0.027%
    //  0x004EA000,   19200,   19208, +0.041%,   -,  0x004EA000,   19195, -0.026%
    //  0x0075C000,   28800,   28777, -0.079%,  No,  0x0075F000,   28793, -0.024%
    //  0x009D0000,   38400,   38369, -0.080%,  No,  0x009D5000,   38406, +0.015%
    //  0x00EB0000,   57600,   57554, -0.079%,  No,  0x00EBF000,   57601, +0.001%
    //  0x013A9000,   76800,   76923, +0.160%,   -,  0x013A9000,   76797, -0.003%
    //  0x01D60000,  115200,  115108, -0.079%,  No,  0x01D7E000,  115203, +0.002%
    //  0x03B00000,  230400,  231884, +0.644%,  No,  0x03AFC000,  230407, +0.003%
    //  0x04000000,  250000,  250000, +0.000%,   -,  0x04000000,  250000,       -
    //  0x07400000,  460800,  457143, -0.793%,  No,  0x075F7000,  460800, +0.000%
    //  0x0F000000,  921600,  941176, +2.124%,  No,  0x0EBEE000,  921600, +0.000%
    //  0x10000000, 1000000, 1000000, +0.000%,   -,  0x10000000, 1000000,       -
    

  • Actually I would bother; 921,600 baud has a 2.124% error using the incorrect value quoted in the data sheet and the SDK code, assuming my calculations are correct. +-2% is as far out as a asynchronous serial port should be allowed to get. Depending on whether the UART uses 3- or 16-sample voting to determine whether a bit is '0' or '1' and the slope of the initial start bit falling edge and any externally introduced noise on that edge means start bit timing determination could be 10% or more off; the next start bit 10 bits later adds 10x2.124=21% to this error (now 31%) before the relative (ie different) clock accuracy at both ends of the link is considered. Assuming 10-bit Tx (send full stop bit) and 9.5-bit Rx (receive half stop bit) that's a risky error as 50% total of all errors is the threshold where framing errors will occur.

    Edit: well this is a surprise, the UART actually works at all baud rates up until 7.999Mbaud on transmit; receive only works up to 1MBaud however, as receive depend on the number of samples used (16 typically) although this is not quoted.

    //  --------Calculated-------------------  ---------------Documentation---------------
    //  Required Register      Actual   Error  Register    Required   Actual  Error   Ok?
    //  ======== =========== ======== =======  =========== ======== ======== =======  ====
    //     1200, 0x0004F000,    1205, +0.416%  0x0004F000,    1200,    1205, +0.416%,   -,
    //     2400, 0x0009D000,    2395, -0.208%  0x0009D000,    2400,    2396, -0.166%,   -,
    //     4800, 0x0013B000,    4806, +0.125%  0x0013B000,    4800,    4808, +0.166%,   -,
    //     9600, 0x00275000,    9597, -0.031%  0x00275000,    9600,    9598, -0.020%,   -,
    //    14400, 0x003B0000,   14404, +0.027%  0x003AF000,   14400,   14401, +0.006%,  No,
    //    19200, 0x004EA000,   19195, -0.026%  0x004EA000,   19200,   19208, +0.041%,   -,
    //    28800, 0x0075F000,   28793, -0.024%  0x0075C000,   28800,   28777, -0.079%,  No,
    //    38400, 0x009D5000,   38406, +0.015%  0x009D0000,   38400,   38369, -0.080%,  No,
    //    57600, 0x00EBF000,   57601, +0.001%  0x00EB0000,   57600,   57554, -0.079%,  No,
    //    76800, 0x013A9000,   76797, -0.003%  0x013A9000,   76800,   76923, +0.160%,   -,
    //   115200, 0x01D7E000,  115203, +0.002%  0x01D60000,  115200,  115108, -0.079%,  No,
    //   230400, 0x03AFC000,  230407, +0.003%  0x03B00000,  230400,  231884, +0.644%,  No,
    //   250000, 0x04000000,  250000,       -  0x04000000,  250000,  250000, +0.000%,   -,
    //   460800, 0x075F7000,  460800, +0.000%  0x07400000,  460800,  457143, -0.793%,  No,
    //   921600, 0x0EBEE000,  921600, +0.000%  0x0F000000,  921600,  941176, +2.124%,  No,
    //  1000000, 0x10000000, 1000000,       -  0x10000000, 1000000, 1000000, +0.000%,   -,
    //  2000000, 0x20000000, 2000000, +0.000%           -,       -,       -,       -,   -,
    //  4000000, 0x40000000, 4000000, +0.000%           -,       -,       -,       -,   -,
    //  7999000, 0x7FFBE000, 7998992,       -           -,       -,       -,       -,   -,
    

  • Well this is a surprise, the UART actually works at all baud rates up until 7.999Mbaud on transmit; receive only works up to 1MBaud however, as receive depend on the number of samples used (16 typically) although this is not quoted. I posted the full table in the edit above, but added this comment as otherwise it gets lost.

    Recap on original post: 921,600 baud has a 2.124% error using the incorrect value quoted in the data sheet and the SDK code, assuming my calculations are correct. +-2% is as far out as a asynchronous serial port should be allowed to get. Depending on whether the UART uses 3- or 16-sample voting to determine whether a bit is '0' or '1' and the slope of the initial start bit falling edge and any externally introduced noise on that edge means start bit timing determination could be 10% or more off; the next start bit 10 bits later adds 10x2.124=21% to this error (now 31%) before the relative (ie different) clock accuracy at both ends of the link is considered. Assuming 10-bit Tx (send full stop bit) and 9.5-bit Rx (receive half stop bit) that's a risky error as 50% total of all errors is the threshold where framing errors will occur.

Reply
  • Well this is a surprise, the UART actually works at all baud rates up until 7.999Mbaud on transmit; receive only works up to 1MBaud however, as receive depend on the number of samples used (16 typically) although this is not quoted. I posted the full table in the edit above, but added this comment as otherwise it gets lost.

    Recap on original post: 921,600 baud has a 2.124% error using the incorrect value quoted in the data sheet and the SDK code, assuming my calculations are correct. +-2% is as far out as a asynchronous serial port should be allowed to get. Depending on whether the UART uses 3- or 16-sample voting to determine whether a bit is '0' or '1' and the slope of the initial start bit falling edge and any externally introduced noise on that edge means start bit timing determination could be 10% or more off; the next start bit 10 bits later adds 10x2.124=21% to this error (now 31%) before the relative (ie different) clock accuracy at both ends of the link is considered. Assuming 10-bit Tx (send full stop bit) and 9.5-bit Rx (receive half stop bit) that's a risky error as 50% total of all errors is the threshold where framing errors will occur.

Children
No Data
Related