1.l2c总线设备驱动模型
首先写出左边l2c控制器驱动程序用来收发数据,还要写出右边设备驱动,左边可以认为是总线驱动,Adapter设备器。
左边驱动程序通过操作里面寄存器来收发l2c数据,右边会用到控制器来读写上面东西。
在设备驱动那层阅读设备芯片手册来知道发送什么命令,数据,在编写驱动程序时重点放在具体芯片怎么操作上面,至于硬件操作细节由总线驱动来实现,分层分为3层。
实际上对于单片机也是相同思想,当操作具体硬件时,如下图底层提供l2c处理细节,而发什么内容有OLED芯片决定。
(1)AT24 C02芯片:知道发什么,读什么
(2)l2c实现怎么发怎么读
1.主控芯片有很多i2c控制器,接到哪条i2c总线上,指定设备地址在设备树上指定这两点也就足够了。
看硬件图接在I2C1总线下面于是在设备树这个节点下面新增加这个节点。
这个节点内容reg内容
看原理图后3位都是000 1010000=0x50 reg = <0x50>
对于每个clientd的addr来自于设备树的reg,adapter适配器也就是这个i2c设备挂载在那个i2c总线。适配器有I2C算法里面有传输函数。
I2c_driver用来与I2c_client设备匹配注册进给链表,当发现匹配的设备后会调用proble函数,
在这里插static struct i2c_driver at24c02_drv = {.driver = {.name = "my24c02",.of_match_table = at24c02_of_match,},.probe = at24c02_probe,.remove = at24c02_remove,.id_table = at24c02_ids,};入代码片
.id_table 表示来说我支持哪些i2c设备
优先使用.of_match_table = at24c02_of_match匹配,不行的话再使用.id_table匹配
i2c驱动主体框架
#include #include #include #include #include #include #include #include #include #include #include #include #include static int at24c02_probe(struct i2c_client *client, const struct i2c_device_id *id){printk("%s %s %dn", __FILE__, __FUNCTION__, __LINE__);return 0;}static int at24c02_remove(struct i2c_client *client){printk("%s %s %dn", __FILE__, __FUNCTION__, __LINE__);return 0;}static const struct of_device_id at24c02_of_match[] = {{.compatible = "100ask,at24c02"},{}};static const struct i2c_device_id at24c02_ids[] = {{ "xxxxyyy",(kernel_ulong_t)NULL },{ }};static struct i2c_driver at24c02_drv = {.driver = {.name = "my24c02",.of_match_table = at24c02_of_match,},.probe = at24c02_probe,.remove = at24c02_remove,.id_table = at24c02_ids,};static int at24c02_init(void){int err;err = i2c_add_driver(&at24c02_drv);printk("%s %s %d, err = %dn", __FILE__, __FUNCTION__, __LINE__, err);return err;}static void at24c02_exit(void){i2c_del_driver(&at24c02_drv);}module_init(at24c02_init);module_exit(at24c02_exit);MODULE_LICENSE("GPL");