基于at91rm9200的i2c分析(DS1307实时时钟芯片)
board-ek.c
构造i2c_board_info结构体
static struct i2c_board_info __initdata ek_i2c_devices[] = {
{
I2C_BOARD_INFO("ds1307", 0x68),
},
};
at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));->
i2c_register_board_info(0, devices, nr_devices);->
将i2c_board_info添加到__i2c_board_list,总线0
struct i2c_devinfo *devinfo;
devinfo->busnum = busnum;
devinfo->board_info = *info;
list_add_tail(&devinfo->list, &__i2c_board_list);
注册at91rm9200_twi_device平台device
platform_device_register(&at91rm9200_twi_device);
static struct platform_device at91rm9200_twi_device = {
.name = "at91_i2c",
.id = -1,
.resource = twi_resources,
.num_resources = ARRAY_SIZE(twi_resources),
};
i2c-at91.c
static struct platform_driver at91_i2c_driver = {
.probe = at91_i2c_probe,
.remove = __devexit_p(at91_i2c_remove),
.suspend = at91_i2c_suspend,
.resume = at91_i2c_resume,
.driver = {
.name = "at91_i2c",
.owner = THIS_MODULE,
},
};
注册平台driver
platform_driver_register(&at91_i2c_driver);
当发现device链表有与”at91_i2c“同名的device就调用at91_i2c_probe
at91_i2c_probe->
构造adapter
struct i2c_adapter *adapter;
snprintf(adapter->name, sizeof(adapter->name), "AT91");
adapter->algo = &at91_algorithm; /* 通信算法 */
clk_enable(twi_clk); /* enable peripheral clock */
at91_twi_hwinit(); /* initialize TWI controller */
at91_twi_hwinit(); /* initialize TWI controller */
注册adapter
i2c_add_numbered_adapter(adapter)->
i2c_register_adapter(adap)->
device_register(&adap->dev);
/* create pre-declared device nodes */
i2c_scan_static_board_info(adap);->
list_for_each_entry(devinfo, &__i2c_board_list, list)
如果busnum相等则调用i2c_new_device
if (devinfo->busnum == adapter->nr && !i2c_new_device(adapter, &devinfo->board_info))->
构造client
struct i2c_client *client;
client->adapter = adap;
/* 检查设备地址是否有效 */
i2c_check_client_addr_validity(client);
/* 检查地址是否被占用 */
i2c_check_addr_busy(adap, client->addr);
注册device
device_register(&client->dev);
i2c-dev.c
i2c_dev_init->
申请设备号,并创建cdev,初始化cdev
register_chrdev(I2C_MAJOR, "i2c", &i2cdev_fops);
创建class:/sys/class/i2c-dev
i2c_dev_class = class_create(THIS_MODULE, "i2c-dev");
注册i2c_driver
i2c_add_driver(&i2cdev_driver);->
i2c_register_driver(THIS_MODULE, driver);->
注册driver
driver_register(&driver->driver);
在链表i2c_bus_type中遍历每一个device,对每一个device调用__process_new_driver
bus_for_each_dev(&i2c_bus_type, NULL, driver, __process_new_driver);
__process_new_driver->
i2c_do_add_adapter(data, to_i2c_adapter(dev))
调用driver的attach_adapter函数,即i2cdev_attach_adapter
driver->attach_adapter(adap)->
/* 构造i2c_dev */
i2c_dev = get_free_i2c_dev(adap);->
/* 将i2c_dev添加到i2c_dev_list */
list_add_tail(&i2c_dev->list, &i2c_dev_list);
/* 在/dev/目录下创建设备节点i2c-0 */
i2c_dev->dev = device_create(i2c_dev_class, &adap->dev, MKDEV(I2C_MAJOR, adap->nr), NULL, "i2c-%d", adap->nr);
这样我们就可以通过i2cdev_fops来操作i2c设备了
static const struct file_operations i2cdev_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.read = i2cdev_read,
.write = i2cdev_write,
.unlocked_ioctl = i2cdev_ioctl,
.open = i2cdev_open,
.release = i2cdev_release,
};
我们也可以不通过/dev/i2c-0这种操作方式,单独实现特定的i2c_driver和i2c_client
rtc-ds1307.c
static const struct i2c_device_id ds1307_id[] = {
{ "ds1307", ds_1307 },
{ "ds1337", ds_1337 },
{ "ds1338", ds_1338 },
{ "ds1339", ds_1339 },
{ "ds1388", ds_1388 },
{ "ds1340", ds_1340 },
{ "ds3231", ds_3231 },
{ "m41t00", m41t00 },
{ "rx8025", rx_8025 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ds1307_id);
static struct i2c_driver ds1307_driver = {
.driver = {
.name = "rtc-ds1307",
.owner = THIS_MODULE,
},
.probe = ds1307_probe,
.remove = __devexit_p(ds1307_remove),
.id_table = ds1307_id,
};
i2c_add_driver(&ds1307_driver)->
i2c_register_driver(THIS_MODULE, driver)->
driver->driver.bus = &i2c_bus_type;
注册driver
driver_register(&driver->driver)->
检查driver是否已存在
driver_find(drv->name, drv->bus)->
bus_add_driver(drv)->
driver_attach(drv)->
遍历drv->bus链表上的每一个device,为每一个device调用__driver_attach
bus_for_each_dev(drv->bus, NULL, drv, __driver_attach)->
__driver_attach(struct device *dev, void *data)->
driver_match_device(drv, dev))->
如果总线i2c_bus_type存在match函数则调用match
drv->bus->match ? drv->bus->match(dev, drv) : 1;
i2c-core.c中定义了i2c_bus_type,同时定义了i2c_device_match函数
struct bus_type i2c_bus_type = {
.name = "i2c",
.match = i2c_device_match,
.probe = i2c_device_probe,
.remove = i2c_device_remove,
.shutdown = i2c_device_shutdown,
.pm = &i2c_device_pm_ops,
};
i2c_device_match(struct device *dev, struct device_driver *drv)->
匹配i2c_device_id(ds1307_id)里的名称
i2c_match_id(driver->id_table, client)->
如果匹配成功,继续driver_attach->
driver_probe_device(drv, dev)->
really_probe(dev, drv)->
调用i2c_device_probe
dev->bus->probe(dev)->
struct i2c_driver *driver = to_i2c_driver(dev->driver)
调用ds1307_probe
driver->probe(client, i2c_match_id(driver->id_table, client))->
注册rtcdevice
ds1307->rtc = rtc_device_register(client->name, &client->dev, &ds13xx_rtc_ops, THIS_MODULE)->
注册device
device_register(&rtc->dev);
基于at91rm9200的i2c分析(DS1307实时时钟芯片)的更多相关文章
- Arduino I2C + DS1307实时时钟
主要特性 DS1307是Maxim的串行.I2C实时时钟芯片.主要特性有: 工作电压:主电源电压4.5~5.5V,电池电压2.0~3.5V 功耗:电池供电.备份模式时<500nA 接口:I2C, ...
- STC8H开发(十三): I2C驱动DS3231高精度实时时钟芯片
目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...
- STC8H开发(十四): I2C驱动RX8025T高精度实时时钟芯片
目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...
- 轻松吃透实时时钟芯片DS1302软硬件设计,看完秒懂
今天我们来讨论一款老掉牙的实时时钟芯片DS1302.什么是实时时钟(RealTime Clock, RTC)呢?为什么我们需要它呢?假设你使用单片机实现万年历应用,一般的做法是这样的:设置中断后判断1 ...
- 4.9版本的linux内核中实时时钟芯片pcf85263的驱动源码在哪里
答:drivers/rtc/rtc-pcf85263.c,内核配置选项为 CONFIG_RTC_DRV_PCF85263 Location: -> Device Drivers -> Re ...
- 4.9版本的linux内核中实时时钟芯片pt7c4338的驱动源码在哪里
答:drivers/rtc/rtc-ds1307.c,内核配置项为CONFIG_RTC_DRV_DS1307 Location: -> Device Drivers -> Real Tim ...
- I2C实时时钟rx-8025板卡实际应用
rx-8025是片外I2C实时时钟,其应用于9260板卡方法如下.总体思想是配置内核添加驱动(I2C驱动,内核已提供的很完备),板级文件添加设备,添加设备文件以应用程序操作. 1. 配置内核 1)I2 ...
- Maxim实时时钟芯片设计指南5791-关于编写健壮的实时时钟控制代码的提示
用DS12C887设计一个万年历,虽然反复查看说明书,还是出各种的错误. 因此,从美信官网查询资料,翻译的不太通,凑合着对照看. 原文链接 Tips for Writing Bulletproof R ...
- linux 实时时钟(RTC)驱动【转】
转自:http://blog.csdn.net/yaozhenguo2006/article/details/6820218 这个是linux内核文档关于rtc实时时钟部分的说明,此文档主要描述了rt ...
随机推荐
- 8-15 Shuffle uva12174
题意: 你正在使用的音乐播放器有一个所谓的乱序功能,即随机打乱歌曲的播放顺序.假设一共有s首歌,则一开始会给这s首歌随机排序,全部播放完毕后再重新随机排序.继续播放,依此类推.注意,当s首歌播放完毕之 ...
- 004 Hadoop2.x基础知识
一:大数据应用 1.Cloudera cloudera公司是Hadoop三大发行商之一,其版本为CDH版本,现在最新的版本是CDH5. 网站:http://archive.cloudera.com/c ...
- Eclipse反编译插件的安装
步骤: 1.已经安装了Eclipse,如我的Eclipse目录:C:\Programs\JAVA\eclipse 2.反编译插件包:eclipse 反编译插件 jad 3.3.0.zip 3.解压反编 ...
- 【*】Redis常见问题汇总
1.什么是Redis? Redis是一个开源.高性能.基于键值对的缓存与存储系统. 2.Redis相比memcached有哪些优势? 劣势:Redis是单线程,Memcached是多线程,在多核服务器 ...
- 字符串hash与字典树
title: 字符串hash与字典树 date: 2018-08-01 22:05:29 tags: acm 算法 字符串 概述 这篇主要是关于字符串里的 字符串hash 和 字符串字典树,,两个都是 ...
- 【基础知识】.Net基础加强 第四天
一. 显示实现接口 1. 显示实现接口的目的:为了解决法方法重名的问题. 2. 显示实现接口必须是私有的,不能用public 3. (复习)类中成员不写访问修饰符默认是private:类如果不写访问修 ...
- JAVA 9 新特性
Oracle已将JAVA 9的开发提上日程.OpenJDK上已经出现了关于下一个主版本JAVA 9的改进建议(JEP).与以往不同,Oracle在这次谈及了一些真正的特性.而早期对于JDK9的声明仅 ...
- 深入理解mysql的自连接和join关联
一.mysql自连接 mysql有时在信息查询时需要进行对自身连接(自连接),所以我们需要为表定义别名.我们举例说明,下面是商品采购表,我们需要找到采购价格比惠惠高的所有信息. 一般情况我们看到这张表 ...
- 凡信(超仿微信Android版)开源了,内有源码下载 -
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha 凡信(超仿微信Android版)开源了,内有源码下载 - IM Geek开发者社区-移动 ...
- java线程系列文章之一(线程的安全性)
本文来自:高爽|Coder,原文地址:http://blog.csdn.net/ghsau/article/details/7421217,转载请注明. 当我们查看JDK API的时候,总会发现一些类 ...