zoukankan      html  css  js  c++  java
  • I2C驱动框架(kernel-2.6.22.6)

    以用i2c通信的实时时钟为例

    框架入口源文件:i2c_m41t11.c

    (可根据入口源文件,再按着框架到内核走一遍)

    内核版本:linux_2.6.22.6   硬件平台:JZ2440


    以下是驱动框架:


    以下是驱动代码 i2c_m41t11.c :

    #include <linux/kernel.h>
    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/slab.h>
    #include <linux/jiffies.h>
    #include <linux/i2c.h>
    #include <linux/mutex.h>
    #include <linux/fs.h>
    
    
    
    static unsigned short normal_i2c[] = {0x68,I2C_CLIENT_END}; //只有七位   0xd0 >> 1
    static unsigned short probe[] = {I2C_CLIENT_END};
    static unsigned short ignore[] = {I2C_CLIENT_END};
    
    //定义一个 client 地址数据
    static struct i2c_client_address_data addr_data =
    {
        .normal_i2c = normal_i2c,
        .probe      = probe,
        .ignore     = ignore, 
    };
    
    //定义 client 
    static struct i2c_client *i2c_m41t11_client;
    
    //定义 主设备号
    static int major;
    
    //定义一个 i2c 字符驱动
    static struct i2c_driver i2c_m41t11_driver;
    
    static ssize_t i2c_m41t11_read(struct file *file, char __user *buf, size_t size, loff_t * offset)
    {
      printk(" <========= this is m41t11 RTC chip =========>  
    ");
      return 0;
    }
    
    
    static ssize_t i2c_m41t11_write(struct file *file, const char __user *buf, size_t size, loff_t * offset)
    {
        printk(" <========== this is m41t11 RTC chip =========> 
    ");
        return 0;
    }
    
    
    //定义字符操作函数
    static struct file_operations i2c_m41t11_fops =
    {
       .owner = THIS_MODULE,
       .read  = i2c_m41t11_read,
       .write = i2c_m41t11_write,
    };
    
    
    
    //定义一个字符设备类
    static struct class *i2c_m41t11_class;
    
    
    //匹配处理函数
    static int m41t11_match_fun(struct i2c_adapter* adpater,int addr ,int kind)
    {
       printk("match m41t11 RTC chip successfully 
    "); 
       //初始化 client 结构体
       i2c_m41t11_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
       i2c_m41t11_client->adapter =  adpater;
       i2c_m41t11_client->driver = &i2c_m41t11_driver;
       i2c_m41t11_client->addr   = addr;
       strcpy(i2c_m41t11_client->name, "i2c_m41t11_client");
       i2c_attach_client(i2c_m41t11_client);
    
       //注册字符设备
        major = register_chrdev(0,"i2c_m41t11", &i2c_m41t11_fops); 
     
        i2c_m41t11_class = class_create(THIS_MODULE,"i2c_m41t11_class");                     //   /sys/class/i2c_m41t11_class
        class_device_create(i2c_m41t11_class, NULL, MKDEV(major, 0), NULL,"i2c_m41t11_dev"); //   /dev/i2c_m41t11_dev
        return 0;
    }
    
    
    static int i2c_m41t11_attach(struct i2c_adapter *adapter)
    {
    
       printk("trying to match  m41t11 RTC chip 
    ");
    
      return   i2c_probe( adapter , &addr_data , m41t11_match_fun );
    } 
    
    static int i2c_m41t11_detach(struct i2c_client *client)
    {
        printk("delect  m41t11 RTC chip 
    ");
       //字符设备
        unregister_chrdev(major, "i2c_m41t11");
        class_destroy(i2c_m41t11_class);
        class_device_destroy(i2c_m41t11_class,MKDEV(major, 0));
           
        //client
        i2c_detach_client(client);
        kfree(i2c_get_clientdata(client));    
        return 0;
    }
    
    //初始化 i2c_m41t11_driver
    static struct i2c_driver i2c_m41t11_driver =
    {
        .driver = { .name = "i2c_m41t11", },
        .attach_adapter = i2c_m41t11_attach,
        .detach_client  = i2c_m41t11_detach,
    };
    
    
    static int i2c_m41t11_init(void)
    {
        i2c_add_driver(&i2c_m41t11_driver);
        return 0;
    }
    
    
    static void i2c_m41t11_exit(void)
    {
       i2c_del_driver(&i2c_m41t11_driver);
    }
        
    
    module_init(i2c_m41t11_init);
    module_exit(i2c_m41t11_exit);
    
    MODULE_LICENSE("GPL");

     注:

            匹配分为三个个步骤
       1. 用驱动的i2c_driver.driver.name与物理设备名字匹配,成功则调用 i2c_driver.attach_adapter。

       2. i2c_driver.attach_adapter中用i2c_probe(adapter,addr,match_func)匹配适配器与物理设备,成功则调用 match_func。

       3. match_func中创建 i2c_client,将 i2c_driver 与 i2c_adapter 联系起来。


    以下是编译驱动的Makefile:

    KER_DIR=/work/systems/kernel/linux-2/linux-2.6.22.6
    all:
    make -C $(KER_DIR) M=`pwd` modules
    clean:
    make -C $(KER_DIR) M=`pwd` modules clean
    rm -fr modules.order

    obj-m += i2c_m41t11.o

  • 相关阅读:
    Java基础算法--排序
    Java基础之String类的细节问题
    Java数据结构四之——二叉树的前、中、后序遍历
    动态规划之----最长公共子序列(LCS)
    最长公共子串问题
    makefile学习笔记
    使用正则表达式,去除C++的注释
    gbk字库音序对照表
    Fsharp 类中的空字段
    使用FSharp 探索Dotnet图像处理功能2--均衡灰度
  • 原文地址:https://www.cnblogs.com/zsy12138/p/10392810.html
Copyright © 2011-2022 走看看