嵌入式中linux系統對eeprom芯片at24c02的操作實例(包括驅動層和應用層代碼)

原文鏈接:https://my.oschina.net/handawei/blog/68526

應用層代碼示例

/* 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");

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章