This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Change I2C peripheral drive strength

Hi,

I noticed that the nRF9160s I2C low level logic voltage is quite high. With a 2kR resistor at 3.3V it's already more than 200mV. Because this is quite high and will get even more when the resistor gets smaller, I wanted to increase the GPIO drive strength to keep some margin. It seems the nRF9160 has two drive strength levels, standard and high drive.

I was able to change the drive strength on the I2C peripheral just by trying to change the GPIO configuration and adding the GPIO_DS_ALT_LOW flag. However, with this way of changing the configuration it's important to not forget any of the other 'default' I2C peripheral flags, like GPIO_OPEN_DRAIN and GPIO_OUTPUT. When I played a bit around with the config I found that these flags were necessary:

gpio_pin_configure(gpio_dev, 9, GPIO_OUTPUT | GPIO_DS_ALT_LOW | GPIO_OPEN_DRAIN | GPIO_ACTIVE_LOW);

With this config it seems to work, but I don't like the approach of having to guess the default flags and having to change this in the main code (I would prefer to have this changed at boot time). Is there any way of specifying this in the devicetree or some way of appending flags so I keep the default?

Thanks,
Martin

Parents
  • Hello Martin,

    With a 2kR resistor at 3.3V it's already more than 200mV.

    Is there a particular reason for choosing 2 k Ohm for your pullup resistor?
    I would recommend that you use the standard size of 4.7k Ohm for your pullup resistor, instead of the 2 k Ohm.

    With this config it seems to work, but I don't like the approach of having to guess the default flags and having to change this in the main code (I would prefer to have this changed at boot time). Is there any way of specifying this in the devicetree or some way of appending flags so I keep the default?

    There is no way to change this in the device tree, since this only concern which physical pins and peripheral that will be in use by the application.
    You might be able to incorporate this change in the twi init function that is run by Zephyr when you have enabled the TWI peripheral through the prj.conf file.
    In the TWIM case, this would be the twim_init function located in  .. ncs\zephyr\drivers\i2c\i2c_nrfx_twim.c, for example.
    For the general case please keep in mind that modifying the function's Zephyr rely on behind the scenes might break the different driver's functionality.

    Alternatively, you will have to initialize the TWI in your main.c file (or other project file), where you pretty much do the initialization yourself instead of having Zephyr do it behind the scenes through the prj.conf. In this case, you could just add your line at the end of this initialization.

    Best regards,
    Karl

Reply
  • Hello Martin,

    With a 2kR resistor at 3.3V it's already more than 200mV.

    Is there a particular reason for choosing 2 k Ohm for your pullup resistor?
    I would recommend that you use the standard size of 4.7k Ohm for your pullup resistor, instead of the 2 k Ohm.

    With this config it seems to work, but I don't like the approach of having to guess the default flags and having to change this in the main code (I would prefer to have this changed at boot time). Is there any way of specifying this in the devicetree or some way of appending flags so I keep the default?

    There is no way to change this in the device tree, since this only concern which physical pins and peripheral that will be in use by the application.
    You might be able to incorporate this change in the twi init function that is run by Zephyr when you have enabled the TWI peripheral through the prj.conf file.
    In the TWIM case, this would be the twim_init function located in  .. ncs\zephyr\drivers\i2c\i2c_nrfx_twim.c, for example.
    For the general case please keep in mind that modifying the function's Zephyr rely on behind the scenes might break the different driver's functionality.

    Alternatively, you will have to initialize the TWI in your main.c file (or other project file), where you pretty much do the initialization yourself instead of having Zephyr do it behind the scenes through the prj.conf. In this case, you could just add your line at the end of this initialization.

    Best regards,
    Karl

Children
  • Hi Karl,

    Thank for the tip! There are a lot of devices on the bus with relatively long lines, which is why the 2k resistor is required.

    In nrfx_twim.c I changed the TWIM_PIN_INIT macro to use the H0D1 drive flag instead of S0D1.

    #define TWIM_PIN_INIT(_pin) nrf_gpio_cfg((_pin),                     \
                                             NRF_GPIO_PIN_DIR_INPUT,     \
                                             NRF_GPIO_PIN_INPUT_CONNECT, \
                                             NRF_GPIO_PIN_PULLUP,        \
                                             NRF_GPIO_PIN_H0D1,          \
                                             NRF_GPIO_PIN_NOSENSE)

    Unfortunately it requires a change in the SDK, but hopefully there will be some way of changing this in the dtc in the future.

    Best regards,
    Martin

Related