Files
mr-library/document/device/i2c/i2c_EN.md

13 KiB

I2C Devices

中文

Register I2C Device

int mr_i2c_dev_register(struct mr_i2c_dev *i2c_dev, const char *path, int addr, int addr_bits);
Parameter Description
i2c_dev I2C device structure pointer
path Device path
addr Device address
addr_bits Device address bits
Return Value
=0 Registration succeeds
<0 Error code
  • name: The I2C device needs to bind to the specified I2C spi_bus, and the name needs to add the spi_bus name, such as: i2cx/dev-name, i2c1/i2c10.
  • addr: Device address (the lowest bit is read/write bit, please pass the address shifted to the left). When serving as a host, the address is the peer's address. When serving as a slave, the address is its own address.
  • addr_bits: Device address bits:
    • MR_I2C_ADDR_BITS_7: 7-bit address.
    • MR_I2C_ADDR_BITS_10: 10-bit address.

Open I2C Device

int mr_dev_open(const char *path, int flags);
Parameter Description
path Device path
flags Open device flags
Return Value
>=0 Device descriptor
<0 Error code
  • path: The I2C device path, such as: i2cx/dev-name,i2c1/i2c10.
  • flags: Open device flags, support MR_O_RDONLY, MR_O_WRONLY, MR_O_RDWR.

Note: When using, the I2C device should be opened separately for different tasks according to the actual situation, and the appropriate flags should be used for management and permission control to ensure that they will not interfere with each other.

Close I2C Device

int mr_dev_close(int desc);
Parameter Description
desc Device descriptor
Return Value
=0 Close successfully
<0 Error code

Control I2C Device

int mr_dev_ioctl(int desc, int cmd, void *args);
Parameter Description
desc Device descriptor
cmd Command code
args Command parameters
Return Value
=0 Setting succeeds
<0 Error code
  • cmd: Command code, supports the following commands:
    • MR_IOC_I2C_SET_CONFIG: Set I2C device configuration.
    • MR_IOC_I2C_SET_REG: Set register value.
    • MR_IOC_I2C_SET_RD_BUFSZ: Set read buffer size.
    • MR_IOC_I2C_CLR_RD_BUF: Clear read buffer.
    • MR_IOC_I2C_SET_RD_CALL:Set read callback function.
    • MR_IOC_I2C_GET_CONFIG: Get I2C device configuration.
    • MR_IOC_I2C_GET_REG: Get register value.
    • MR_IOC_I2C_GET_RD_BUFSZ: Get read buffer size.
    • MR_IOC_I2C_GET_RD_DATASZ: Get read buffer data size.
    • MR_IOC_I2C_GET_RD_CALL:Get read callback function.

Set/Get I2C Device Configuration

I2C device configuration:

  • baud_rate: Baud rate.
  • host_slave: Master/slave mode.
  • reg_bits: Register bits.
/* Set default configuration */
struct mr_i2c_config config = MR_I2C_CONFIG_DEFAULT;

/* Set I2C device configuration */  
mr_dev_ioctl(ds, MR_IOC_I2C_SET_CONFIG, &config);
/* Get I2C device configuration */
mr_dev_ioctl(ds, MR_IOC_I2C_GET_CONFIG, &config);

Independent of I2C interface:

/* Set default configuration */
int config[] = {100000, 0, 8};

/* Set I2C device configuration */  
mr_dev_ioctl(ds, MR_IOC_SCFG, &config);
/* Get I2C device configuration */
mr_dev_ioctl(ds, MR_IOC_GCFG, &config);

Note:

  • If not manually configured, the default configuration is:
    • Baud rate: 100000
    • Master/slave mode: MR_I2C_HOST
    • Register bits: MR_I2C_REG_BITS_8
  • When an I2C device on the I2C spi_bus is configured to slave mode, it will continuously occupy the I2C spi_bus. At this point, other I2C devices cannot perform read/write operations until the I2C device in slave mode is reconfigured to master mode.

Set/Get Register Value

The register value will be written first (range: 0 ~ INT32_MAX) before reading and writing data.

/* Set register value */
mr_dev_ioctl(ds, MR_IOC_I2C_SET_REG, MR_MAKE_LOCAL(int, 0x12));

/* Get register value */  
uint8_t reg;
mr_dev_ioctl(ds, MR_IOC_I2C_GET_REG, &reg);

Independent of I2C interface:

/* Set register value */
mr_dev_ioctl(ds, MR_IOC_SPOS, MR_MAKE_LOCAL(int, 0x12));

/* Get register value */  
uint8_t reg;
mr_dev_ioctl(ds, MR_IOC_GPOS, &reg);

Note:

  • The register value only takes effect in master mode.
  • It is not effective if set to a negative number.
  • The register value is not included in the read/write size.

Set/Get Read Buffer Size

size_t size = 256;

/* Set read buffer size */
mr_dev_ioctl(ds, MR_IOC_I2C_SET_RD_BUFSZ, &size);
/* Get read buffer size */
mr_dev_ioctl(ds, MR_IOC_I2C_GET_RD_BUFSZ, &size);

Independent of I2C interface:

size_t size = 256;

/* Set read buffer size */
mr_dev_ioctl(ds, MR_IOC_SRBSZ, &size);
/* Get read buffer size */
mr_dev_ioctl(ds, MR_IOC_GRBSZ, &size);

Note: If not manually configured, it will use the size configured in Kconfig (default 32Byte). The read buffer is only used in slave mode.

Clear Read Buffer

mr_dev_ioctl(ds, MR_IOC_I2C_CLR_RD_BUF, MR_NULL);

Independent of I2C interface:

mr_dev_ioctl(ds, MR_IOC_CRBD, MR_NULL);

Get Read Buffer Data Size

size_t size = 0;

/* Get read buffer data size */
mr_dev_ioctl(ds, MR_IOC_I2C_GET_RD_DATASZ, &size);

Independent of I2C interface:

size_t size = 0;

/* Get read buffer data size */
mr_dev_ioctl(ds, MR_IOC_GRBDSZ, &size);

Set/Get Read Callback Function

/* Define callback function */
void fn(int desc, void *args)
{
    /* Handle interrupt */
}
void (*callback)(int desc, void *args);

/* Set read callback function */
mr_dev_ioctl(ds, MR_IOC_I2C_SET_RD_CALL, &fn);
/* Get read callback function */  
mr_dev_ioctl(ds, MR_IOC_I2C_GET_RD_CALL, &callback);

Independent of I2C interface:

/* Define callback function */
void fn(int desc, void *args)
{
    /* Handle interrupt */
}
void (*callback)(int desc, void *args);

/* Set read callback function */
mr_dev_ioctl(ds, MR_IOC_SRCB, &fn);
/* Get read callback function */  
mr_dev_ioctl(ds, MR_IOC_GRCB, &callback);

Read I2C Device Data

ssize_t mr_dev_read(int desc, void *buf, size_t count);
Parameter Description
desc Device descriptor
buf Read data buffer
count Read data size
Return Value
>=0 Read data size
<0 Error code
uint8_t buf[128];
/* Read I2C device data */
ssize_t size = mr_dev_read(ds, buf, sizeof(buf));
/* Whether the read succeeded */
if (size < 0)
{
    
}

Note:

  • In host mode, data is read synchronously in polling mode. In slave mode, reads a specified amount of data from the read buffer (returns the size of the data actually read).
  • When the register parameter is not negative, the write operation of the register value is inserted before the read operation.

Write I2C Device Data

ssize_t mr_dev_write(int desc, const void *buf, size_t count);
Parameter Description
desc Device descriptor
buf Write data buffer
count Write data size
Return Value
>=0 Write data size
<0 Error code
uint8_t buf[] = {0x01, 0x02, 0x03, 0x04};
/* Write data to I2C device */
ssize_t size = mr_dev_write(ds, buf, sizeof(buf));
/* Whether write succeeds */
if (size < 0)
{
    
} 

Note: When the register parameter is not negative, a register value write operation will be inserted before the write operation.

Usage Example:

#include "include/mr_lib.h"

/* Define I2C devices */
struct mr_i2c_dev host_dev;
struct mr_i2c_dev slave_dev;

/* Define I2C device descriptors */  
int host_ds = -1;
int slave_ds = -1;

void i2c_init(void)
{
    int ret = MR_EOK;
    
    /* Register I2C-HOST device */
    ret = mr_i2c_dev_register(&host_dev, "i2c1/host", 0x62, MR_I2C_ADDR_BITS_7);
    if (ret < 0)
    {
        mr_printf("host i2c device register failed: %d\r\n", mr_strerror(ret));
        return;
    }
    
    /* Register I2C-SLAVE device */
    ret = mr_i2c_dev_register(&slave_dev, "i2c2/slave", 0x62, MR_I2C_ADDR_BITS_7);
    if (ret < 0)
    {
        mr_printf("slave i2c device register failed: %d\r\n", mr_strerror(ret));
        return;
    }
    
    /* Open I2C-HOST device */
    host_ds = mr_dev_open("i2c1/host", MR_O_RDWR);
    if (host_ds < 0)
    {
       mr_printf("host i2c device open failed: %d\r\n", mr_strerror(ret));
       return;
    }
    /* Set register value */
    mr_dev_ioctl(host_ds, MR_IOC_I2C_SET_REG, MR_MAKE_LOCAL(int, 0x12));
    
    /* Open I2C-SLAVE device */
    slave_ds = mr_dev_open("i2c2/slave", MR_O_RDWR);
    if (slave_ds < 0)
    {
       mr_printf("slave i2c device open failed: %d\r\n", mr_strerror(ret));
       return;
    }
    /* Set slave mode */
    struct mr_i2c_config config = MR_I2C_CONFIG_DEFAULT;
    config.host_slave = MR_I2C_SLAVE;
    ret = mr_dev_ioctl(slave_ds, MR_IOC_I2C_SET_CONFIG, &config);
    if (ret < 0)
    {
       mr_printf("slave i2c device set config failed: %d\r\n", mr_strerror(ret));
    }
}
/* Export to auto init (APP level) */
MR_INIT_APP_EXPORT(i2c_init);

int main(void) 
{
    /* Auto init (i2c_init function will be called automatically here) */
    mr_auto_init();
    
    /* Send test data */
    uint8_t wr_buf[] = {0x01, 0x02, 0x03, 0x04};
    mr_dev_write(host_ds, wr_buf, sizeof(wr_buf));
    
    /* Receive test data */
    uint8_t rd_buf[128];
    mr_dev_read(slave_ds, rd_buf, sizeof(rd_buf));
    
    /* Compare register value */
    if (rd_buf[0] == 0x12)
    {
       /* Compare data */
       if (memcmp(wr_buf, (rd_buf + 1), sizeof(wr_buf)) == 0)
       {
           mr_printf("i2c test success\r\n");
           return 0;
       }
    }
    
    while (1)
    {
        
    }
}

Connect I2C1 and I2C2 and perform sending and receiving test. I2C1 works as master and I2C2 works as slave. I2C2 will compare the received data with the sent data. Since the register value is set, the register value will be received first before the data writing.

Software I2C

Note: Software I2C requires enabling PIN device.

Register Software I2C Bus

int mr_soft_i2c_bus_register(struct mr_soft_i2c_bus *soft_i2c_bus, const char *path, int scl_pin, int sda_pin);
Parameter Description
soft_i2c_bus Software I2C spi_bus structure pointer
path Bus path
scl_pin SCL pin number
sda_pin SDA pin number
Return Value
=0 Registration succeeds
<0 Error code
/* Define SCL, SDA pin numbers for software I2C spi_bus */
#define SCL_PIN_NUMBER                  0    
#define SDA_PIN_NUMBER                  1

/* Define software I2C spi_bus */
struct mr_soft_i2c_bus soft_i2c_bus;

/* Register software I2C spi_bus */
mr_soft_i2c_bus_register(&soft_i2c_bus, "i2c1", SCL_PIN_NUMBER, SDA_PIN_NUMBER);

After registration, the software I2C spi_bus will simulate a hardware I2C.

Note: The software I2C spi_bus only supports master mode.