当前位置: 首页 > news >正文

学网站建设难吗青岛官网seo公司

学网站建设难吗,青岛官网seo公司,手机网站 切图,无印良品vi设计分析文章目录1. 前言2. i2c-dev驱动的注册过程3. open_i2c_dev函数分析4. set_slave_addr函数分析5. i2c_read_bytes函数分析1. 前言 前面分析i2c-tool测试工具就是基于drivers/i2c/i2c-dev.c驱动来实现的。i2c-dev驱动在加载时会遍历所有的I2C总线(i2c_bus_type)上所有注册的adap…

文章目录

  • 1. 前言
  • 2. i2c-dev驱动的注册过程
  • 3. open_i2c_dev函数分析
  • 4. set_slave_addr函数分析
  • 5. i2c_read_bytes函数分析

1. 前言

前面分析i2c-tool测试工具就是基于drivers/i2c/i2c-dev.c驱动来实现的。i2c-dev驱动在加载时会遍历所有的I2C总线(i2c_bus_type)上所有注册的adapter,并且在linux系统创建对应的字符设备,如:/dev/i2c-0/dev/i2c-1/dev/i2c-2等。应用程序通过open打开对应的i2c字符设备,通过ioctl来收发数据。具体的架构如下图:
在这里插入图片描述

2. i2c-dev驱动的注册过程

i2c-dev.c的驱动入口i2c_dev_init函数具体操作如下:

  1. register_chrdev_region:注册i2c字符设备
  2. class_create:创建i2c-dev的class,为在linux文件系统中创建字符设备做准备。
  3. i2cdev_attach_adapter:通过函数i2c_for_each_dev遍历已经绑定的adapter,有多少个adapter就调用i2cdev_attach_adapter函数几次。
    在这里插入图片描述
  4. to_i2c_adapter:通过dev获取对应的i2c adapter
  5. cdev_init:它会初始化一个重要的结构体,file_operations。
  6. dev_set_name:设置device name为i2c-x,也就是我们在字符设备创建成功后看到的/dev/i2c-x设备。
  7. cdev_device_add:添加设备到系统,并且创建对应的字符设备到用户空间。
    在这里插入图片描述

备注:
cdev_device_add这里其实调用了cdev_add和device_add。然而,device_create()是device_register()的封装,而device_register()则是device_add()的封装。

3. open_i2c_dev函数分析

open_i2c_devi2c-tool工具open i2c-dev驱动的函数,根据传递的参数最终重要函数应该如下:
file = open("/dev/i2c-0", O_RDWR);
该函数的主要代码如下:

/* File Path = i2c-tools-4.3/tools/i2cbusses.c */
int open_i2c_dev(int i2cbus, char *filename, size_t size, int quiet)
{int file, len;len = snprintf(filename, size, "/dev/i2c/%d", i2cbus);if (len >= (int)size) {fprintf(stderr, "%s: path truncated\n", filename);return -EOVERFLOW;}file = open(filename, O_RDWR);if (file < 0 && (errno == ENOENT || errno == ENOTDIR)) {len = snprintf(filename, size, "/dev/i2c-%d", i2cbus);if (len >= (int)size) {fprintf(stderr, "%s: path truncated\n", filename);return -EOVERFLOW;}file = open(filename, O_RDWR);}...return file;
}

应用层调用open后,会对应调用i2c-dev通用驱动的open函数。主要是如下几个步骤:

  1. to_i2c_adapter:通过minor次设备号,其实这里等同于i2c总线编号。通过它来获取对应总线的adapter。
  2. kzalloc:申请一个i2c client表示I2C设备,并且初始化该client的name和保存adapter与其建立联系。但是,整个open函数这里没有对I2C地址进行初始化。
  3. file->private_data:通过private_data保存申请的client地址,为了后面read/write/ioctl可以通过file->private_data很方便的拿到当前dev的client。
/* File Path = kernel/drivers/i2c/i2c-dev.c */
static int i2cdev_open(struct inode *inode, struct file *file)
{unsigned int minor = iminor(inode);struct i2c_client *client;struct i2c_adapter *adap;adap = i2c_get_adapter(minor);if (!adap)return -ENODEV;/* This creates an anonymous i2c_client, which may later be* pointed to some address using I2C_SLAVE or I2C_SLAVE_FORCE.** This client is ** NEVER REGISTERED ** with the driver model* or I2C core code!!  It just holds private copies of addressing* information and maybe a PEC flag.*/client = kzalloc(sizeof(*client), GFP_KERNEL);if (!client) {i2c_put_adapter(adap);return -ENOMEM;}snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr);client->adapter = adap;file->private_data = client;return 0;
}

4. set_slave_addr函数分析

open_i2c_devi2c-tool工具来设置I2C的设备地址。具体代码如下:

/* File Path = i2c-tools-4.3/tools/i2cbusses.c */
int set_slave_addr(int file, int address, int force)
{/* With force, let the user read from/write to the registerseven when a driver is also running */if (ioctl(file, force ? I2C_SLAVE_FORCE : I2C_SLAVE, address) < 0) {fprintf(stderr,"Error: Could not set address to 0x%02x: %s\n",address, strerror(errno));return -errno;}return 0;
}

应用层调用ioctl I2C_SLAVE_FORCE后,会对应调用i2c-dev通用驱动对应的ioctl I2C_SLAVE_FORCE。主要是如下2个步骤:

  1. client = file->private_data:从private_data中获取当前I2C设备。
  2. client->addr = arg:设置当前I2C设备的地址信息,方便后面的read/write操作I2C设备。
/* File Path = kernel/drivers/i2c/i2c-dev.c */
static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{struct i2c_client *client = file->private_data;unsigned long funcs;switch (cmd) {case I2C_SLAVE:case I2C_SLAVE_FORCE:if ((arg > 0x3ff) ||(((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))return -EINVAL;if (cmd == I2C_SLAVE && i2cdev_check_addr(client->adapter, arg))return -EBUSY;/* REVISIT: address could become busy later */client->addr = arg;return 0;...
}

5. i2c_read_bytes函数分析

i2c_read_bytes这个函数是我自己写的demo code,这里只列了read部分来分析,完整的demo code可以查看上一篇我的博客。主要是如下2个步骤:

  1. struct i2c_msg messages[2]:定义2个i2c_msg的消息体,并且初始化它。它包含了:I2C的从机设备地址、read/write的flag、数据的长度、存放数据的地址。msg[0]主要是为了发送需要读取从机的哪个寄存器,msg[1]主要的配置读取的数据长度的和存放数据的地址。
  2. struct i2c_rdwr_ioctl_data packets:它主要是存放i2c_msg消息地址和i2c_msg消息个数。
  3. ioctl:通过ioctl发送到内核。
static int i2c_read_bytes(int fd, uint8_t slave_addr, uint8_t reg_addr, uint8_t *values, uint8_t len)
{uint8_t outbuf[1];struct i2c_rdwr_ioctl_data packets;struct i2c_msg messages[2];outbuf[0] = reg_addr;messages[0].addr = slave_addr;messages[0].flags = 0;messages[0].len = sizeof(outbuf);messages[0].buf = outbuf;/* The data will get returned in this structure */messages[1].addr = slave_addr;messages[1].flags = I2C_M_RD/* | I2C_M_NOSTART*/;messages[1].len = len;messages[1].buf = values;/* Send the request to the kernel and get the result back */packets.msgs = messages;packets.nmsgs = 2;if(ioctl(fd, I2C_RDWR, &packets) < 0){printf("Error: Unable to send data");return -1;}return 0;
}

应用层调用ioctl I2C_RDWR后,会对应调用i2c-dev通用驱动对应的ioctl I2C_RDWR。它将应用层的数据到拷贝的内核,具体如下:

/* File Path = kernel/drivers/i2c/i2c-dev.c */
case I2C_RDWR: {struct i2c_rdwr_ioctl_data rdwr_arg;struct i2c_msg *rdwr_pa;//从用户空间拷贝数据到内核空间copy_from_user(&rdwr_arg,(struct i2c_rdwr_ioctl_data __user *)arg,sizeof(rdwr_arg));//分配一块内存空间,将用户空间的数据拷贝进去rdwr_pa = memdup_user(rdwr_arg.msgs, rdwr_arg.nmsgs * sizeof(struct i2c_msg));return i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa);
}static int i2cdev_ioctl_rdwr(struct i2c_client *client, unsigned nmsgs, struct i2c_msg *msgs)
{***res = i2c_transfer(client->adapter, msgs, nmsgs);***
}

总结:其实应用层初始化的i2c_msg就是直接给内核i2c_transfer将I2C消息发送出去的。

http://www.hkea.cn/news/262470/

相关文章:

  • 制作网站项目流程无锡网站建设seo
  • 最好的开发网站建设价格如何搜索网页关键词
  • 做网站犯法了 程序员有责任吗网站建设合同
  • 建设部职称网站关键词优化营销
  • 做seo还要需要做网站吗百度热搜榜排行
  • 福建城市建设厅网站怎么推广一个网站
  • 机构网站建设需要交费吗关键词挖掘
  • 专业网站建设费用报价今日最新消息
  • 电商网站建设论文2022黄页全国各行业
  • 能源企业 网站建设网络营销的应用
  • 如何看网站是用什么语言做的关键词排名是由什么决定的
  • 政府网站建设招标书百度网站收录
  • 已经有了网站怎么做推广哈尔滨关键词优化报价
  • 网站建设与管理作业镇江推广公司
  • 域名申请好后 如何建设网站网站权重划分
  • 佛山百度网站快速优化网络营销推广工具
  • 建一个网站需要哪些人广州seo网站推广公司
  • 建设银行etc官方网站搜索引擎优化的七个步骤
  • 做网站需要花钱吗海南百度推广运营中心
  • 做的网站显示图片很慢百度运营公司
  • 青州哪里做网站公司推广渠道
  • 网站面包屑导航怎么做的网推接单平台有哪些
  • 宜昌网站建设兼职百度关键词排名软件
  • 如何让百度快照找到自己的网站营销策划方案ppt模板
  • php网站超市广告软文是什么意思
  • b2c跨境电商宣城网站seo
  • 网站建设一流公司免费网站开发平台
  • 网站开发模式名词外贸谷歌优化
  • 网站素材 下载产品推广渠道
  • 网站后台维护怎么做seo专员工资一般多少