一、编写一个框架程序1.1 设备树1.2 platform_driver1.3 probe函数1.3.1 i2c_adpater结构体1.3.2 i2c_algorithm示例二、模拟EEPROM2.1 编写master_xfer函数2.2 上机实验2.2.2 编译、安装驱动程序2.2.3 使用i2c-tools测试
参考资料:
- Linux内核文档:
Linux-4.9.88\Documentation\devicetree\bindings\i2c\i2c-gpio.txt
Linux-5.4\Documentation\devicetree\bindings\i2c\i2c-gpio.yaml
- Linux内核驱动程序:使用GPIO模拟I2C
Linux-4.9.88\drivers\i2c\busses\i2c-gpio.c
Linux-5.4\drivers\i2c\busses\i2c-gpio.c
- Linux内核真正的I2C控制器驱动程序
- IMX6ULL:
Linux-4.9.88\drivers\i2c\busses\i2c-imx.c
- STM32MP157:
Linux-5.4\drivers\i2c\busses\i2c-stm32f7.c
一、编写一个框架程序
1.1 设备树
在设备树里构造I2C Bus节点:
1.2 platform_driver
分配、设置、注册platform_driver结构体。
1.3 probe函数
platform_driver 核心是probe函数,它要做这几件事:
- 根据设备树信息设置硬件(引脚、时钟等)
- 分配、设置、注册一个i2c_adpater结构体:
- i2c_adpater的核心是i2c_algorithm
- i2c_algorithm的核心是master_xfer函数
1.3.1 i2c_adpater结构体
- 分配
- 设置
- 注册:i2c_add_adapter/i2c_add_numbered_adapter
- 反注册
1.3.2 i2c_algorithm示例
- Linux-5.4中使用GPIO模拟I2C
- Linux-5.4中STM32F157的I2C驱动
- Linux-4.9.88中IMX6ULL的I2C驱动
i2c_apdater核心是master_xfer函数,它的实现取决于硬件,大概代码如下:
二、模拟EEPROM
在虚拟的I2C_Adapter驱动程序里,只要实现了其中的
master_xfer
函数,这个I2C Adapter就可以使用了。2.1 编写master_xfer
函数
模拟一个EEPROM,需要实现
master_xfer
函数,思路如下:- 分配一个512自己的buffer,表示EEPROM
- 对于slave address为0x50的i2c_msg,解析并处理
- 对于写:把i2c_msg的数据写入buffer
- 对于读:从buffer中把数据写入i2c_msg
- 对于slave address为其他值的i2c_msg,返回错误
2.2 上机实验
2.2.1 编译、替换设备树
- 修改
arch/arm/boot/dts/100ask_imx6ull-14x14.dts
,添加如下代码:
- 编译设备树:
在Ubuntu的IMX6ULL内核目录下执行如下命令,
得到设备树文件:
arch/arm/boot/dts/100ask_imx6ull-14x14.dtb
- 复制到NFS目录:
- 开发板上挂载NFS文件系统
- vmware使用NAT(假设windowsIP为192.168.1.100)
- vmware使用桥接,或者不使用vmware而是直接使用服务器:假设Ubuntu IP为192.168.1.137
- 更新设备树
- 重启开发板
2.2.2 编译、安装驱动程序
- 编译:
- 在Ubuntu上
- 修改
06_i2c_adapter_virtual_ok
中的Makefile,指定内核路径KERN_DIR
,在执行make
命令即可。
- 安装:
- 在开发板上
- 挂载NFS,复制文件,insmod,类似如下命令:
2.2.3 使用i2c-tools测试
在开发板上执行,命令如下:
- 列出I2C总线
结果类似下列的信息:
注意:不同的板子上,i2c-bus-virtual的总线号可能不一样,上文中总线号是4。
- 检查虚拟总线下的I2C设备
- 读写模拟的EEPROM