Delay UART initialization in Zephyr

For my application I need the UART TX/RX pins pulled low until I am ready to turn on the UART.  Is there a method in Zephyr to do this?  
Currently when Zephyr starts it reads the device tree configuration and initializes the UART driver before main, which then places pull up on the TX/RX pin.  How can I manually control when the UART initialization occurs in my code? 

Parents
  • Hi,

    You could always use gpio_pin_configure_dt() to configure GPIOs during runtime when the time is right, or any other uart-specific functions from the UART API that suits your applications needs.

    Is this sufficient for you or do you want to do the full initialization when you see fit?

    Kind regards,
    Andreas

  • That will not work as that on power up the TX pin goes high which is not allowed.   The TX pin must stay low (or tristated) until we are ready, for personnel safety reasons.    

    If we try to turn pin over to GPIO in main() then what happens is on power up TX goes high, main then drives low.  Additionally in the datasheet it says the UART must be disabled before you change pins to GPIO. 

    I did try using the pinctrl and power manager to disable the UART and then set a pinctrl state for sleep with TX/RX pulled low.  When I put the peripheral in the sleep mode the RX pin does go low, but the TX remains high.  I did not go and debug the UARTE driver to figure out what is wrong, but it did not work as expected.  Also this still has issue of the TX pin going high before main() where we would sleep peripheral.  

    I have posted on the Zephyr forum and this delayed initialization with devicetrees is a feature in the bleeding edge of Zephyr but not in the version we have. 
    Other suggestions I have received is to add hardware to make sure pins are disconnected.  This would work but adding hardware to work around Zephyr is a bit insane and costly.  

    I have been trying to figure out if the driver can be setup and initialized outside of the devicetree.  I personally do not like devicetrees as they are too complex and rigid and the macro foo is insane.  Thus I would greatly prefer a solution which removes device trees and gives the developers back control over the initialization process.   Yes I do know that devicetrees is part of the koolaid that you drink when you join the Zephyr cult, and I will have to adapt or change careers. 

  • Zephyr might be tasty when it work, however what are the recovery options when it fails?

    I have thought about this UART issue, an went through several ideas discussing with anyone who will listen, not many by the way.  The best solution I can come up with at the moment is making an out of tree driver by copying nordic's uarte driver from zephyr and then renaming to something like 'myuarte'.  Then in this custom driver make it work the way I need it to and add to my project. 

    This is not the best option but might be good enough to move forward, while we wait for  Zephyr to grow up and mature.

  • trampas said:
    The best solution I can come up with at the moment is making an out of tree driver by copying nordic's uarte driver from zephyr and then renaming to something like 'myuarte'

    This is within what I have thought as well. I were playing around with trying to use an overlay to modify the existing UART device binding, i.e setting it up but not initializing before I call the initialization of the device but I can't quite get it to do this. Maybe the missing ingredient is to do what you say, i.e copy the existing device and creating your own custom variant of the UART that allows for this.

    Even though it's a bit clunky it is also one of the good features with Zephyr i.e allowing for relatively standardized customization of devices and nodes.

    I won't be able to look further into creating a sample for this for a while, but I am fairly confident that your suggestion will work

    Kind regards,
    Andreas

  • A second idea is to have a config option which removes all the initialization calls.  Then have a means for me to call all the initialization first thing in main.   Then I can not initialize the UART driver. 

    The basic idea would be to make the 

    z_sys_init_run_level(enum init_level level)
    a weak function.  Then in my project source code I could redefine this function and control everything. 
  • Hi,

    I've discussed this topic some more with my colleagues and I've concluded that I'm gonna loop back to my first suggestion, i.e to use the overlay or dts to modify the UART instance to have pull-down until you need to configure it differently using gpio_pin_configure_dt().

    https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/config_and_build/configuring_app/hardware/pin_control.html#pin-control-in-nrf suggests this option atleast, i.e to use different groups for different modes. Create one pinctrl node with pullup and one with bias-disable and then change between these.

    I've not tested this with hardware and verified that it will comply with the spec you're describing, but it's another suggestion that you can investigate if you wish.

    Kind regards,
    Andreas

  • Unless I misunderstand the suggestion there will be a period of time after the UART is initialized by Zephyr where the pins are high, before the  call to gpio_pin_configure_dt().  Can you please explain how this solution works around this issue? 

Reply Children
  • trampas said:
    Unless I misunderstand the suggestion there will be a period of time after the UART is initialized by Zephyr where the pins are high, before the  call to gpio_pin_configure_dt().

    They should be sett do pull-down when being initialized when setting this up in the overlay. But this is exactly what we would need to verify by monitoring the relevant GPIOs. Do you have a Power Profiling Kit or any other tool to measure the current available?

    Kind regards,
    Andreas

Related