-
-
Save gquere/d532ffaa62e3a23753afd4f0080e4df0 to your computer and use it in GitHub Desktop.
#include <stdlib.h> | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <fcntl.h> | |
#include <linux/i2c-dev.h> | |
#define READ_SIZE (256) | |
#define NB_PAGES (256) | |
/* UTILS **********************************************************************/ | |
void hexprint(const uint8_t *input, const int input_length) | |
{ | |
int i = 0; | |
for (i = 0; i < input_length; i++) { | |
if (i%16 == 0) { | |
printf("\n"); | |
} | |
printf("%02x ", input[i]); | |
} | |
printf("\n"); | |
} | |
void dump_to_file(const char *output_file_path, | |
const uint8_t *buffer, const int buffer_length) | |
{ | |
int output_file = open(output_file_path, O_RDWR|O_APPEND|O_CREAT); | |
if (output_file < 0) { | |
printf("Failed opening output file %s\n", output_file_path); | |
return; | |
} | |
write(output_file, buffer, buffer_length); | |
} | |
/* MAIN ***********************************************************************/ | |
int main(int argc, char *argv[]) | |
{ | |
/* got these values from i2cdetect */ | |
const char *i2c_device = "/dev/i2c-2"; | |
const int device_address = 0x50; | |
/* open the i2c device file */ | |
int file = open(i2c_device, O_RDWR); | |
if (file < 0) { | |
printf("Failed opening %s\n", i2c_device); | |
return 1; | |
} | |
if (ioctl(file, I2C_SLAVE, device_address) < 0) { | |
printf("Failed addressing device at %02X\n", device_address); | |
close(file); | |
return 1; | |
} | |
int i = 0; | |
for (i = 0; i < NB_PAGES; i++) { | |
char buf[READ_SIZE] = {0}; | |
if (read(file, buf, READ_SIZE) != READ_SIZE) { | |
printf("Failed reading\n"); | |
close(file); | |
return 1; | |
} | |
//hexprint(buf, READ_SIZE); | |
dump_to_file(argv[1], buf, READ_SIZE); | |
} | |
close(file); | |
return 0; | |
} |
this is almost correct but in my case I get the starting page always different depending on the last read.
how to read from the start and not from a random page?
Sorry not sure where this could be coming from, haven't worked with I2C in years. This was just a hack to dump a simple EEPROM from a beaglebone card. Maybe there's a sequential read page counter for your chip. You should refer to its manual or read the code of a full-blown HAL like the one from STM Cube maybe.
not a problem.. I rewrote the program yesterday to dump and restore a 24c256 very easily and without most of i2c stuff.
I will soon publish it and if you like I will give you the link.
any way to READ a 24c256 you need first to write 2 BYTES, ADDRHI and ADDRLO, then just by using read() you can read it all 256 byte at a time.
to write it is trickier.. you need to write 34 bytes (or less) at a time where the first 2 are the address.
but you have to wait 2-3ms between the writes.
all codes present on github/staroverflow do not work! at least not on an lg tv which has an old linux kernel.
but in this way it works and I correctly dumped and restored the 24c256 eeprom.
Check my fork.. it's even easier.. all that is missing is a simple write:
write(file,'\x00\x00',2); // ADDRESS
before the read cycle.
25c256 have 16 bit HI then LO, as address.
Smaller eeproms have only 8 so the write must be one byte only.
note: when writing back instead, you must write the address (2 bytes) followed by the data (32bytes maximum), and wait at least 3ms between the writes.
here is the full backup and restore program which now includes also the "aknowledge polling" (before I had just an ugly usleep function).
https://gist.github.com/Zibri/cf8ac0b311301aeeaa8910c7da824bff
this is almost correct but in my case I get the starting page always different depending on the last read.
how to read from the start and not from a random page?