NRF9160DK i2c device no response

Evaluating direct access I2C operation with the NRF9160DK. I have a INA219 connected to pin 30 & pin 31. I am aware that there is a zephyr driver for the INA219, but I want to test direct I2C operation until the replacement device can be implemented. I am only trying to read register 0x00, which should provide the output of 0x39, 0x9F. I have tried different variations of the i2c read/write (i2c_write_read_dt, and separate write/read functions) and all return an error code -5. 
To ensure that data is being transmitted to the INA219 (to eliminate connection issues) I am monitoring the SCL & SDA data lines using a DIGILENT Device to see what data is transmitted. I am also able to send I2C data to the INA219 to verify proper device operation. When sending data from the DIGILENT device I get the proper response and the proper returned data. Below is the protocol data that is captured when monitoring the SDA & SCL lines. By looking at the received protocol what is being sent from the DIGILENT device vs the NRF9160 is different

Protocol Captures

DIGILENT Sending/Receiving I2C data (WORKS)
Start, h80 [ h40 | WR ], h00, h00, Stop
Start, h80 [ h40 | WR ], h00,
Restart, h81 [ h40 | RD ], h39, h9F NACK, Stop


NRF9160DK Sending/Receiving I2C data (DOESNT WORK)
Start, h80 [ h40 | WR ], h00, h00,
Restart, h81 [ h40 | RD ], h01, h02 NACK, Stop

nrf9160dk_overlay file

&i2c2 {
    status = "okay";
    pinctrl-0 = <&i2c2_default>;
    pinctrl-1 = <&i2c2_sleep>;
    pinctrl-names = "default", "sleep";
    ina219: ina219@40{
        compatible = "i2c-device";
        status = "okay";
        reg = < 0x40 >;
        label = "ina219";
    };
};

&pinctrl {
    /omit-if-no-ref/ i2c2_default: i2c2_default {
        group1  {
            psels = <NRF_PSEL(TWIM_SCL, 0, 31)>,
                    <NRF_PSEL(TWIM_SDA, 0, 30)>;
        };
    };

    /omit-if-no-ref/ i2c2_sleep: i2c2_sleep {
        group1  {
            psels = <NRF_PSEL(TWIM_SCL, 0, 31)>,
                    <NRF_PSEL(TWIM_SDA, 0, 30)>;
            low-power-enable;
        };
    };
};

static const struct i2c_dt_spec dev_i2c = I2C_DT_SPEC_GET(I2C_NODE);
if (!device_is_ready(dev_i2c.bus)) {
    LOG_ERR("I2C bus %s is not ready!\n\r",dev_i2c.bus->name);
    //return -1;
}



    // Step 1: Write to Register 0x00
    ret = i2c_write_dt(&dev_i2c, &reg_addr, 1);
    if (ret != 0) {
        LOG_ERR("Failed to write register address (Error %d)", ret);
        //return;
    }
    k_sleep(K_MSEC(10));

    // Step 2: Read 2 bytes from Register 0x00
    ret = i2c_read_dt(&dev_i2c, config_data, 2);
    if (ret != 0) {
        LOG_ERR("Failed to read INA219 register (Error %d)", ret);
        //return;
    }

Parents
  • Hi,

    I don't exactly understand the log information, but on a high level I would expect something along the lines of:

    Start, h80 [ h40 | WR ], h00, h00, Stop

    msg[0].buf = 40/80 00 00;
    msg[0].len = 2/3 bytes?;
    msg[0].flags = I2C_MSG_WRITE | I2C_MSG_STOP;

    i2c_transfer_dt(spec, msg, 1);

    Start, h80 [ h40 | WR ], h00,
    Restart, h81 [ h40 | RD ], h39, h9F NACK, Stop

    msg[0].buf = 40/80 00;
    msg[0].len = 1/2 bytes?;
    msg[0].flags = I2C_MSG_WRITE;

    msg[1].buf = 81/40?;
    msg[1].len = 2/3bytes?;
    msg[1].flags = I2C_MSG_RESTART | I2C_MSG_READ | I2C_MSG_STOP;

    i2c_transfer_dt(spec, msg, 2);

    Something along of those lines.

    Kenneth

  • Kenneth

    Thank you for your response. What I am trying to show with the log information is the difference in the I2C capture from when i am trying to read data from the INA219 with the Digilent device as the I2C master versus the NRF9160Dk as the I2C master. What i was trying to show is that there is a difference (with same hw connections) between them and the digilent as the master works (i get data), and the nrf9160 as master (it doesn't work i2C return value of -5).

    From what i am seeing with the Digitlent master there is an additional transaction "Start, h80 [ h40 | WR ], h00," between the initial start and restart. The NRF9160 capture does not have intermediary transaction. 

Reply
  • Kenneth

    Thank you for your response. What I am trying to show with the log information is the difference in the I2C capture from when i am trying to read data from the INA219 with the Digilent device as the I2C master versus the NRF9160Dk as the I2C master. What i was trying to show is that there is a difference (with same hw connections) between them and the digilent as the master works (i get data), and the nrf9160 as master (it doesn't work i2C return value of -5).

    From what i am seeing with the Digitlent master there is an additional transaction "Start, h80 [ h40 | WR ], h00," between the initial start and restart. The NRF9160 capture does not have intermediary transaction. 

Children
  • I can understand, but take a look at how i2c_transfer_dt() is used in my "example", and search also for drivers in zephyr that use i2c_transfer_dt(), I think you should be able to replicate the same with nRF9160 using the suggestion I provided as guide.

    Kenneth

  • Fin tuning it a bit:

    Start, h80 [ h40 | WR ], h00, h00, Stop

    msg[0].buf = 0x00 0x00;
    msg[0].len = 2;
    msg[0].flags = I2C_MSG_WRITE | I2C_MSG_STOP;

    i2c_transfer_dt(spec, msg, 1);

    Start, h80 [ h40 | WR ], h00,
    Restart, h81 [ h40 | RD ], h39, h9F NACK, Stop

    msg[0].buf = 0x00;
    msg[0].len = 1;
    msg[0].flags = I2C_MSG_WRITE;

    msg[1].buf = 0x39 0x9F;
    msg[1].len = 2;
    msg[1].flags = I2C_MSG_RESTART | I2C_MSG_READ | I2C_MSG_STOP;

    i2c_transfer_dt(spec, msg, 2);

    Something along of those lines.

    Kenneth

Related