在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 3.4.2內(nèi)核下的I2C驅(qū)動(dòng)框架解析

            3.4.2內(nèi)核下的I2C驅(qū)動(dòng)框架解析

            作者: 時(shí)間:2016-11-21 來(lái)源:網(wǎng)絡(luò) 收藏
            第一種方法:
            at24cxx_drv.c源碼:
            #include "linux/kernel.h"
            #include "linux/module.h"
            #include "linux/platform_device.h"
            #include "linux/i2c.h"
            #include "linux/err.h"
            #include "linux/regmap.h"
            #include "linux/slab.h"
            static int __devinit at24cxx_probe(struct i2c_client *client,
            const struct i2c_device_id *id)
            {
            printk("%s %s %dn", __FILE__, __FUNCTION__, __LINE__);
            return 0;
            }
            static int __devexit at24cxx_remove(struct i2c_client *client)
            {
            printk("%s %s %dn", __FILE__, __FUNCTION__, __LINE__);
            return 0;
            }
            static const struct i2c_device_id at24cxx_id_table[] = {
            { "at24c08", 0 },
            {}
            };
            // 1. 分配/設(shè)置i2c_driver //
            static struct i2c_driver at24cxx_driver = {
            .driver = {
            .name = "100ask",
            .owner = THIS_MODULE,
            },
            .probe = at24cxx_probe,
            .remove = __devexit_p(at24cxx_remove),
            .id_table = at24cxx_id_table,
            };
            static int at24cxx_drv_init(void)
            {
            // 2. 注冊(cè)i2c_driver //
            i2c_add_driver(&at24cxx_driver);
            return 0;
            }
            static void at24cxx_drv_exit(void)
            {
            i2c_del_driver(&at24cxx_driver);
            }
            module_init(at24cxx_drv_init);
            module_exit(at24cxx_drv_exit);
            MODULE_LICENSE("GPL");
            at24cxx_dev.c源碼:
            #include "linux/kernel.h"
            #include "linux/module.h"
            #include "linux/platform_device.h"
            #include "linux/i2c.h"
            #include "linux/err.h"
            #include "linux/regmap.h"
            #include "linux/slab.h"
            static struct i2c_board_info at24cxx_info = {
            I2C_BOARD_INFO("at24c08", 0x50),
            };
            static struct i2c_client *at24cxx_client;
            static int at24cxx_dev_init(void)
            {
            struct i2c_adapter *i2c_adap;
            i2c_adap = i2c_get_adapter(0);
            at24cxx_client = i2c_new_device(i2c_adap, &at24cxx_info);
            i2c_put_adapter(i2c_adap);
            return 0;
            }
            static void at24cxx_dev_exit(void)
            {
            i2c_unregister_device(at24cxx_client);
            }
            module_init(at24cxx_dev_init);
            module_exit(at24cxx_dev_exit);
            MODULE_LICENSE("GPL");
            ===============================================================
            第二種方法:
            at24cxx_drv.c源碼:
            #include "linux/kernel.h"
            #include "linux/module.h"
            #include "linux/platform_device.h"
            #include "linux/i2c.h"
            #include "linux/err.h"
            #include "linux/regmap.h"
            #include "linux/slab.h"
            static int __devinit at24cxx_probe(struct i2c_client *client,
            const struct i2c_device_id *id)
            {
            printk("%s %s %dn", __FILE__, __FUNCTION__, __LINE__);
            return 0;
            }
            static int __devexit at24cxx_remove(struct i2c_client *client)
            {
            printk("%s %s %dn", __FILE__, __FUNCTION__, __LINE__);
            return 0;
            }
            static const struct i2c_device_id at24cxx_id_table[] = {
            { "at24c08", 0 },
            {}
            };
            // 1. 分配/設(shè)置i2c_driver //
            static struct i2c_driver at24cxx_driver = {
            .driver = {
            .name = "100ask",
            .owner = THIS_MODULE,
            },
            .probe = at24cxx_probe,
            .remove = __devexit_p(at24cxx_remove),
            .id_table = at24cxx_id_table,
            };
            static int at24cxx_drv_init(void)
            {
            // 2. 注冊(cè)i2c_driver //
            i2c_add_driver(&at24cxx_driver);
            return 0;
            }
            static void at24cxx_drv_exit(void)
            {
            i2c_del_driver(&at24cxx_driver);
            }
            module_init(at24cxx_drv_init);
            module_exit(at24cxx_drv_exit);
            MODULE_LICENSE("GPL");
            at24cxx_dev.c源碼:
            #include "linux/kernel.h"
            #include "linux/module.h"
            #include "linux/platform_device.h"
            #include "linux/i2c.h"
            #include "linux/err.h"
            #include "linux/regmap.h"
            #include "linux/slab.h"
            static struct i2c_client *at24cxx_client;
            static const unsigned short addr_list[] = { 0x60, 0x50, I2C_CLIENT_END };
            static int at24cxx_dev_init(void)
            {
            struct i2c_adapter *i2c_adap;
            struct i2c_board_info at24cxx_info;
            memset(&at24cxx_info, 0, sizeof(struct i2c_board_info));
            strlcpy(at24cxx_info.type, "at24c08", I2C_NAME_SIZE);
            i2c_adap = i2c_get_adapter(0);
            at24cxx_client = i2c_new_probed_device(i2c_adap, &at24cxx_info, addr_list, NULL);
            i2c_put_adapter(i2c_adap);
            if (at24cxx_client)
            return 0;
            else
            return -ENODEV;
            }
            static void at24cxx_dev_exit(void)
            {
            i2c_unregister_device(at24cxx_client);
            }
            module_init(at24cxx_dev_init);
            module_exit(at24cxx_dev_exit);
            MODULE_LICENSE("GPL");
            =============================================================
            第四種方法:
            at24cxx_drv.c源碼:
            #include "linux/kernel.h"
            #include "linux/module.h"
            #include "linux/platform_device.h"
            #include "linux/i2c.h"
            #include "linux/err.h"
            #include "linux/regmap.h"
            #include "linux/slab.h"
            static int __devinit at24cxx_probe(struct i2c_client *client,
            const struct i2c_device_id *id)
            {
            printk("%s %s %dn", __FILE__, __FUNCTION__, __LINE__);
            return 0;
            }
            static int __devexit at24cxx_remove(struct i2c_client *client)
            {
            printk("%s %s %dn", __FILE__, __FUNCTION__, __LINE__);
            return 0;
            }
            static const struct i2c_device_id at24cxx_id_table[] = {
            { "at24c08", 0 },
            {}
            };
            static int at24cxx_detect(struct i2c_client *client,
            struct i2c_board_info *info)
            {
            // 能運(yùn)行到這里, 表示該addr的設(shè)備是存在的
            * 但是有些設(shè)備單憑地址無(wú)法分辨(A芯片的地址是0x50, B芯片的地址也是0x50)
            * 還需要進(jìn)一步讀寫(xiě)I2C設(shè)備來(lái)分辨是哪款芯片
            * detect就是用來(lái)進(jìn)一步分辨這個(gè)芯片是哪一款,并且設(shè)置info->type
            //
            printk("at24cxx_detect : addr = 0x%xn", client->addr);
            // 進(jìn)一步判斷是哪一款 //
            strlcpy(info->type, "at24c08", I2C_NAME_SIZE);
            return 0;
            }
            static const unsigned short addr_list[] = { 0x60, 0x50, I2C_CLIENT_END };
            // 1. 分配/設(shè)置i2c_driver //
            static struct i2c_driver at24cxx_driver = {
            .class = I2C_CLASS_HWMON, // 表示去哪些適配器上找設(shè)備 //
            .driver = {
            .name = "100ask",
            .owner = THIS_MODULE,
            },
            .probe = at24cxx_probe,
            .remove = __devexit_p(at24cxx_remove),
            .id_table = at24cxx_id_table,
            .detect = at24cxx_detect, // 用這個(gè)函數(shù)來(lái)檢測(cè)設(shè)備確實(shí)存在 //
            .address_list = addr_list, // 這些設(shè)備的地址 //
            };
            static int at24cxx_drv_init(void)
            {
            // 2. 注冊(cè)i2c_driver //
            i2c_add_driver(&at24cxx_driver);
            return 0;
            }
            static void at24cxx_drv_exit(void)
            {
            i2c_del_driver(&at24cxx_driver);
            }
            module_init(at24cxx_drv_init);
            module_exit(at24cxx_drv_exit);
            MODULE_LICENSE("GPL");
            ===============================================================
            1. 框架
            1.1 硬件協(xié)議簡(jiǎn)介
            1.2 驅(qū)動(dòng)框架
            1.3 bus-drv-dev模型及寫(xiě)程序
            a. 設(shè)備的4種構(gòu)建方法(對(duì)于以下4種方法建議使用前3種,第四種方法迫不得已情況下使用)
            a.1 定義一個(gè)i2c_board_info, 里面有:名字, 設(shè)備地址
            然后i2c_register_board_info(busnum, ...) (把它們放入__i2c_board_list鏈表)
            list_add_tail(&devinfo->list, &__i2c_board_list);
            鏈表何時(shí)使用:
            i2c_register_adapter > i2c_scan_static_board_info > i2c_new_device
            使用限制:必須在 i2c_register_adapter 之前 i2c_register_board_info
            所以:不適合我們動(dòng)態(tài)加載insmod
            a.2 直接i2c_new_device, i2c_new_probed_device
            a.2.1 i2c_new_device : 認(rèn)為設(shè)備肯定存在
            a.2.2 i2c_new_probed_device :對(duì)于"已經(jīng)識(shí)別出來(lái)的設(shè)備"(probed_device),才會(huì)創(chuàng)建("new")
            i2c_new_probed_device
            probe(adap, addr_list[i]) // 確定設(shè)備是否真實(shí)存在 //
            info->addr = addr_list[i];
            i2c_new_device(adap, info);
            a.3 從用戶(hù)空間創(chuàng)建設(shè)備
            創(chuàng)建設(shè)備
            echo at24c08 0x50 > /sys/class/i2c-adapter/i2c-0/new_device
            導(dǎo)致i2c_new_device被調(diào)用
            刪除設(shè)備
            echo 0x50 > /sys/class/i2c-adapter/i2c-0/delete_device
            導(dǎo)致i2c_unregister_device
            a.4 前面的3種方法都要事先確定適配器(I2C總線(xiàn),I2C控制器)
            如果我事先并不知道這個(gè)I2C設(shè)備在哪個(gè)適配器上,怎么辦?去class表示的所有的適配器上查找
            有上一些I2C設(shè)備的地址是一樣,怎么繼續(xù)分配它是哪一款?用detect函數(shù)
            static struct i2c_driver at24cxx_driver = {
            .class = I2C_CLASS_HWMON, // 表示去哪些適配器上找設(shè)備 //
            .driver = {
            .name = "100ask",
            .owner = THIS_MODULE,
            },
            .probe = at24cxx_probe,
            .remove = __devexit_p(at24cxx_remove),
            .id_table = at24cxx_id_table,
            .detect = at24cxx_detect, // 用這個(gè)函數(shù)來(lái)檢測(cè)設(shè)備確實(shí)存在 //
            .address_list = addr_list, // 這些設(shè)備的地址 //
            };
            去"class表示的這一類(lèi)"I2C適配器,用"detect函數(shù)"來(lái)確定能否找到"address_list里的設(shè)備",
            如果能找到就調(diào)用i2c_new_device來(lái)注冊(cè)i2c_client, 這會(huì)和i2c_driver的id_table比較,
            如果匹配,調(diào)用probe
            i2c_add_driver
            i2c_register_driver
            a. at24cxx_driver放入i2c_bus_type的drv鏈表
            并且從dev鏈表里取出能匹配的i2c_client并調(diào)用probe
            driver_register
            b. 對(duì)于每一個(gè)適配器,調(diào)用__process_new_driver
            對(duì)于每一個(gè)適配器,調(diào)用它的函數(shù)確定address_list里的設(shè)備是否存在
            如果存在,再調(diào)用detect進(jìn)一步確定、設(shè)置,然后i2c_new_device
            // Walk the adapters that are already present //
            i2c_for_each_dev(driver, __process_new_driver);
            __process_new_driver
            i2c_do_add_adapter
            // Detect supported devices on that bus, and instantiate them //
            i2c_detect(adap, driver);
            for (i = 0; address_list[i] != I2C_CLIENT_END; i += 1) {
            err = i2c_detect_address(temp_client, driver);
            // 判斷這個(gè)設(shè)備是否存在:簡(jiǎn)單的發(fā)出S信號(hào)確定有ACK //
            if (!i2c_default_probe(adapter, addr))
            return 0;
            memset(&info, 0, sizeof(struct i2c_board_info));
            info.addr = addr;
            // 設(shè)置info.type
            err = driver->detect(temp_client, &info);
            i2c_new_device
            b. 驅(qū)動(dòng)的寫(xiě)法
            2. 完善設(shè)備驅(qū)動(dòng)程序
            3. 不自己寫(xiě)驅(qū)動(dòng)直接訪(fǎng)問(wèn)
            Device Drivers
            I2C support
            <*> I2C device interface
            4. 編寫(xiě)"總線(xiàn)(適配器adapter)"驅(qū)動(dòng)
            Device Drivers
            I2C support
            I2C Hardware Bus support
            < > S3C2410 I2C Driver
            nfs 30000000 192.168.1.123:/work/nfs_root/uImage_noi2cbus; bootm 30000000


            評(píng)論


            相關(guān)推薦

            技術(shù)專(zhuān)區(qū)

            關(guān)閉