Dynamic Pin Control/Changing Functionality in runtime

Hello, 

I recently noticed that I may have an issue with our current design of PCB and firmware. We basically have created a datalogger using the nRF9160, and we take readings for a variety of sensors. One such thing that we have yet to add into firmware, is the ability to read Modbus sensors (RS485), which would need a UART port. 

I am not sure I have ever fully understood the devicetree, so bare with me....

We currently have in use - (Enabled in Overlay file)

I2C0

SPI1

I2C2

UART3

So I don't know how we are going to add a further UART Port. 

Is it possible to disable say I2C0, and enable UART0 in runtime? 

Alternatively, is it possible to dynamically change the pins of UART3 to go to another set of UART pins in runtime?

On the latter I have found this remap function but it runs in PRE_KERNEL_1 sdk-zephyr/samples/boards/nordic/dynamic_pinctrl/src/remap.c at main · nrfconnect/sdk-zephyr

Can this be modified to work without rebooting the firmware? 

I am guessing either of these would be possible, maybe without using the Devicetree, but I cant find any specific reference document. 

Thanks, 

Damien

Parents Reply Children
  • Surely at the low level it would be possible. It's fairly standard on microcontrollers to init and deinit peripherals in runtime. I am guessing the limitation is coming from Zephyr rather than the nRF9160?

  • Hello,

    From a hardware perspective the only real limitation is what is described here:
    https://docs.nordicsemi.com/bundle/ps_nrf9160/page/peripheral_interface.html#ariaid-title3  

    However the zephyr drivers do not really support this at all, they rely on static configuration compile time or early init. Only exception is if you were working at a low level driver, then you could for instance use the low level nrfx drivers to do pretty much do whatever you want, e.g. change between interfaces and pins for the same hardware ID instance. However the higher level sensor and serial drivers in zephyr do not support this in any way. 

    I assume you are not able to do any changes to the hardware? Because if you were able to put both i2c sensors on the same i2c interface, then that would actually work well in zephyr, because the i2c interface is by design built in such a way that if two sensors try to use (read or write to) the i2c interface at the same time, then one would simply be delayed until the other is finished, however that is really the only interface that can do this.

    If you are not able to change the hardware, then that limit the number of options here. There is a i2c_gpio (i2c_bitbang) implementation in zephyr, so that might potentially free up one of the i2c hardware instances, but bit-banging i2c will be less efficient and need to be tested in case the sensor have some hard requirements to how low speed the clock can in corner cases be (don't think it's a problem, but it must be tested).

    Kenneth

  • Yea that would be the most ideal way, but we do have to support older hardware devices that have been made in that way. I cannot remember the exact reason for having two I2C ports in the first place, but I have to work with it. 
    Seems like disabling the Zephyr UART3, and writing my own UART driver with nrfx that will deinit, and init with different pins is the way to go.

  • DamoL said:
    Seems like disabling the Zephyr UART3, and writing my own UART driver with nrfx that will deinit, and init with different pins is the way to go.

    Sounds like a good plan.

    As long as you have full control of when the UART3 is used, you may find this useful also (think this may still work in recent ncs versions):
    https://devzone.nordicsemi.com/f/nordic-q-a/107317/configuring-uart1-using-pinctrl-for-two-uarts/463996  

    Alternatively, you can use the nrfx drivers directly. An example on how to do this is shown in:
    v3.2.1\modules\hal\nordic\nrfx\samples\src\nrfx_uarte

    Hope that helps,
    Kenneth

  • Thanks Kenneth, that's very useful.

    I am a little confused at this first option though, looking at the code provided, it seems it is using zephyr UART0, and changing the pins, with PM_DEVICE_ACTION_SUSPEND / RESUME

    However, according to the documentation this should only be used before the device is initialized,

    Surely this violates what the documentation says though?

    Thanks, 

    Damien

Related