I2C系統框架(1)

lethe1203發表於2024-03-30
學習資料:韋東山第三期
i2c_adapter:
nr:第幾路i2c匯流排
xfer:讀寫操作
 struct i2c_adapter {
         struct module *owner;
         unsigned int class;               /* classes to allow probing for */
         const struct i2c_algorithm *algo; /* the algorithm to access the bus */
         void *algo_data;

         /* data fields that are valid for all devices   */
         struct rt_mutex bus_lock;

         int timeout;                    /* in jiffies */
         int retries;
         struct device dev;              /* the adapter device */

         int nr;
         char name[48];
         struct completion dev_released;

         struct mutex userspace_clients_lock;
         struct list_head userspace_clients;

         struct i2c_bus_recovery_info *bus_recovery_info;
         const struct i2c_adapter_quirks *quirks;
 };

 struct i2c_algorithm {
         /* If an adapter algorithm can't do I2C-level access, set master_xfer
            to NULL. If an adapter algorithm can do SMBus access, set
            smbus_xfer. If set to NULL, the SMBus protocol is simulated
            using common I2C messages */
         /* master_xfer should return the number of messages successfully
            processed, or a negative value on error */
         int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,
                            int num);
         int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,
                            unsigned short flags, char read_write,
                            u8 command, int size, union i2c_smbus_data *data);

         /* To determine what the adapter supports */
         u32 (*functionality) (struct i2c_adapter *);

 #if IS_ENABLED(CONFIG_I2C_SLAVE)
         int (*reg_slave)(struct i2c_client *client);
         int (*unreg_slave)(struct i2c_client *client);
 #endif
 };
 
 struct i2c_msg {
         __u16 addr;     /* slave address                        */
         __u16 flags;
 #define I2C_M_RD                0x0001  /* read data, from slave to master */
                                         /* I2C_M_RD is guaranteed to be 0x0001! */
 #define I2C_M_TEN               0x0010  /* this is a ten bit chip address */
 #define I2C_M_DMA_SAFE          0x0200  /* the buffer of this message is DMA safe */
                                         /* makes only sense in kernelspace */
                                         /* userspace buffers are copied anyway */
 #define I2C_M_RECV_LEN          0x0400  /* length will be first received byte */
 #define I2C_M_NO_RD_ACK         0x0800  /* if I2C_FUNC_PROTOCOL_MANGLING */
 #define I2C_M_IGNORE_NAK        0x1000  /* if I2C_FUNC_PROTOCOL_MANGLING */
 #define I2C_M_REV_DIR_ADDR      0x2000  /* if I2C_FUNC_PROTOCOL_MANGLING */
 #define I2C_M_NOSTART           0x4000  /* if I2C_FUNC_NOSTART */
 #define I2C_M_STOP              0x8000  /* if I2C_FUNC_PROTOCOL_MANGLING */
         __u16 len;              /* msg length                           */
         __u8 *buf;              /* pointer to msg data                  */
 };
 
  struct i2c_client {
         unsigned short flags;           /* div., see below              */
 #define I2C_CLIENT_PEC          0x04    /* Use Packet Error Checking */
 #define I2C_CLIENT_TEN          0x10    /* we have a ten bit chip address */
                                         /* Must equal I2C_M_TEN below */
 #define I2C_CLIENT_SLAVE        0x20    /* we are the slave */
 #define I2C_CLIENT_HOST_NOTIFY  0x40    /* We want to use I2C host notify */
 #define I2C_CLIENT_WAKE         0x80    /* for board_info; true iff can wake */
 #define I2C_CLIENT_SCCB         0x9000  /* Use Omnivision SCCB protocol */
                                         /* Must match I2C_M_STOP|IGNORE_NAK */

         unsigned short addr;            /* chip address - NOTE: 7bit    */
                                         /* addresses are stored in the  */
                                         /* _LOWER_ 7 bits               */
         char name[I2C_NAME_SIZE];
         struct i2c_adapter *adapter;    /* the adapter we sit on        */
         struct device dev;              /* the device structure         */
         int init_irq;                   /* irq set at initialization    */
         int irq;                        /* irq issued by device         */
         struct list_head detected;
 #if IS_ENABLED(CONFIG_I2C_SLAVE)
         i2c_slave_cb_t slave_cb;        /* callback for slave mode      */
 #endif
 };
子裝置用i2c_client結構體表示,這個結構體裡面肯定有addr,adapter,掛在哪一條匯流排上
傳輸的資料使用i2c_msg表示,.buf表示資料
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
最終使用i2c_transfer函式在adap找到傳輸函式,把msgs傳給裝置,裝置的地址和buf在msgs裡面包含有,是複數
舉例:裝置地址為0x50的EEPROM,要讀取它裡面儲存地址為0x10的一個位元組,應該構造幾個i2c_msg?
  • 要構造2個i2c_msg
  • 第一個i2c_msg表示寫操作,把要訪問的儲存地址0x10發給裝置
  • 第二個i2c_msg表示讀操作
  • 程式碼如下
u8 data_addr = 0x10;
i8 data;
struct i2c_msg msgs[2];

msgs[0].addr   = 0x50;
msgs[0].flags  = 0;            // 寫操作
msgs[0].len    = 1;
msgs[0].buf    = &data_addr;

msgs[1].addr   = 0x50;
msgs[1].flags  = I2C_M_RD;    //
msgs[1].len    = 1;
msgs[1].buf    = &data;

相關文章