Enhanced EEPROM 25LCxxx driver

Dependents:   eeprom_test

Fork of 25LCxxx_SPI by Hendrik Lipka

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Ser25lcxxx.cpp Source File

Ser25lcxxx.cpp

00001 /*
00002 * Ser25lcxxx library
00003 * Copyright (c) 2010 Hendrik Lipka
00004 * 
00005 * Permission is hereby granted, free of charge, to any person obtaining a copy
00006 * of this software and associated documentation files (the "Software"), to deal
00007 * in the Software without restriction, including without limitation the rights
00008 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00009 * copies of the Software, and to permit persons to whom the Software is
00010 * furnished to do so, subject to the following conditions:
00011 * 
00012 * The above copyright notice and this permission notice shall be included in
00013 * all copies or substantial portions of the Software.
00014 * 
00015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00018 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00019 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00020 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00021 * THE SOFTWARE.
00022 */
00023 
00024 #include "Ser25lcxxx.h"
00025 #include "wait_api.h"
00026 
00027 #define HIGH(x)     ((x&0xff00)>>8)
00028 #define LOW(x)      (x&0xff)
00029 
00030 Ser25LCxxx::Ser25LCxxx (PinName sck, PinName si, PinName so, PinName enable,
00031                                                 int pagenumber, int pagesize):
00032                                                 spi(si, so, sck), cs(enable) {
00033     spi.format(8,3);
00034     spi.frequency(EEPROM_SPI_SPEED);
00035     size = pagesize*pagesize;
00036     pageSize = pagesize;
00037     pageNumber = pagenumber;
00038     cs.write(1);
00039 }
00040 
00041 unsigned int Ser25LCxxx::read (unsigned int startAdr, unsigned int len,
00042                                                         unsigned char* buf) {
00043     // assertion
00044     if ((startAdr+len) > size)
00045         return 0;
00046 
00047     //active the device
00048     cs = 0;
00049     wait_us(1);
00050 
00051     //send command and address
00052     if (size<512) { // 256 and 128 bytes
00053         spi.write(EEPROM_CMD_READ);
00054         spi.write(LOW(startAdr));
00055     } else if (512==size) { // 4k variant adds 9th address bit to command
00056         spi.write(startAdr>255?0xb:EEPROM_CMD_READ);
00057         spi.write(LOW(startAdr));
00058     } else if (size<131072) { // everything up to 512k
00059         spi.write(EEPROM_CMD_READ);
00060         spi.write(HIGH(startAdr));
00061         spi.write(LOW(startAdr));
00062     } else { // 25xx1024, needs 3 byte address
00063         spi.write(EEPROM_CMD_READ);
00064         spi.write(startAdr>>16);
00065         spi.write(HIGH(startAdr));
00066         spi.write(LOW(startAdr));
00067     }
00068 
00069     //read data into buffer
00070     for (int i=0; i<len; i++)
00071         buf[i] = spi.write(0);
00072     wait_us(1);
00073 
00074     cs = 1;
00075 
00076     return len;
00077 }
00078 
00079 unsigned int Ser25LCxxx::write (unsigned int startAdr, unsigned int len,
00080                                                    const unsigned char* data) {
00081     if ((startAdr+len) > size)
00082         return 0;
00083 
00084     unsigned int remaining = len;
00085     unsigned int count = 0;
00086 
00087     while (remaining > 0) {
00088         // calculate amount of data to write into current page
00089         int page_left = pageSize - (startAdr % pageSize);
00090         int to_be_written = (remaining > page_left)? page_left : remaining;
00091         if (writePage(startAdr, to_be_written, data+count) != to_be_written)
00092             return count;
00093         // and switch to next page
00094         count += to_be_written;
00095         remaining -= to_be_written;
00096         startAdr += to_be_written;
00097     }
00098     return count;
00099 }
00100 
00101 unsigned int Ser25LCxxx::writePage (unsigned int startAdr, unsigned int len,
00102                                                    const unsigned char* data) {
00103     //deactivate write-protection latch
00104     enableWrite();
00105 
00106     //activate eeprom
00107     cs = 0;
00108     wait_us(1);
00109 
00110     //send command and address
00111     if (size<512) { // 256 and 128 bytes
00112         spi.write(EEPROM_CMD_WRITE);
00113         spi.write(LOW(startAdr));
00114     } else if (512==size) { // 4k variant adds 9th address bit to command
00115         spi.write(startAdr>255?0xa:EEPROM_CMD_WRITE);
00116         spi.write(LOW(startAdr));
00117     } else if (size<131072) { // everything up to 512k
00118         spi.write(EEPROM_CMD_WRITE);
00119         spi.write(HIGH(startAdr));
00120         spi.write(LOW(startAdr));
00121     } else { // 25xx1024, needs 3 byte address
00122         spi.write(EEPROM_CMD_WRITE);
00123         spi.write(startAdr>>16);
00124         spi.write(HIGH(startAdr));
00125         spi.write(LOW(startAdr));
00126     }
00127 
00128     //write data
00129     for (int i=0; i<len; i++)
00130         spi.write(data[i]);
00131     wait_us(1);
00132 
00133     //disable eeprom
00134     cs = 1;
00135 
00136     //wait until write operation ends
00137     if (!waitForWrite())
00138         return 0;
00139 
00140     return len;
00141 }
00142 
00143 unsigned int Ser25LCxxx::clearPage (unsigned int pageNum) {
00144     unsigned char s[pageSize];
00145     memset(s, EEPROM_CLEAN_BYTE, pageSize);
00146 
00147     return writePage(pageSize*pageNum, pageSize, s);
00148 }
00149 
00150 unsigned int Ser25LCxxx::clearMem () {
00151     /* the implementation does not exploit clearPage to optimize the use
00152        of the buffer s - it is not set for each page but just once for the
00153        whole eeprom memory */
00154     unsigned char s[pageSize];
00155     unsigned int counter = 0;
00156 
00157     memset(s, EEPROM_CLEAN_BYTE, pageSize);
00158 
00159     for (int i=0; i<pageNumber; i++) {
00160         if (writePage(pageSize*i, pageSize, s) != pageSize)
00161             return counter;
00162         counter += pageSize;
00163     }
00164 
00165     return counter;
00166 }
00167 
00168 int Ser25LCxxx::readStatus() {
00169     //activate eeprom
00170     cs = 0;
00171     wait_us(1);
00172     
00173     //send command
00174     spi.write(EEPROM_CMD_RDSR);
00175     
00176     //read value
00177     int status = spi.write(0x00);
00178     wait_us(1);
00179     
00180     //deactivate eeprom
00181     cs = 1;
00182 
00183     return status;
00184 }
00185 
00186 bool Ser25LCxxx::waitForWrite() {
00187     unsigned int counter = 0;
00188 
00189     while (isWriteInProgress()) {
00190         wait_us(10);
00191         if ((++counter) > 500)
00192             return false;
00193     }
00194     
00195     return true;
00196 }
00197 
00198 void Ser25LCxxx::enableWrite () {
00199     //enable eeprom
00200     cs = 0;
00201     wait_us(1);
00202 
00203     //send command
00204     spi.write(EEPROM_CMD_WREN);
00205     wait_us(1);
00206     
00207     //disable eeprom
00208     cs = 1;
00209 }
00210 
00211 void Ser25LCxxx::writeStatus (unsigned char val) {
00212     enableWrite();
00213 
00214     //enable eeprom
00215     cs = 0;
00216     wait_us(1);
00217 
00218     //send command
00219     spi.write(EEPROM_CMD_WRSR);
00220     
00221     //write stautus
00222     spi.write(val);
00223     wait_us(1);
00224 
00225     //disable eeprom
00226     cs = 1;
00227 }