内核版本:linux-2.6.32.2 实验平台:mini2440
1. 添加主控设备支持
i2c主控制器也是一个设备,只是在内核被虚拟成了一个平台设备,平台设备在内核中已经被定义了,定义在plat-s3c/dev-i2c0.c中:
static struct resource s3c_i2c_resource[] = {
[0] = {
.start = S3C_PA_IIC,
.end = S3C_PA_IIC + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_IIC,
.end = IRQ_IIC,
.flags = IORESOURCE_IRQ,
},
};
struct platform_device s3c_device_i2c0 = {
.name = "s3c2410-i2c",
#ifdef CONFIG_S3C_DEV_I2C1
.id = 0,
#else
.id = -1,
#endif
.num_resources = ARRAY_SIZE(s3c_i2c_resource),
.resource = s3c_i2c_resource,
};
那么我只需要将这个平台设备添加到mini2440_devices这个数组里面,最终这个平台设备将被注册到内核中。
2. 添加主控驱动支持
主控制器驱动为drivers/i2c/busses/i2c-s3c2410.c,那么我们只需要配置一下就可以了:
Device Drivers --->
<*> I2C support --->
I2C Hardware Bus support --->
<*> S3C2410 I2C Driver
3. at24c08 i2c设备的注册
这里使用i2c_register_board_info()函数来注册i2c设备,首先是使用I2C_BOARD_INFO宏来定义i2c设备信息:
static struct at24_platform_data at24_platdata = {
.byte_len = 8192,
.page_size = 16,
};
static struct i2c_board_info mini2440_i2c_devices[] = {
{
I2C_BOARD_INFO("24c08", 0x50),
.platform_data = &at24_platdata,
}
};
mini2440上at24c08的i2c地址为0x50,并且是挂载到i2c0上的,在mini2440_machine_init去完成注册:
i2c_register_board_info(0, mini2440_i2c_devices, ARRAY_SIZE(mini2440_i2c_devices));
其中的第一个参数需要注意,为i2c的总线号。
最后还需要注意别忘了包含这两个头文件:
4. at24c08驱动支持 驱动代码就用默认的drivers/misc/eeprom/at24.c,配置如下: Device Drivers ---> [*] Misc devices ---> EEPROM support ---> -*- I2C EEPROMs from most vendors 5. 验证 那么怎么去验证我们添加的i2c驱动和i2c设置是匹配成功的了呢,进入到这个目录下:/sys/bus/i2c/drivers/at24,然后可以看到一个文件0-0050,说明i2c驱动和i2c设备是匹配成功了的。 //2016.3.27 add linux自带的eeprom驱动程序可能不便于测试,为此,我写了个简单的i2c驱动用来测试at24c08,代码如下: #include #include #include #include #include #include #include MODULE_LICENSE("GPL"); struct at24_data { struct cdev cdev; struct i2c_client *client; }; int at24_read_block(struct i2c_client *client, u8 addr, u8 len, u8 *values) { return i2c_smbus_read_i2c_block_data(client, addr, len, values); } int at24_write_block(struct i2c_client *client, u8 addr, u8 len, u8 *values) { return i2c_smbus_write_i2c_block_data(client, addr, len, values); } #define BLOCK_MAX 32 static size_t at24_read(struct file *file, char __user *buf, size_t count, loff_t *pos) { struct at24_data *at24 = file->private_data; int num; u8 block[BLOCK_MAX]; if (count > BLOCK_MAX) count = BLOCK_MAX; num = at24_read_block(at24->client, *pos, count, block); if (copy_to_user(buf, block, num)) { return -EFAULT; } else { *pos += num; return num; } } static size_t at24_write(struct file *file, char __user *buf, size_t count, loff_t *pos) { struct at24_data *at24 = file->private_data; int num; u8 block[BLOCK_MAX]; if (count > BLOCK_MAX) count = BLOCK_MAX; if (copy_from_user(block, buf, count)) { return -EFAULT; } else { num = at24_write_block(at24->client, *pos, count, block); *pos += num; return num; } } static size_t at24_open(struct inode *inode, struct file *file) { struct at24_data *at24; at24 = container_of(inode->i_cdev, struct at24_data, cdev); file->private_data = at24; return 0; } static size_t at24_close(struct inode *inode, struct file *file) { file->private_data = NULL; return 0; } static struct file_operations at24_fops = { .open = at24_open, .release = at24_close, .read = at24_read, .write = at24_write, }; static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct at24_data *at24; int retval = 0; dev_t dev_id; at24 = kzalloc(sizeof(struct at24_data), GFP_KERNEL); if (!at24) { return -ENOMEM; } at24->client = client; retval = alloc_chrdev_region(&dev_id, 0, 1, "at24c08"); if (retval < 0) { dev_err(&client->dev, "unable to allocate char device regionn"); goto err_out; } cdev_init(&at24->cdev, &at24_fops); retval = cdev_add(&at24->cdev, dev_id, 1); if (retval < 0) { dev_err(&client->dev, "unable to register char devicen"); goto err_free_region; } i2c_set_clientdata(client, at24); return 0; err_free_region: unregister_chrdev_region(dev_id, 1); err_out: kfree(at24); return -1; } static int at24_remove(struct i2c_client *client) { struct at24_data *at24 = i2c_get_clientdata(client); cdev_del(&at24->cdev); kfree(at24); unregister_chrdev_region(at24->cdev.dev, 1); return 0; } static struct i2c_device_id at24_ids[] = { { "at24c08", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, at24_ids); static struct i2c_driver at24_driver = { .driver = { .name = "at24c08", }, .id_table = at24_ids, .probe = at24_probe, .remove = at24_remove, }; static int __init at24_init(void) { return i2c_add_driver(&at24_driver); } static void __exit at24_exit(void) { i2c_del_driver(&at24_driver); } module_init(at24_init); module_exit(at24_exit); 编译好了之后,首先insmod,然后mknod,测试app程序如下: #include #include #include #include #include #include //#define TEST_WRITE 1 #define TEST_READ 1 int main(int argc, char *argv[]) { int fd; int i; char buf[8]; if (argc < 2) exit(1); fd = open(argv[1], O_RDWR); if (fd < 0) exit(1); #ifdef TEST_WRITE for (i = 0; i < sizeof(buf); i++) buf[i] = i; write(fd, buf, sizeof(buf)); #endif #ifdef TEST_READ memset(buf, 0, sizeof(buf)); read(fd, buf, sizeof(buf)); for (i = 0; i < sizeof(buf); i++) printf("%d ", buf[i]); printf("n"); #endif close(fd); exit(0); } 最后测试得即使掉电之后也能正确读取到写入的数据,说明程序是ok的。 // 2016-05-15 add 另一个i2c read函数 int at24_read_array(struct i2c_client *client, u8 addr, u8 len, u8 *vals) { struct i2c_msg msgs[] = { { .addr = client->addr, .flags = 0, .len = 1, .buf = &addr }, { .addr = client->addr, .flags = I2C_M_RD, .len = len, .buf = vals } }; int ret; ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); if (ret < 0) printk("i2c_transfer errorn"); return ret; } 这里使用i2c_transfer来操作i2c,注意i2c_transfer的返回值,正确返回的是传输i2c_msg的个数。
上一篇:ARM时钟学习
下一篇:mini2440裸机之I2C
推荐阅读最新更新时间:2024-11-09 10:30
设计资源 培训 开发板 精华推荐
- DC498C,具有 LTC4007EGN 3A 锂离子电池充电器的演示板
- USB-SDP-CABLEZ,串行接口板提供 USB 连接,USB 2.0 高速连接到计算机
- EVB-USB2240-IND,使用 USB2240 的评估板是具有安全数字 SD 的超快速 USB 2.0 多格式闪存媒体控制器
- HackRFOne复刻版V2.0
- 用于便携式的 5 节镍镉电池备份
- 【航顺训练营】基于HK32蓝牙双模键盘+461097A
- LTM4632EY QDR4 存储器电源模块稳压器的典型应用电路
- 使用 Analog Devices 的 ADA4077-2 的参考设计
- S5U13700P00C000,基于S1D13705F00A嵌入式存储器LCD控制器的开发套件
- Protues仿真实例(8051)-8255并行口扩展
- 泰克MDO3000系列示波器结合MDO3PWR功率分析模块 立即询价享春季好礼!
- 阅读并了解 TE Connectivity 无创想,不奇迹 精彩专题,答题有礼!
- 有奖直播 | 同质化严重,缺乏创新,ST60毫米波非接触连接器,赋予你独特的产品设计,重拾市场话语权
- 报名STM32全国巡回研讨会,打卡轻松得ST开发板
- 有奖学习 | 探索泰克 4 系列 BMSO 强大功能,还能参与“叠叠乐”省钱大作战!
- 答题有礼|罗彻斯特电子带你解锁半导体全周期难题
- 【赠书100%有礼】一本书教你如何开发测试系统,深入了解数据采集系统
- 报名有礼:【TI C2000在实时控制系统中的新特性】网络直播诚邀您参与!
- 开关电源兴趣小组招募,只为学习开关电源