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");



