IIC专题(二)-使用内核原代码提供的at24.c驱动来操作I2C的at24lc04 EEPROM

来源:互联网 发布:日本交换 知乎 编辑:程序博客网 时间:2024/06/10 14:34

前面第一篇已经讲了有关IIC的相关知识这边就不再重复,

本篇我们使用内核原代码提供的at24.c驱动来操作I2C的at24lc04 EEPROM

内核I2C子系统的架构请参考第一篇文章,这边只讲at24.c相关的部份


接下来因为驱动使用的是内核 at24.c 文件当然得先分析一下该文件

首先看到的是ar24.c驱动支持的设备

static const struct i2c_device_id at24_ids[] = {/* needs 8 addresses as A0-A2 are ignored */{ "24c00", AT24_DEVICE_MAGIC(128 / 8, AT24_FLAG_TAKE8ADDR) },/* old variants can't be handled with this generic entry! */{ "24c01", AT24_DEVICE_MAGIC(1024 / 8, 0) },{ "24c02", AT24_DEVICE_MAGIC(2048 / 8, 0) },/* spd is a 24c02 in memory DIMMs */{ "spd", AT24_DEVICE_MAGIC(2048 / 8,AT24_FLAG_READONLY | AT24_FLAG_IRUGO) },{ "24c04", AT24_DEVICE_MAGIC(4096 / 8, 0) },/* 24rf08 quirk is handled at i2c-core */{ "24c08", AT24_DEVICE_MAGIC(8192 / 8, 0) },{ "24c16", AT24_DEVICE_MAGIC(16384 / 8, 0) },{ "24c32", AT24_DEVICE_MAGIC(32768 / 8, AT24_FLAG_ADDR16) },{ "24c64", AT24_DEVICE_MAGIC(65536 / 8, AT24_FLAG_ADDR16) },{ "24c128", AT24_DEVICE_MAGIC(131072 / 8, AT24_FLAG_ADDR16) },{ "24c256", AT24_DEVICE_MAGIC(262144 / 8, AT24_FLAG_ADDR16) },{ "24c512", AT24_DEVICE_MAGIC(524288 / 8, AT24_FLAG_ADDR16) },{ "24c1024", AT24_DEVICE_MAGIC(1048576 / 8, AT24_FLAG_ADDR16) },{ "at24", 0 },{ /* END OF LIST */ }};

我们24c04是在列表中的,总共有4096位/8 = 512字节

在初始化驱动时有这样的代码片段

static struct i2c_driver at24_driver = {.driver = {.name = "at24",.owner = THIS_MODULE,},.probe = at24_probe,.remove = __devexit_p(at24_remove),.id_table = at24_ids,};static int __init at24_init(void){if (!io_limit) {pr_err("at24: io_limit must not be 0!\n");return -EINVAL;}io_limit = rounddown_pow_of_two(io_limit);return i2c_add_driver(&at24_driver);}

也就是说这是采用总线的驱动,总线的过程是当有设备加入总线,会调用驱动的 probe 方法来捕获设备,

驱动已经实现了probe 方法剩下的是得把我们的设备加入总线,寻找smart210的设备加入总线的操作部分,

发现坑人的是明明是 smart210 应该是s5kv210的核心结果对应到的文件居然是 Mach-mini210.c 而不是Mach-smdkv210.c

找到该文件加入以下的代码

//add by yang#include <linux/i2c.h>#include <linux/i2c/at24.h>
以上是使用at24.c 的头文件

//add by yangstatic struct at24_platform_data at24c04 = {.byte_len = 4096 / 8,.page_size = 16,.flags = 0,};static struct i2c_board_info  __initdata smdkv210_i2c_devices[] = {        {                I2C_BOARD_INFO("24c04", 0x50),                .platform_data  = &at24c04,        },};
这个是我们设备的描述,因为at24.c是对应多种设备的,所以需要加上板载的一些资讯,

然后找到mini210_machine_init 这个函数将上面的设备信息加入总线

static void __init mini210_machine_init(void){arm_pm_restart = smdkc110_pm_restart;  .....这边省略一堆代码.....
#ifdef CONFIG_TOUCHSCREEN_GOODIXif (mini210_get_ctp() == CTP_GT80X) {i2c2_data.frequency = 260*1000;}#endif//add by yangi2c_register_board_info(0, smdkv210_i2c_devices,ARRAY_SIZE(smdkv210_i2c_devices));s3c_i2c2_set_platdata(&i2c2_data);i2c_register_board_info(0, mini210_i2c_devs0,ARRAY_SIZE(mini210_i2c_devs0));i2c_register_board_info(1, mini210_i2c_devs1,ARRAY_SIZE(mini210_i2c_devs1));i2c_register_board_info(2, mini210_i2c_devs2,ARRAY_SIZE(mini210_i2c_devs2));....下面省略一堆代码.......
主要将刚刚定义好的设备描述加入总线

最后检查一下内核中的EEPROM支持是否已经开启

内核中的eeprom没打开,请先到内核配置以下选项

Device Drivers  --->

[*] Misc devices  --->

EEPROM support  --->

<*>I2C EEPROMs from most vendors

重新编译下载内核之后可以发现在 /sys/bus/i2c/devices/0-0050/ 目录下应该要有 eeprom 设备文件

这样就算准备就绪



最后实现应用程序代码如下
/************************************************ 档名:i2c_app.c* 作者:yang@wapoop.com* 日期:2016/10/13* 描述:使用Linux内核提供的at24.c驱动读写板载AT24C04************************************************/#include <stdio.h>#include <fcntl.h>#include <sys/ioctl.h>#include <linux/types.h>#include <unistd.h>int main(){int fd;int i;char write_data[8] = {0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,0x40};char read_data[256] = {0};fd = open("/sys/bus/i2c/devices/0-0050/eeprom",O_RDWR);for(i=0;i<8;i++)write_data[i] = i;        //使用lseek来定位数据地址lseek(fd,0,SEEK_SET);write(fd,write_data,8);lseek(fd,0,SEEK_SET);read(fd,read_data,256);for(i=0;i<256;i++){if(i%16 == 0)printf("\n");printf("%02x ",read_data[i]);}printf("\n");}



0 0
原创粉丝点击