Interfacing external EEPROM using I2C drivers on nrf52840 in Zephyr NCS v2.5.0

Hi. I am working on a project and I need to interface a EEPROM to store some data. I tried using I2C drivers from the ncs but it appears that the APIs support only 8 bit addresses as shown below.

Write API:

/**
 * @brief Write multiple bytes to an internal address of an I2C device.
 *
 * This is equivalent to:
 *
 *     i2c_burst_write(spec->bus, spec->addr, start_addr, buf, num_bytes);
 *
 * @param spec I2C specification from devicetree.
 * @param start_addr Internal address to which the data is being written.
 * @param buf Memory pool from which the data is transferred.
 * @param num_bytes Number of bytes being written.
 *
 * @return a value from i2c_burst_write()
 */
static inline int i2c_burst_write_dt(const struct i2c_dt_spec *spec,
				     uint8_t start_addr,
				     const uint8_t *buf,
				     uint32_t num_bytes);

Read API:

/**
 * @brief Read multiple bytes from an internal address of an I2C device.
 *
 * This is equivalent to:
 *
 *     i2c_burst_read(spec->bus, spec->addr, start_addr, buf, num_bytes);
 *
 * @param spec I2C specification from devicetree.
 * @param start_addr Internal address from which the data is being read.
 * @param buf Memory pool that stores the retrieved data.
 * @param num_bytes Number of bytes to read.
 *
 * @return a value from i2c_burst_read()
 */
static inline int i2c_burst_read_dt(const struct i2c_dt_spec *spec,
				    uint8_t start_addr,
				    uint8_t *buf,
				    uint32_t num_bytes);

So, is there any other alternative for this which I can use to access the EEPROM as 8 bits are not enough to access all the addresses. This driver is more suitable for sensors I believe.

Parents
  • Hi Sahil

    These functions are primarily intended for sensors or configuration registers, yes, not for accessing EEPROM devices. 

    If you use the more generic i2c_write(..), i2c_write_dt(..), i2c_read(..) or i2c_read_dt(..) functions you can format the data payload exactly as you wish, and you should be able to use an address size matching that of your connected EEPROM. 

    If you need to do a TX -> RX transaction using repeated start you can use the i2c_transfer(..) or i2c_transfer_dt(..) functions. 

    Another alternative is to check for a native driver for your EEPROM device in Zephyr. If one exists you can interface your device directly using one of the higher level flash API's, rather than interfacing it directly through the I2C driver. 

    Best regards
    Torbjørn

  • Hi Sahil

    The addr field in the function calls should be the static I2C address of your EEPROM, that is correct, not the memory address that you are trying to access. 

    My point is that you can encode the EEPROM address in the I2C buffer itself, something like this:

    int eeprom_write(uint16_t eeprom_addr, uint8_t *data, int length)
    {
        static uint8_t write_buf[EEPROM_MAX_WRITE_LENGTH + 2];
        if (length > EEPROM_MAX_WRITE_LENGTH) return -ENOMEM;
        write_buf[0] = (uint8_t)(eeprom_addr >> 8);
        write_buf[1] = (uint8_t)(eeprom_addr);
        memcpy(&write_buf[2], data, length);
        return i2c_write(dev, write_buf, length + 2, EEPROM_I2C_ADDR);
    }

    Please note this is just an example. Without taking a look at the specification of your EEPROM I don't know exactly what the format of the instructions should be. 

    Best regards
    Torbjørn

Reply
  • Hi Sahil

    The addr field in the function calls should be the static I2C address of your EEPROM, that is correct, not the memory address that you are trying to access. 

    My point is that you can encode the EEPROM address in the I2C buffer itself, something like this:

    int eeprom_write(uint16_t eeprom_addr, uint8_t *data, int length)
    {
        static uint8_t write_buf[EEPROM_MAX_WRITE_LENGTH + 2];
        if (length > EEPROM_MAX_WRITE_LENGTH) return -ENOMEM;
        write_buf[0] = (uint8_t)(eeprom_addr >> 8);
        write_buf[1] = (uint8_t)(eeprom_addr);
        memcpy(&write_buf[2], data, length);
        return i2c_write(dev, write_buf, length + 2, EEPROM_I2C_ADDR);
    }

    Please note this is just an example. Without taking a look at the specification of your EEPROM I don't know exactly what the format of the instructions should be. 

    Best regards
    Torbjørn

Children
Related