nRF52840 UARTE in Zephyr

I'm having problems using the UARTE in the nRF52840 via Zephyr.    I'm watching the TX pin using a logic analyzer and seeing correct data when running at 9600 baud.   But if I configure the UART for 115200 baud, the data is garbled (sometimes some later characters are correct).   I've tried using the "built-in" Zephyr UART driver and disabling it and using the nrfxlib uarte driver with the same results.

I suspect that there is a clock accuracy issue...

I set:

CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=n
CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y

in prj.conf since my board has a 32.768 KHz crystal.     Is there some other configuration option needed to use the UARTE at 115200 baud?

Thanks!

  • Hi,

     

    I'm watching the TX pin using a logic analyzer and seeing correct data when running at 9600 baud.   But if I configure the UART for 115200 baud, the data is garbled (sometimes some later characters are correct).   I've tried using the "built-in" Zephyr UART driver and disabling it and using the nrfxlib uarte driver with the same results.

    Your current configuration sets the LFCLK, while the UART's tolerance comes from the HFCLK.

    If you are running with the internal 64M RC oscillator, it is quite inaccurate (in the percent area). You can request the HFXO using this sequence:

    https://github.com/nrfconnect/sdk-nrf/blob/v1.7.0/samples/bluetooth/direct_test_mode/src/dtm.c#L497-L527

     

    Kind regards,

    Håkon

  • Hi,

    Thanks for your response.

    I tried using the clock_init() function you highlighted in the link you provided.     It did not solve the problem I am seeing (logic analyzer (using async analyzer/decoder) sees correct output sequence when UART is set to 9600 (via .dts file setting), but characters are wrong when the .dts file is changed to 115200).

    err is reported as 0 (I assume that means everything is OK).

    Would I be better off using the nrfx uarte driver from nrfxlib (versus the Zephyr built-in UART driver)?   Or are they the same?

    Is there anything else that could be happening here?

    I see in case ID 205318, a comment that turning on BLE might automatically switch the HFCLK to the internal oscillator to save power, and that a call to sd_clock_hfclk_request() is needed to ensure the HFCLK is kept with the crystal.   Is this also true when using BLE in Zephyr?   If so, is there an equivalent call in the Zephyr BLE API (the bt_ functions vs. the sd_ functions)?

    Thanks!

  • Hi,

     

    CktDesigner said:
    Would I be better off using the nrfx uarte driver from nrfxlib (versus the Zephyr built-in UART driver)?   Or are they the same?

    The zephyr built-in driver is built on nrfx, so they're quite similar in what's underneath.

    CktDesigner said:
    I see in case ID 205318, a comment that turning on BLE might automatically switch the HFCLK to the internal oscillator to save power, and that a call to sd_clock_hfclk_request() is needed to ensure the HFCLK is kept with the crystal.   Is this also true when using BLE in Zephyr?   If so, is there an equivalent call in the Zephyr BLE API (the bt_ functions vs. the sd_ functions)?

    If you are using the softdevice controller (default for all bluetooth samples in NCS), you should use this function call to request the HFCLK:

    https://github.com/nrfconnect/sdk-nrfxlib/blob/v1.7.0/mpsl/include/mpsl_clock.h#L136

     

    For all other subsystems in zephyr (including the zephyr bluetooth link layer), the former clock_control function will work.

    CktDesigner said:
    Is there anything else that could be happening here?

    Could you show an example of the expected vs. corrupted output? Are you using a nRF5 DK or a external uart bridge?

     

    Kind regards,

    Håkon 

  • I'm using a custom board with a Laird BL654PA module.  The Laird module includes the main crystal and I have a 32.768 KHz crystal on the board (since it states in the spec that BLE works better using the crystal).

    So if I use the clock_init() function you suggested, do I still need the mpsl_clock_hfclk_request() function to keep the HFCLK on (when using BLE)?   

    I also tried "not enabling" BLE (but using the clock_init() function you provided), thinking that perhaps BLE was somehow disabling the XO version of HFCLK, just to see if that made a difference, but got the same results.

    Here is the expected waveform from my test (just a sequence of characters) when:

    current-speed = <9600>;

    is in the board's .dts file

    Using the same code, but recompiling with:

    current-speed = <115200>;

    in the board's .dts file, I get this output:

    Note that the overall shape of the two waves is very similar.   The beginning (first character) of the 115200 baud version looks a bit corrupted, which then (I'm guessing) shifts all of the other characters out, causing framing errors or bad decoding.

    By zooming in appropriately and lining up the two waveforms, it appears that the 115200 baud version doesn't start properly.    Could this be a problem with the UART or the clock?   After the first couple of characters, the waves track each other pretty closely, but since everything gets shifted the decoding fails.   Here is the beginning of the two waves, zoomed and lined up:

    Still trying to figure out what is happening...

    Thanks!

  • Hi,

     

    As the waveform has jittering, the parser is parsing at the incorrect edge.

    Q1: is this scope taken from reset state?

    Q2: Do you see the same issue if you connect a receiver on the other end?

     

    Kind regards,

    Håkon

Related