#include #include #include #include #include #include #include #define DEV "/dev/i2c/0" #define EEPROM_ADDR 0x50 static int i2cdev; void raw_writepage(unsigned char page_start, unsigned char *src) { // Write 8-byte page unsigned char buf[9]; buf[0] = page_start; memcpy(buf + 1, src, 8); if (write(i2cdev, buf, 9) != 9) perror("data_write"); while (write(i2cdev, "\x00", 1) != 1) // Busy loop usleep(1000); eeprom_readpage(page_start, buf); // Verify if (memcmp(buf, src, 8) != 0) fprintf(stderr, "I2C eeprom data compare failed at page 0x%02x\n", page_start); } void check_journal() { /* Control page: 1st byte: 0 if clean, 1 if dirty 2st byte: write address */ unsigned char buf[8]; int dirty, destaddr; eeprom_readpage(PAGE_CONTROL, buf); dirty = buf[0]; destaddr = buf[1]; if (dirty == 0) // Memory is clean return; fprintf(stderr, "Replaying journal to page 0x%02x\n", destaddr); eeprom_readpage(PAGE_JOURNAL, buf); // If we lose power again, journal will be intact raw_writepage(destaddr, buf); // Clear control memset(buf, 0, 8); raw_writepage(PAGE_CONTROL, buf); } /* Public functions */ void eeprom_initialize() { i2cdev = open(DEV, O_RDWR); if (i2cdev < 0) perror("eeprom_open"); if (ioctl(i2cdev, I2C_SLAVE, EEPROM_ADDR) < 0) perror("eeprom_ioctl"); check_journal(); } void eeprom_readpage(unsigned char page_start, unsigned char *dest) { // Read 8-byte page if (write(i2cdev, &page_start, 1) != 1) perror("address_write"); if (read(i2cdev, dest, 8) != 8) perror("data_read"); } void eeprom_writepage(unsigned char page_start, unsigned char *src) { // Journalled write or 8-byte page unsigned char buf[8] = {0}; // Write journal raw_writepage(PAGE_JOURNAL, src); // Write control page buf[0] = 1; buf[1] = page_start; raw_writepage(PAGE_CONTROL, buf); // Write memory raw_writepage(page_start, src); // Clear control memset(buf, 0, 8); raw_writepage(PAGE_CONTROL, buf); }