4.19作业 驱动开发

一、编程要求

  • 在内[[核中不支持浮点类型打印

  • 将si7006硬件数据读取到内核空间,拷贝到用户空间

  • 在i2c子系统驱动中,需要编写读取温湿度传感器函数

  • 在probe函数中

    • 注册字符设备驱动(分步注册)
    • 自动创建设备节点
  • 通过ioctl函数判断应用层发送命令码,是读取温度的数据还是湿度的数据

  • 编写应用层程序 公式

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/i2c.h>
    #include <linux/fs.h>
    #include <linux/device.h>

    struct i2c_client *gclient;
    unsigned int major = 0;
    #define CNAME "myled"
    struct class *cls;
    struct device *device;

    int myled_open(struct inode *inode, struct file *file)
    {
    printk("%s:%s:%d\n",FILE,func,LINE);
    return 0;
    }

    ssize_t myled_read(struct file *file, char __user *ubuf, size_t size, loff_t *loff)
    {
    printk("%s:%s:%d\n",FILE,func,LINE);
    return 0;
    }

    ssize_t myled_write(struct file *file, const char __user *ubuf, size_t size, loff_t *loff)
    {
    printk("%s:%s:%d\n",FILE,func,LINE);
    return 0;
    }

    int myled_close(struct inode *inode, struct file *file)
    {
    printk("%s:%s:%d\n",FILE,func,LINE);
    return 0;
    }

    //操作方法结构体
    const struct file_operations fops = {
    .open = myled_open,
    .read = myled_read,
    .write = myled_write,
    .release = myled_close,
    };

    //函数功能:读取电子串号和固件版本号的函数
    int read_serial_firmware(unsigned short reg)
    {
    char r_buf[] = {(reg >> 8 & 0xff),reg & 0xff};
    char value;
    int num;
    struct i2c_msg r_msg[2] = {
    [0] = {
    .addr = gclient->addr, //从机地址
    .flags = 0, //写标志位
    .len = 2, //消息长度
    .buf = r_buf, //从reg寄存器中读取数据
    },
    [1] = {
    .addr = gclient->addr, //从机地址
    .flags = 1,//读标志位
    .len = 1, //消息长度
    .buf = &value, //读取到的数据内容
    },
    };
    //发送数据
    num = i2c_transfer(gclient->adapter,r_msg,ARRAY_SIZE(r_msg));
    if(num != ARRAY_SIZE(r_msg))
    {
    printk("i2c transfer is error\n");
    return -EIO;
    }
    return value;
    }

    //当设备驱动层和总线驱动层匹配成功执行probe函数
    int si7006_probe(struct i2c_client *client, const struct i2c_device_id *id)
    {
    int ret;
    gclient = client;
    printk("%s:%s:%d\n",FILE,func,LINE);
    //读取电子串号
    ret = read_serial_firmware(0xFCC9);
    printk("serial(0x06) = %#x\n",ret);
    //读取固件版本号
    ret = read_serial_firmware(0x84B8);
    printk("fireware(0xff/0x20) = %#x\n",ret);

    复制代码
      //读取温湿度传感器协议版本号
      ret = read_serial_firmware(0xE340);
      printk("temperature(0xff/0x20)  = %#x\n",ret);
      ret = read_serial_firmware(0xE540);
      printk("Relative Humidity(0xff/0x20) = %#x\n",ret);
    
      //注册字符设备驱动
      major = register_chrdev(0,CNAME,&fops);
      if(major < 0){
          printk("register chrdev is error\n");
          return -EIO;
      }
          //向上层提交目录信息
      cls = class_create(THIS_MODULE,CNAME);
      if(IS_ERR(cls)){
          return PTR_ERR(cls);
      }
      //向上层提交设备节点信息
      device = device_create(cls,NULL,MKDEV(major,0),NULL,CNAME);
      if(IS_ERR(device)){
          return PTR_ERR(device);
      }
      printk("major = %d\n",major);//打印主设备号的值
    
      //判断读取的是温度还是湿度的数据,此处不会
      if(gclient->flags==1 && gclient->flags)
      {
          ;
      }
    
    
    
    
    
      return 0;

    }

    //当任意一方卸载,执行remove函数
    int si7006_remove(struct i2c_client *client)
    {
    //注销字符设备驱动
    unregister_chrdev(major,CNAME);
    printk("%s:%s:%d\n",FILE,func,LINE);
    return 0;
    }

    const struct of_device_id si7006_tabble[] = {
    {.compatible = "hqyj,si7006",},
    {},//防止数组越界
    };

    //初始化i2c_driver结构体
    struct i2c_driver si7006 ={
    .probe = si7006_probe,
    .remove = si7006_remove,
    .driver = {
    .name = "hello",
    .of_match_table = si7006_tabble,
    }
    };

    module_i2c_driver(si7006);
    MODULE_LICENSE("GPL");

相关推荐
乱七八糟的屋子3 小时前
AMQP C++ 超详细实战教程(amqp-cpp 开源库从零入门到生产落地)
c++·rabbitmq·任务队列·amqp·流量削峰·c++服务端异步解耦·分布式消息通信
余—笙19 小时前
Docker安装rabbitmq并安装延迟队列插件
docker·容器·rabbitmq
稚南城才子,乌衣巷风流4 天前
RabbitMQ 消息队列:从入门到实战
分布式·rabbitmq
过期动态5 天前
【LeetCode 热题 100】找到字符串中所有字母异位词
java·数据结构·算法·leetcode·职场和发展·rabbitmq
YDS8297 天前
大营销平台 —— 活动SKU库存扣减业务及其一致性处理
java·spring boot·redis·rabbitmq·ddd
霸道流氓气质7 天前
Kiro 中配置 RabbitMQ MCP Server 指南
分布式·rabbitmq·ruby
quweiie8 天前
tp8使用rabbitMQ消息队列的示例
消息队列·rabbitmq·thinkphp消息队列
六点_dn8 天前
RabbitMQ学习笔记-定义与作用
笔记·学习·rabbitmq
Steadfast_GG10 天前
RabbitMQ升级打怪之路(1) - RabbitMQ概述
消息队列·rabbitmq·流量削峰·消息分发·异步解耦
时代的狂11 天前
RabbitMQ 面试问答
分布式·面试·rabbitmq