//----------------------------------------------------------------------------- // File: eeprom.c // Contents: EEPROM update firmware source. (Write only) // // indent 3. NO TABS! // // Copyright (c) 2002 Cypress Semiconductor // // $Workfile: eeprom.c $ // $Date: 9/07/05 2:54p $ // $Revision: 1 $ //----------------------------------------------------------------------------- //#include "fx2.h" #include "fx2regs.h" #include "eeprom.h" /////////////////////////////////////////////////////////////////////////////////////// // Write up to one page of data to the EEPROM. // Returns 0 on success, 1 on failure // Normally called within a while() loop so that errors are retried: // while (EEPROMWritePage(....)) // ; BYTE EEPROMWritePage(WORD addr, BYTE xdata * ptr, BYTE len) { BYTE i; BYTE retval; //EEPROM_DISABLE_WRITE_PROTECT(); // Make sure the i2c interface is idle EEWaitForStop(); // write the START bit and i2c device address EEStartAndAddr(); if(EEWaitForAck()) { retval = 1; goto EXIT_WP; } // write the eeprom offset if (DB_Addr) { I2DAT = MSB(addr); if(EEWaitForAck()) { retval = 1; goto EXIT_WP; } } I2DAT = LSB(addr); if(EEWaitForAck()) { retval = 1; goto EXIT_WP; } // Write the data Page for (i = 0; i < len; i++) { I2DAT = *ptr++; if(EEWaitForDone()) { retval = 1; goto EXIT_WP; } } I2CS |= bmSTOP; WaitForEEPROMWrite(); retval = 0; EXIT_WP: EEPROM_ENABLE_WRITE_PROTECT(); return(retval); } void EEStartAndAddr() { I2CS = bmSTART; I2DAT = I2C_Addr << 1; } // 0x2e in assembly, less than 0x20 with compiler optimization!! void WaitForEEPROMWrite() { EEWaitForStop(); waitForBusy: EEStartAndAddr(); EEWaitForDone(); I2CS |= bmSTOP; // ; Set the STOP bit EEWaitForStop(); if (!(I2CS & bmACK)) // If no ACK, try again. goto waitForBusy; } void EEWaitForStop() { // Data should not be written to I2CS or I2DAT until the STOP bit returns low. while (I2CS & bmSTOP) ; } // Returns 0 on success, 1 on failure BYTE EEPROMRead(WORD addr, BYTE length, BYTE xdata *buf) { BYTE i; // Make sure the i2c interface is idle EEWaitForStop(); // write the START bit and i2c device address EEStartAndAddr(); if(EEWaitForAck()) return(1); // write the eeprom offset if (DB_Addr) { I2DAT = MSB(addr); if(EEWaitForAck()) return(1); } I2DAT = LSB(addr); if(EEWaitForAck()) return(1); I2CS = bmSTART; // send the read command I2DAT = (I2C_Addr << 1) | 1; if(EEWaitForDone()) return(1); // read dummy byte i = I2DAT; if(EEWaitForDone()) return(1); for (i=0; i < (length - 1); i++) { *(buf+i) = I2DAT; if(EEWaitForDone()) return(1); } I2CS = bmLASTRD; if(EEWaitForDone()) return(1); *(buf+i) = I2DAT; if(EEWaitForDone()) return(1); I2CS = bmSTOP; i = I2DAT; return(0); } // Return 0 for ok, 1 for error BYTE EEWaitForDone() { BYTE i; while (!((i = I2CS) & 1)) // Poll the done bit ; if (i & bmBERR) return 1; else return 0; } // Return 0 for ok, 1 for error // Same as wait for done, but checks for ACK as well BYTE EEWaitForAck() { BYTE i; while (!((i = I2CS) & 1)) // Poll the done bit ; if (i & bmBERR) return 1; else if (!(i & bmACK)) return 1; else return 0; } // Determine the page size supported by the EEPROM. All of the EEPROMS we use // (Atmel, Xicor and Microchip) will wrap their page address pointer if the page // buffer is overrun. We write 128 incrementing bytes to the EEPROM. We then // read the block back. If location 0 is right, the page size is 128. // If location 0 is wrong, it directly provides a mask for the page size. // For example, if the page size is 4, location 0 will contain 0x7c BYTE EEPROMGetPageSize() { #define MAX_PAGE_SIZE 64 BYTE xdata testData[MAX_PAGE_SIZE]; BYTE xdata saveData[MAX_PAGE_SIZE]; BYTE i; BYTE retval; if (!DB_Addr) return(1); EEPROMRead(0, MAX_PAGE_SIZE, saveData); for (i = 0; i < MAX_PAGE_SIZE; i++) { testData[i] = i; } EEPROMWritePage(0, testData, MAX_PAGE_SIZE); for (i = 0; i < MAX_PAGE_SIZE; i++) { testData[i] = ~i; } EEPROMRead(0, MAX_PAGE_SIZE, testData); i = testData[0]; if (i & 1) retval = 1; // Couldn't read back large EEPROM. Assume page size 1. else { i = (MAX_PAGE_SIZE-1) ^ i; i++; retval = i; } for (i = 0; i < MAX_PAGE_SIZE; i+= retval) EEPROMWritePage(i, saveData, retval); return(retval); }