應用層代碼示例
/* app.c at24c08讀寫測試應用程序 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#define DEV "/dev/at24_eeprom"
int main(int argc, char **argv)
{
int fd, pos, i;
unsigned char value[512] = {};
fd = open(DEV, O_RDWR);
if(fd < 0)
{
perror(DEV);
exit(1);
}
for(i = 0; i < 32; i++)
value[i] = i * 2;
pos = 16;
lseek(fd, pos, SEEK_SET);
write(fd, value, 32);
sleep(1);
pos = 16;
lseek(fd, pos, SEEK_SET);
printf("\nread eeprom from at offset %d\n", pos);
printf("===============================================\n");
memset(value, 0, sizeof(value));
read(fd, value, 256);
for(i = 0; i < 256; i++)
{
if(i && ((i % 16) == 0))
printf("\n");
printf("%02x ",value[i]);
}
printf("\n===============================================\n");
pos = 0;
lseek(fd, pos, SEEK_SET);
printf("\nread eeprom from at offset %d:\n", pos);
printf("===============================================\n");
memset(value,0,sizeof(value));
read(fd, value, 256);
for(i = 0; i < 256; i++)
{
if(i && ((i % 16) == 0))
printf("\n");
printf("%02x ",value[i]);
}
printf("\n===============================================\n");
close(fd);
return 0;
}
linux系統驅動層代碼:
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/mod_devicetable.h>
#include <linux/log2.h>
#include <linux/i2c.h>
#include <linux/i2c/at24.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#define AT24_SIZE_BYTELEN 5
#define AT24_SIZE_FLAGS 8
/* create non-zero magic value for given eeprom parameters */
#define AT24_DEVICE_MAGIC(_len, _flags) \
((1 << AT24_SIZE_FLAGS | (_flags)) \
<< AT24_SIZE_BYTELEN | ilog2(_len))
static const struct i2c_device_id at24_ids[] = {
{ "24c00", AT24_DEVICE_MAGIC(128 / 8, AT24_FLAG_TAKE8ADDR) },
{ "24c01", AT24_DEVICE_MAGIC(1024 / 8, 0) },
{ "24c02", AT24_DEVICE_MAGIC(2048 / 8, 0) },
{ "spd", AT24_DEVICE_MAGIC(2048 / 8,
AT24_FLAG_READONLY | AT24_FLAG_IRUGO) },
{ "24c04", AT24_DEVICE_MAGIC(4096 / 8, 0) },
{ "at24c08", 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 */ }
};
MODULE_DEVICE_TABLE(i2c, at24_ids);
static struct i2c_client *client;
static ssize_t at24_eeprom_read(struct file *file,
char __user *buffer,
size_t count,
loff_t * offset)
{
u8 buf[1024] = {};
int ret;
ret = i2c_master_send(client, (const char *)offset, 1);
if(ret < 0)
{
printk("i2c_master_send failed!\n");
return -EAGAIN;
}
ret = i2c_master_recv(client, buf, sizeof(buf));
if(ret < 0)
{
printk("i2c_master_recv failed!\n");
return -EAGAIN;
}
ret = copy_to_user (buffer, (void *) buf, count);
if (!ret)
{
*offset += count;
return count;
}
return -EAGAIN;
}
static ssize_t at24_eeprom_write(struct file *file,
const char __user *buffer,
size_t count,
loff_t *offset)
{
unsigned char kbuf[2048] = {0};
unsigned transferred = 0;
int i = 0, ret;
if(i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
{
ret = copy_from_user (kbuf, buffer, count);
if(ret)
return -EAGAIN;
while (transferred < count)
{
ret = i2c_smbus_write_byte_data (client, i + (*offset), kbuf[i]);
if(ret < 0)
return -EAGAIN;
i++;
transferred++;
}
}
*offset += transferred;
return transferred;
}
static struct file_operations dev_fops = {
.owner = THIS_MODULE,
.read = at24_eeprom_read,
.write = at24_eeprom_write,
};
static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = "at24_eeprom",
.fops = &dev_fops,
};
static int at24_probe(struct i2c_client *clt, const struct i2c_device_id *id)
{
int ret;
client = clt;
if( !i2c_check_functionality(client->adapter,I2C_FUNC_SMBUS_READ_I2C_BLOCK) )
return -EPFNOSUPPORT;
ret = misc_register(&misc); //目的在/dev生成用戶空間訪問接口。
if(ret)
printk("dev register FAILED!\n");
return ret;
}
static int __devexit at24_remove(struct i2c_client *client)
{
return misc_deregister(&misc);
}
static struct i2c_driver at24_driver = {
.driver = {
.name = "at24_eeprom",
.owner = THIS_MODULE,
},
.probe = at24_probe,
.remove = __devexit_p(at24_remove),
.id_table = at24_ids,
};
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);
MODULE_LICENSE("GPL");