Rogue I2C read starting when I force Zephyr to shut down

Hi,

I'm using SDK 2.1.0 for this project.

I found that when I shut down using the following:

pm_state_force(0u, &(struct pm_state_info){PM_STATE_SOFT_OFF, 0, 0}); // Force a hard off where the interrupt wakeup resets the processor
I am getting an unexpected I2C read starting on my I2C bus. I have both a periodic k_work_delayable task that does a manual read on this bus, and also an interrupt service routine that kicks off a worker to do the same.
Before I shut down I turn off my ISR and I cancel my delayable task, so I don't think there's a pending read trying to kick off, but that's my best guess about why it's happening. I also tried adding a global variable in my task that performs the read so that if my shutting_down variable is true it skips the read.
 
Do you have any ideas on how to make sure I don't have a pending read or task before shutting down, or any thoughts on why this kicks off when I call the shutdown function? Maybe part of shutting down is to hurry up and close out any pending tasks?
Thanks,
Glen
Parents
  • Hello Glen,

    Are you using some specific I2C device driver from zephyr by chance?

    I wonder if it could be part of the shutdown procedure in the driver for this device.

    Best regards,

    Michal

  • I don't think so. It's a custom driver I made for this device but it appears to just use the i2c_nrfx_twi driver. My .dts file looks like this: 

    &i2c0 {
    compatible = "nordic,nrf-twi";
    status = "okay";
    pinctrl-0 = <&i2c0_default>;
    pinctrl-1 = <&i2c0_sleep>;
    pinctrl-names = "default", "sleep";
    clock-frequency = <100000>;

    tm065049@2A {
    compatible = "nordic,tm065049";
    int-gpios = <&gpio0 25 (GPIO_ACTIVE_LOW)>;
    reg = <0x2A>;
    };
    };

    I've found that this only happens when there's been heavy traffic happening while I'm shutting down, but at this point I feel like I've tried everything to get it to shut off, including lots of k_sleep delays to let things finish.

    I even did my best to disable and uninitialize the I2C driver and turn the SDA and SCL lines back into GPIO so it can't send anything, but my best attempt at code to do that apparently doesn't work. I think I have the device definition for my nrfx_twi_t  struct wrong.

    // GDM I added this function because I found that when shutting down in board.c via pm_state_force, I was getting
    // a half a read coming out of the I2C port.
    static const struct device *const m_i2c_dev = DEVICE_DT_GET(DT_NODELABEL(i2c0));
    static const struct device *const gpio_dev = DEVICE_DT_GET(DT_NODELABEL(gpio0));

    void disableI2C(void)
    {
    const struct nrfx_twi_t *config = m_i2c_dev->config;

    nrfx_twi_disable(config);
    nrfx_twi_uninit(config);

    // Reconfigure the I2C pins as inputs
    gpio_pin_configure(gpio_dev, 26, GPIO_INPUT);
    gpio_pin_configure(gpio_dev, 27, GPIO_INPUT);

Reply
  • I don't think so. It's a custom driver I made for this device but it appears to just use the i2c_nrfx_twi driver. My .dts file looks like this: 

    &i2c0 {
    compatible = "nordic,nrf-twi";
    status = "okay";
    pinctrl-0 = <&i2c0_default>;
    pinctrl-1 = <&i2c0_sleep>;
    pinctrl-names = "default", "sleep";
    clock-frequency = <100000>;

    tm065049@2A {
    compatible = "nordic,tm065049";
    int-gpios = <&gpio0 25 (GPIO_ACTIVE_LOW)>;
    reg = <0x2A>;
    };
    };

    I've found that this only happens when there's been heavy traffic happening while I'm shutting down, but at this point I feel like I've tried everything to get it to shut off, including lots of k_sleep delays to let things finish.

    I even did my best to disable and uninitialize the I2C driver and turn the SDA and SCL lines back into GPIO so it can't send anything, but my best attempt at code to do that apparently doesn't work. I think I have the device definition for my nrfx_twi_t  struct wrong.

    // GDM I added this function because I found that when shutting down in board.c via pm_state_force, I was getting
    // a half a read coming out of the I2C port.
    static const struct device *const m_i2c_dev = DEVICE_DT_GET(DT_NODELABEL(i2c0));
    static const struct device *const gpio_dev = DEVICE_DT_GET(DT_NODELABEL(gpio0));

    void disableI2C(void)
    {
    const struct nrfx_twi_t *config = m_i2c_dev->config;

    nrfx_twi_disable(config);
    nrfx_twi_uninit(config);

    // Reconfigure the I2C pins as inputs
    gpio_pin_configure(gpio_dev, 26, GPIO_INPUT);
    gpio_pin_configure(gpio_dev, 27, GPIO_INPUT);

Children
No Data
Related