电子说
I2C需要分两部分进行修改,第一部分是设备树的配置,这部分主要是有关I2C控制器相关的参数、中断等,另一部分是硬件引脚的配置,由于驱动用的是i2c-designware的通用驱动,所以需要读取进行IO初始化,这就出现了额外的操作,希望后面对驱动进行适配,可以从设备树对引脚进行配置,自动完成初始化。
下面就来看看I2C驱动的大概过程吧:
// linux_5.10/arch/riscv/boot/dts/cvitek/cv180x_base.dtsi
i2c0: i2c@04000000 {
compatible = "snps,designware-i2c";
clocks = < &clk CV180X_CLK_I2C >;
reg = < 0x0 0x04000000 0x0 0x1000 >;
clock-frequency = < 400000 >;
#size-cells = < 0x0 >;
#address-cells = < 0x1 >;
resets = < &rst RST_I2C0 >;
reset-names = "i2c0";
};
// linux_5.10/arch/riscv/boot/dts/cvitek/cv180x_base_riscv.dtsi
i2c0: i2c@04000000 {
interrupts = < 49 IRQ_TYPE_LEVEL_HIGH >;
interrupt-parent = < &plic0 >;
};
使用的是i2c designware的框架。
// linux_5.10/drivers/i2c/busses/i2c-designware-platdrv.c
dw_i2c_plat_probe(struct platform_device *pdev):
i2c_dw_probe(struct dw_i2c_dev *dev)
i2c_dw_probe_master(struct dw_i2c_dev *dev)
i2c_add_numbered_adapter(struct i2c_adapter *adap)
i2c_add_adapter(struct i2c_adapter *adapter)
i2c_register_adapter(struct i2c_adapter *adap)
device_register(struct device *dev) // 注册设备
// linux_5.10/drivers/i2c/i2c-core-base.c
i2c_register_driver(struct module *owner, struct i2c_driver *driver)
driver_register(&driver- >driver); // 注册驱动
通过device_register和driver_register会进行match和probe的操作,从而关联起来I2C适配器和设备驱动。
对于详细得展开需要进一步的学习。
i2c的驱动编程就是open/read/write/ioctrl这一套。
uint8_t reg_addr = 0x00;
uint8_t data_buf[2];
// 打开设备
int i2c_fd = open("/dev/i2c-0", O_RDWR);
// 方式一:
// 设置从机地址
ioctl(i2c_fd, I2C_SLAVE, slave_addr);
write(i2c_fd, 0, ®_addr, 1);
read(i2c_fd, 0, data_buf, 2);
// 方式二:
struct i2c_rdwr_ioctl_data rdwr;
struct i2c_msg msgs[2];
msgs[0].addr = I2C_SLAVE;
msgs[0].flags = 0;
msgs[0].len = 1;
msgs[0].buf = ®_addr;
msgs[1].addr = I2C_SLAVE;
msgs[1].flags = I2C_M_RD;
msgs[1].len = 2;
msgs[1].buf = data_buf;
rdwr.msgs = msgs;
rdwr.nmsgs = 2;
ioctl(file, I2C_RDWR, &rdwr);
以上两种方式选择其中一种就行。
接下去就用温湿度传感器测试一下i2c总线的使用,演示过程后面通过视频展示。
审核编辑:汤梓红
全部0条评论
快来发表一下你的评论吧 !