成员。我们可以看到消息结构体里面有从设备地址,读写标志,数据长度以及存储数据buf。这些成员我们看完之后会发现它大致符合先给设备地址,然后给写信号以及数据的时序。其实但我们写代码的时候并不一定是addr非得定义在flags前面,因为内核会自动帮助我们完成这些具体的时序操作。但有一点,我们必须要填充好nmsgs以及i2c_msg中的成员。

那么我们具体的i2c下的 ioctl 函数是怎么样的呢?我们暂且把i2c-dev.c看作一个设备驱动。里面的fops结构体显示

我们继续追踪看看i2cdev_ioctl这个函数

static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)

{

struct i2c_client *client = file->private_data;

unsigned long funcs;

dev_dbg(&client->adapter->dev, "ioctl, cmd=0x%02x, arg=0x%02lx\n",

cmd, arg);

switch (cmd) {

case I2C_SLAVE:

case I2C_SLAVE_FORCE:

/* NOTE:  devices set up to work with "new style" drivers

* can't use I2C_SLAVE, even when the device node is not

* bound to a driver.  Only I2C_SLAVE_FORCE will work.

*

* Setting the PEC flag here won't affect kernel drivers,

* which will be using the i2c_client node registered with

* the driver model core.  Likewise, when that client has

* the PEC flag already set, the i2c-dev driver won't see

* (or use) this setting.

*/

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; //设置addr

return 0;

case I2C_TENBIT://设置10 bit地址模式

if (arg)

client->flags |= I2C_M_TEN;

else

client->flags &= ~I2C_M_TEN;

return 0;

case I2C_PEC://设置传输后增加PEC标志

if (arg)

client->flags |= I2C_CLIENT_PEC;

else

client->flags &= ~I2C_CLIENT_PEC;

return 0;

case I2C_FUNCS://获取函数支持

funcs = i2c_get_functionality(client->adapter);

return put_user(funcs, (unsigned long __user *)arg);

case I2C_RDWR://读取和发送数据

return i2cdev_ioctl_rdrw(client, arg);

case I2C_SMBUS: //SMBUS协议数据传输

return i2cdev_ioctl_smbus(client, arg);

case I2C_RETRIES://设置重试次数

client->adapter->retries = arg;

break;

case I2C_TIMEOUT://设置超时时间

/* For historical reasons, user-space sets the timeout

* value in units of 10 ms.

*/

client->adapter->timeout = msecs_to_jiffies(arg * 10);

break;

default:

/* NOTE:  returning a fault code here could cause trouble

* in buggy userspace code.  Some old kernel bugs returned

* zero in this case, and userspace code might accidentally

* have depended on that bug.

*/

return -ENOTTY;

}

return 0;

}

对于简单使用来说,我现在并没有全深入整明白,所以暂且知道:

ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。

在驱动程序中实现的ioctl函数体内,实际上是有一个switch{case}的结构,每一个case对应一个cmd操作命令,并有相对应的操作。

我这里cmd参数使用的是I2C_RDWR这个命令码,根据i2c-dev.c里的源码看i2cdev_ioctl_rdrw结构体可知

I2C 设备的写操作经历了如下几个步骤。

(1) 从用户空间到字符设备驱动写函数接口,写函数构造 I2C 消息数组。

(2) 写函数把构造的 I2C 消息数组传递给 I2C 核心的传输函数 i2c_transfer()。

(3) I2C 核心的传输函数 i2c_transfer()找到对应适配器 algorithm 的通信方法函数 master_xfer()去最终完成 I2C 消息的处理。

PS:I2c_transfer这个函数实现了core与adapter的联系。想更深入的探究,可以自己去看看I2C总线驱动中的I2C_algorithm结构以及其中的s3c24xx_i2c_xfer(),s3c24xx_i2c_doxfer()和s3c24xx_i2c_message_start()函数和i2c_transfer()函数。

下面我们看看代码在开发板中运行的现象:

1.在把可执行文件放入开发板启动之前我们先检查下I2C控制器s3c2410-i2c节点是否配置好。

上面的i2c_dev/i2c-0是在注册i2c-dev.c后产生的,代表一个可操作的适配器。如果不使用i2c-dev.c的方式,就没有,也不需要这个节点。

2.确保出现I2C控制器s3c2410-i2c后即可通过交叉编译器将编译后可执行文件放入开发板中执行。

仔细看上面的结果。可以看到我们原本的数据test1234\n在上面的显示中出了点问题。后来我又测试一次test123\n与test12345678

我第一次是通过at24.c的read和write以及lseek直接对eeprom读写,所以可以一次写入超过8个字节,第二次通过内部i2c控制器的ioctl来间接读写eeprom时则遭遇了阻击,一次时序,若超过8个字节,超过的字节数自动将前面的数据覆盖掉。然后我想到at24c02是32个页,一页8个字节。通过网上查阅知:

===================================================================================================

================================================================================================================================

由于E2PROM的半导体工艺特性,对E2PROM的写入时间要5~10ms,但AT24CXX系列串行E2PROM芯片内部设置了一个具有SRAM性质的输入缓冲器,称为页写缓冲器。CPU对该芯片写操作时,AT24CXX系列芯片先将CPU输入的数据暂存页写缓冲器内,然后,慢慢写入E2PROM中。因此,CPU对AT24CXX系列E2PROM一次写入的数据,受到该芯片页写缓冲器容量的限制。页写缓冲器的容量:AT24C01A/02为8B,AT24C04/08/16为16B,AT24C32/64为32B。

====================================================================================================

注意:

写AT24CXX应用时,若CPU需写入超过芯片页写缓冲器容量的字节数据,应在一页写完后,隔5~10ms重新启动一次写操作。其次,若不是从页写缓冲器零地址(指AT24CXX片内末位地址0或8)写起,一次写入不能超出页内地址111,若超出页写缓冲器最大地址时,也应将超出部分,隔5~10ms重新启动一次写操作。

最后通我们回顾AT24C02的官方datasheet来看看本质:

Byte write:

==================================================================================================================

Byte write的操作时序如上图所示。主机在发送device address,并且接受到确定回应Ask后再接着发送需要写的地址(把这个数据写到芯片的哪个地址上),然后收到确定回应ask后再发送数据。当AT24C02接受完毕这个数据时会输出一个确认回应Ack,此时主机发送一个停止信号Stop,然后AT240C2进入写时序,将刚才接受到的数据从缓冲器写到存储单元中,并在此期间不响应任何输入,直到操作完成。

==================================================================================================================

Pagewrite:

==================================================================================================================

Page write前面几步的操作和Bytewrite操作类似,只是在成功发送第一个数据之后,主机在收到AT24C02的确认回应Ask之后不会发送停止信号Stop而是继续发送剩余的7个字节数据。直到一个page的8字节数据发送完毕之后才发送停止信号Stop。在页操作的时候word address用与表示业内的低地址的低3bit会每收到一个数据就自动增长,页地址维持不变。所以,当业内地址到顶端时,此时假如还有数据,则数据将会被放到页的起始地址处,页起始地址中之前存放的数据也将会被覆盖。即AT24C02页操作时,写入的数据大于8byte,则大于8byte的数据将重新从此页起始处存放,并覆盖掉之前写入的的数据

==================================================================================================================

另外我们再说一下随机读取:

==================================================================================================================

随机读写的操作就是主机先用一个写操作来骗过AT24C02器件,使AT24C02内部的data word address中的地址值修改,然后再通过current ad

[1] [2] [3] [4]

本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

linux 下i2c读写命令,S3C2440 Linux下的I2C驱动以及I2C体系下对EEPROM进行读写操作相关推荐

  1. linux清空垃圾箱的命令,在Linux系统下安装Autotrash并使用Autotrash自动清空垃圾箱...

    本文介绍在Linux操作系统上自动清空垃圾箱的方法,在Ubuntu/Debian/Arch Linux/Fedora/OpenSUSE系统下安装Autotrash,并使用它为所有用户清空垃圾. 前言 ...

  2. linux定时执行任务命令,crontab(linux下定时执行任务命令)

    在linux在可以通过在脚本里(列如sh)写如日常需要进行的操作,然后通过crontab定时运行脚本. Linux下的任务调度分为两类,系统任务调度和用户任务调度. 系统任务调度:系统周期性所要执行的 ...

  3. expand linux,Expand和Unexpand命令在Linux下的使用示例

    本文通过实际示例解释两个Linux命令,即Expand和Unexpand,这两个命令用于替换具有SPACE字符的文件中的TAB字符,反之亦然.在MS-DOS中还有一个名为"Expand&qu ...

  4. linux下的zz命令,[zz]Linux下压缩命令

    一.Linux下和windows下的压缩文件的几个说明 在Windows下最常见的压缩文件就只有两种,一是,zip,另一个是.rar.可是Linux就不同了,它有.gz..tar.gz.tgz. bz ...

  5. linux删除目录或文件命令行,Linux删除目录下的文件的10种方法小结

    看到了一遍文章,便突发奇想的想起Linux中删除目录下的所有文件的方法:整理了几个,如有不足,还望读者不吝赐教! 删除当前目录下的文件 1.rm -f * #最经典的方法,删除当前目录下的所有类型的文 ...

  6. linux 获取ip地址命令行,linux获取ip_shell命令获取linux下eth0的IP地址

    摘要 腾兴网为您分享:shell命令获取linux下eth0的IP地址,我画你猜,万豪金业,调音器,时光机器等软件知识,以及usb2.0webcamera,蚂蚁,粤菜菜谱,怪物闹钟,帮我吧,英文小说, ...

  7. Mac 下使用ll命令(linux 自定义命令bash)

    Mac 下使用ll命令(自定义命令bash)_index_ling的博客-CSDN博客 1.打开文件bash_profile vim ~/.bash_profile 2.键入命令别名,保存退出 ali ...

  8. linux服务器性能查看命令,查看Linux服务器性能的日常命令和工具大全

    通过使用以下命令和工具,可以在1分钟内对系统资源使用情况有个大致的了解uptime dmesg | tail vmstat 1 mpstat -P ALL 1 pidstat 1 iostat -xz ...

  9. linux卸载cf卡命令,嵌入式Linux 中CF卡的驱动和管理技术研究

    在嵌入式Linux系统中,为了在没有PCMCIA控制器的情况下仍然要利用CompactFlash存储卡(简称CF卡)作为存储设备,作者从CF卡的硬件特性入手,在系统层基于CF卡的memory寻址访问方 ...

最新文章

  1. slice,substring,substr的区别
  2. 首款鸿蒙p系om统终端,华为全力赋能:首款鸿蒙系统终端荣耀智慧屏,距离上市销售倒计时...
  3. 计算机在外语专业中有哪些应用,CALL(3):计算机在外语教学中的应用
  4. Apache-Guacamole windows11 远程控制
  5. js 控制浏览器窗口大小
  6. 对编码通俗易懂的介绍
  7. pom报错如何解决(org.apache.maven.archiver.mavenarchiver.getmanifest)
  8. 深度学习之 RBF神经网络
  9. 汇编语言指令用法大全
  10. 计算机主机频率单位,计算机常见计量单位解析
  11. C语言:正负交替的问题
  12. unity android 播放器,Unity3D 安卓视频播放插件 WRP Android Video Player Pro
  13. 三菱IO模块QH42P使用方法
  14. 攒机笔记十二:路由器
  15. #define s(x) x*x 的计算方法
  16. 让机器认知中文实体 — 复旦大学知识工场发布中文实体识别与链接服务
  17. 智慧渣土运输管控系统
  18. 【考研数学】九. 无穷级数
  19. c#方向联蔚数科一面面经
  20. 对开发框架的浅显认识

热门文章

  1. 快捷方式修复_Mac上的屏幕截图不起作用该如何修复?
  2. python static函数_python函数怎么实现static变量?
  3. java settings文件夹_windows下打开.m2文件夹,没有找到setting.xml
  4. c语言程序设计基础1千克,c语言学习知识编程经典编辑题汇总整编.doc
  5. 如何允许网页中的编辑器访问剪切板_Vditor下一代的 Markdown 编辑器,为未来而构建...
  6. python制作收费标准_在Python中做一次简单定制1
  7. java webservice 身份验证_java-Http基本身份验证不适用于Spring WS和WebS...
  8. layui轮播图切换会有跳动_Layui中轮播图切换函数说明
  9. 服务器将office转pdf文件,Windows服务-Office转PDF文件
  10. 番茄花园win11 32位官方纯净版镜像v2021.07