zoukankan      html  css  js  c++  java
  • 基于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);
                        
                    

            
        
        
        
           

  • 相关阅读:
    战胜忧虑<2>——忙碌可以消除忧虑
    战胜忧虑<1>——不要让忧郁侵入你的生活
    Django的下载和安装
    Github 如何上传本地文件
    Python_相对路径的获取
    Python_生成HTMLTestRunner测试报告
    Python_requests实例
    Charles抓包(Http/Https请求)
    Python_base_函数返回值
    Python_base_print 取消自动换行
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3206335.html
Copyright © 2011-2022 走看看