Lecture et écriture de mémoire EEPROM via I2C avec Linux

J’essaie de lire et d’écrire une EEPROM Atmel 24C256 avec un Raspberry Pi B + sur I2C, mais j’ai du mal à tout faire fonctionner correctement.

Voici le code que j’ai jusqu’à présent:

#include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #define DEVICE_PATH "/dev/i2c-1" #define PAGE_SIZE 64 #define DEVICE_ADDR 0x50 // 0b1010xxxx int file_desc; char buffer[PAGE_SIZE + 2]; // 64 bytes + 2 for the address void teardownI2C() { int result = close(file_desc); } void setupI2C() { file_desc = open(DEVICE_PATH, O_RDWR); if(file_desc < 0) { printf("%s\n", strerror(errno)); exit(1); } if(ioctl(file_desc, I2C_SLAVE, DEVICE_ADDR)  PAGE_SIZE + 2) { printf("Can't write more than %d bytes at a time.\n", PAGE_SIZE); return -1; } int i; my_buf[0] = addr_hi; my_buf[1] = addr_lo; for(i= 0; i < len; i++) { my_buf[2+i] = buf[i]; } msg_rdwr.msgs = &i2cmsg; msg_rdwr.nmsgs = 1; i2cmsg.addr = DEVICE_ADDR; i2cmsg.flags = 0; i2cmsg.len = 2+len; i2cmsg.buf = my_buf; if(ioctl(file_desc,I2C_RDWR,&msg_rdwr)<0) { printf("write_to_device(): %s\n", strerror(errno)); return -1; } return 0; } int read_from_device(char addr_hi, char addr_lo, char * buf, int len) { struct i2c_rdwr_ioctl_data msg_rdwr; struct i2c_msg i2cmsg; if(write_to_device(addr_hi, addr_lo ,NULL,0)<0) { printf("read_from_device(): address reset did not work\n"); return -1; } msg_rdwr.msgs = &i2cmsg; msg_rdwr.nmsgs = 1; i2cmsg.addr = DEVICE_ADDR; i2cmsg.flags = I2C_M_RD; i2cmsg.len = len; i2cmsg.buf = buf; if(ioctl(file_desc,I2C_RDWR,&msg_rdwr)<0) { printf("read_from_device(): %s\n", strerror(errno)); return -1; } return 0; } void fill_buffer(char *buf) { int i = 0; while(i < PAGE_SIZE && *buf) { buffer[i+2] = *buf++; } while(i++ 0) { printf("%s\n", newbuf); } teardownI2C(); //cleanup return EXIT_SUCCESS; } 

Écriture sur le périphérique comme dans la ligne write_to_device(0x01, 0x00, buffer, PAGE_SIZE); ne génère pas d’erreur, mais lorsque j’essaie de lire à partir du périphérique, je dois écrire un octet “factice” conformément à la fiche technique, puis essayer de lire à partir du périphérique, mais pour une raison quelconque, l’écriture de l’octet factice entraîne une erreur “Erreur d’entrée / sortie”. Je n’arrive pas à comprendre comment cela fonctionne. J’utilise deux ressources pour me guider, la documentation Linux I2C-Dev et un exemple tiré d’un périphérique EEPROM similaire. Je suis un peu coincé ici et je ne sais pas quoi essayer. Toutes les suggestions ou indications sont grandement appréciées!

Vous pouvez également y accéder via le pilote du kernel at24.c , si vous êtes en mesure de comstackr et d’installer une autre arborescence de périphériques du kernel pour votre Raspberry Pi.

L’arborescence de périphériques du kernel doit spécifier le type et l’adresse de l’EEPROM, ainsi que le bus I²C auquel il est connecté. Je ne suis pas sûr de Raspberry Pi, mais pour la EEPROM BeagleBone Black, cela se passe comme suit:

 &i2c0 { eeprom: eeprom@50 { compatible = "at,24c32"; reg = <0x50>; }; }; 

Pour votre appareil, vous devez spécifier compatible = "at,24c256";

Assurez-vous que la configuration du kernel spécifie CONFIG_EEPROM_AT24=y (ou =m ).

Ensuite, vous devriez pouvoir accéder à la mémoire EEPROM depuis l’espace utilisateur à l’ /sys/bus/i2c/devices/0-0050/eeprom ou de /sys/bus/i2c/drivers/at24/0-0050/eeprom .

Peut-être que ceci ici pourrait aider. http://www.richud.com/wiki/Rasberry_Pi_I2C_EEPROM_Program car il gère apparemment le périphérique que vous essayez de programmer et explique également certaines mises en garde concernant l’adressage 24c256

Mon code:

 enter code here __s32 write_eeprom(__s32 fd,__u32 offset,__u32 len,__u8 *buf) { __s32 ret; struct i2c_rdwr_ioctl_data msg_set; struct i2c_msg iomsgs; __u32 sended, sending; __u8 temp[ONE_PAGE + 1]; if((offset + len) > BYTES_MAX || len == 0) { printf("write too long than BYTES_MAX\n"); return -1; } sended = 0; iomsgs.addr = DEVICE_ADDR; iomsgs.flags = 0; //write iomsgs.buf = temp; msg_set.msgs = &iomsgs; msg_set.nmsgs = 1; while(len > sended) { if(len - sended > ONE_PAGE) sending = ONE_PAGE; else sending = len - sended; iomsgs.len = sending + 1; temp[0] = offset + sended; memcpy(&temp[1], buf + sended, sending); //printf("sending:%d sended:%d len:%d offset:%d \n", sending, sended, len, offset); ret = ioctl(fd, I2C_RDWR, (unsigned long)&msg_set); if(ret < 0) { printf("Error dring I2C_RDWR ioctl with error code: %d\n", ret); return ret; } sended += sending; usleep(5000); } return sended; } 

Petit programme simple pour comprendre la gestion facile d’un eeprom

 /* Simple program to write / read the eeprom AT24C32. Developed and tested on the Raspberry pi3B jessie To create the executable use the following command: gcc -Wall -o thisprogram.exe thisprogram.c */ #include  #include  // ioctl #include  // open #include  // read/write usleep #include  #include  // htons #include  #pragma pack(1) #define PAGESIZE 32 #define NPAGES 128 #define NBYTES (NPAGES*PAGESIZE) #define ADDRESS 0x57 // AT24C32's address on I2C bus typedef struct { ushort AW; char buf[PAGESIZE+2]; }WRITE; static WRITE AT = {0}; int main() { int fd; char bufIN[180] = {0}; time_t clock=time(NULL); snprintf(AT.buf, PAGESIZE+1, "%s: my first attempt to write", ctime(&clock)); // the buffer to write, cut to 32 bytes if ((fd = open("/dev/i2c-1", O_RDWR)) < 0) { printf("Couldn't open device! %d\n", fd); return 1; } if (ioctl(fd, I2C_SLAVE, ADDRESS) < 0) { printf("Couldn't find device on address!\n"); return 1; } AT.AW = htons(32); // I will write to start from byte 0 of page 1 ( 32nd byte of eeprom ) if (write(fd, &AT, PAGESIZE+2) != (PAGESIZE+2)) { perror("Write error !"); return 1; } while (1) { char ap[4]; if (read(fd,&ap,1) != 1) usleep(500); else break; } // wait on write's end if (write(fd, &AT, 2) != 2) { perror("Error in sending the reading address"); return 1; } if (read(fd,bufIN,PAGESIZE) != PAGESIZE) { perror("reading error\n"); return 1;} printf ("\n%s\n", bufIN); close(fd); return 0; }