基于at91rm9200的i2c分析(DS1307实时时钟芯片)

时间:2022-10-23 10:10:04

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实时时钟芯片)的更多相关文章

  1. Arduino I2C + DS1307实时时钟

    主要特性 DS1307是Maxim的串行.I2C实时时钟芯片.主要特性有: 工作电压:主电源电压4.5~5.5V,电池电压2.0~3.5V 功耗:电池供电.备份模式时<500nA 接口:I2C, ...

  2. 轻松吃透实时时钟芯片DS1302软硬件设计,看完秒懂

    今天我们来讨论一款老掉牙的实时时钟芯片DS1302.什么是实时时钟(RealTime Clock, RTC)呢?为什么我们需要它呢?假设你使用单片机实现万年历应用,一般的做法是这样的:设置中断后判断1 ...

  3. 4&period;9版本的linux内核中实时时钟芯片pcf85263的驱动源码在哪里

    答:drivers/rtc/rtc-pcf85263.c,内核配置选项为 CONFIG_RTC_DRV_PCF85263 Location: -> Device Drivers -> Re ...

  4. 4&period;9版本的linux内核中实时时钟芯片pt7c4338的驱动源码在哪里

    答:drivers/rtc/rtc-ds1307.c,内核配置项为CONFIG_RTC_DRV_DS1307 Location: -> Device Drivers -> Real Tim ...

  5. I2C实时时钟rx-8025板卡实际应用

    rx-8025是片外I2C实时时钟,其应用于9260板卡方法如下.总体思想是配置内核添加驱动(I2C驱动,内核已提供的很完备),板级文件添加设备,添加设备文件以应用程序操作. 1. 配置内核 1)I2 ...

  6. Maxim实时时钟芯片设计指南5791-关于编写健壮的实时时钟控制代码的提示

    用DS12C887设计一个万年历,虽然反复查看说明书,还是出各种的错误. 因此,从美信官网查询资料,翻译的不太通,凑合着对照看. 原文链接 Tips for Writing Bulletproof R ...

  7. linux 实时时钟(RTC)驱动【转】

    转自:http://blog.csdn.net/yaozhenguo2006/article/details/6820218 这个是linux内核文档关于rtc实时时钟部分的说明,此文档主要描述了rt ...

  8. I2C分析三

    1 引言 IIC (Inter-Integrated Circuit1总线是一种由Philips公司开发的2线式串行总线,用于连接微控制器及其外围设备.它是同步通信的一种特殊形式,具有接口线少.控制方 ...

  9. 基于FPGA的线阵CCD实时图像采集系统

    基于FPGA的线阵CCD实时图像采集系统 2015年微型机与应用第13期 作者:章金敏,张 菁,陈梦苇2016/2/8 20:52:00 关键词: 实时采集 电荷耦合器件 现场可编程逻辑器件 信号处理 ...

随机推荐

  1. Java api 入门教程 之 JAVA的StringBuffer类

    StringBuffer类和String一样,也用来代表字符串,只是由于StringBuffer的内部实现方式和String不同,所以StringBuffer在进行字符串处理时,不生成新的对象,在内存 ...

  2. WPF学习笔记(一):数据绑定之元素到元素绑定

    前言 作为一只菜鸟,之前学了一段时间的WPF,但是没有总结,过了一学期发现好多东西都忘记了,很多东西还是需要记下来,以备后续复习. 数据绑定在事件中应用非常广泛,可以有效地减少代码量,那么什么是数据绑 ...

  3. 食物链(codevs 1074)

    题目描述 Description 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A吃B,B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并 ...

  4. HDU 5054 Alice and Bob

    #include <cstdio> int main(){ int n,m,x,y; while(~scanf("%d%d%d%d",&n,&m,&am ...

  5. nodejs版本管理工具NVM&lpar;Node Version Mene&rpar;

    最近打算用心学习nodejs,所以在学习中了解到NVM-nodejs的版本管理工具,下面我就记录下我学习并且安装的详细过程,请大神们放过~~第一步.你要先把你本机上安装的nodejs以及npm相关的东 ...

  6. django报错invalid literal for int&lpar;&rpar; with base 10&colon; &&num;39&semi;&&num;39&semi;

    这种错误是因为模型类中某个字段的条件约束为int类型,但是给了一个字符串类型,所以报错,找到那个模型类的字段,并对应修改就好了.

  7. Azure PowerShell &lpar;15&rpar; 批量导出Azure ASM&sol;ARM VM信息

    <Windows Azure Platform 系列文章目录> 客户又提出新的需求,需要知道所有订阅下的虚拟机数量.运行情况等信息. 我花了点时间,写了一个PowerShell脚本,发布到 ...

  8. 【转】在SpringMVC Controller中注入Request成员域

    原文链接:https://www.cnblogs.com/abcwt112/p/7777258.html 原文作者:abcwt112 主题 在工作中遇到1个问题....我们定义了一个Controlle ...

  9. chrome访问不了go语言中文网

    最近开发转用golang语言,所以经常在晚上搜资料,结果发现go语言中文网,我居然访问不了,刚开始以为是跟go有关,所以被*屏蔽了,结果,偶尔讨论发现办公室的其他两个同事都可以访问,真是奇了怪了 ...

  10. ASP&period;NET Web API 使用Swagger使用笔记

    https://www.cnblogs.com/lhbshg/p/8711604.html 最近换了工作,其中Webapi这块没有文档,之前有了解过Swagger借此机会好好整理下常用的地方分享给有需 ...