Dynamically change devicetree configuration for UART in firmware

Hi,

In the nRF Connect SDK, is it possible to dynamically change devicetree overlay configurations in firmware?

Say for example, UART1 is defined in the devicetree overlay as:

&uart1 {
    compatible = "nordic,nrf-uarte";
    status = "okay";
    current-speed = <115200>;
    pinctrl-0 = <&uart1_default>;
    pinctrl-1 = <&uart1_sleep>;
    pinctrl-names = "default", "sleep";
};

Would it be possible to change the baud rate and pin configuration in my firmware application code?
Thanks in advance.
  • Hello Martaer,

    My name is Ted.  Your post catches my eye as I've had need over the past year to build a Zephyr based app which can adjust UART baud rates at run time.  I've worked with Zephyr and its device tree elements for a couple of years, so yet something of a newcomer to this paradigm.  The answer to your question from all I have learned so far is:  not possible to make device tree source act dynamically.

    This is not an nRF Connect SDK specific reality.  This limitation comes from device tree source (DTS) being compiled by `dtc`, and further by Zephyr's complex device tree macro system.  These build steps produce some intermediate files some of which are further processed by gcc in its build steps.

    While I haven't yet gotten a run time baud adjusting sample app working, the direction I am going is two fold:

    (1)  I am reading the datasheet for my target MCU, a member of NXP LPC family,

    (2)  I am reviewing Zephyr / NXP hardware abstraction level sources related to Zephyr's UART API.

    At this time I believe I can extend the existing driver with code that updates one or more registers of the UART at run time.  I won't be modifying Zephyr or NXP sources directly.  I'll technically be writing a part of my app to act as an extension to the Zephyr driver.

    I'll need to take care that my extension plays well with the hardware, and with Zephyr's API.

    I think one place I may need to adjust at run time are registers which control clock source division.  I recall from older projects that setting baud rates involves configuring clock sources and clock dividers.  MCUXpresso has a wizard to help with this for NXP family parts.  You may be using another family or class of MCU.

    There may well be some additional run time UART register touching to do.  It may not be practical or electrically sensible to change just the clock, without first pausing or disabling some other aspect of the on-chip UART.  This is among the details I am searching for in datasheets and forums.

    Sorry I do not have a ready solution to share!

    I'll bookmark your post so I may see what further answers you receive.  I may learn something to help in the related work I'm interested to achieve.

    - Ted

  • Hello,

    If you only wanted to change the pins, you could add another pinctrl instance, e.g.:

    pinctrl-2 = <&uart_default_2>;

    and define that as you like, and switch between the two different pinctrl instances during runtime, pretty much like it already does when it goes from active (default) to sleep. However, you see that the baudrate is not defined in pinctrl. It is defined in the uart instance itself. So therefore it is not possible to change between different baudrates during runtime while using devicetree. 

    If you specifically need to change between different baudrates on the same UART instance, I suggest you check out the nrfx driver for UART. This is a driver that interacts more directly with the UART registers, and not through the zephyr API. So there you are free to change baudrates and GPIOs as you like. 

    Please see my colleague, Jørgen's, reply in this ticket:

     NRF5340 - Reprogram UART baudrate at runtime 

    Best regards,

    Edvin

Related