A library to read and write all 25* serial SPI eeprom devices from Microchip (from 25xx010 to 25xx1024).
Dependents: RobotRic VITI2_ihm_2
Revision 0:238ca4fdef8c, committed 2011-01-26
- Comitter:
- hlipka
- Date:
- Wed Jan 26 22:14:41 2011 +0000
- Child:
- 1:c29a67c7034d
- Commit message:
- initial version
Changed in this revision
Ser25lcxxx.cpp | Show annotated file Show diff for this revision Revisions of this file |
Ser25lcxxx.h | Show annotated file Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Ser25lcxxx.cpp Wed Jan 26 22:14:41 2011 +0000 @@ -0,0 +1,177 @@ +#include "Ser25lcxxx.h" +#include "wait_api.h" + +#define HIGH(x) ((x&0xff00)>>8) +#define LOW(x) (x&0xff) + +Ser25LCxxx::Ser25LCxxx(SPI *spi, PinName enable, int bytes, int pagesize) { + _spi=spi; + _enable=new DigitalOut(enable); + _size=bytes; + _pageSize=pagesize; + _enable->write(1); +} + +Ser25LCxxx::~Ser25LCxxx() { + delete _enable; +} + +char* Ser25LCxxx::read(unsigned int startAdr, unsigned int len) { + // assertion + if (startAdr+len>_size) + return NULL; + char* ret=(char*)malloc(len); + _enable->write(0); + wait_us(1); + // send address + if (_size<512) { // 256 and 128 bytes + _spi->write(0x03); + _spi->write(LOW(startAdr)); + } else if (512==_size) { // 4k variant adds 9th address bit to command + _spi->write(startAdr>255?0xb:0x3); + _spi->write(LOW(startAdr)); + } else if (_size<131072) { // everything up to 512k + _spi->write(0x03); + _spi->write(HIGH(startAdr)); + _spi->write(LOW(startAdr)); + } else { // 25xx1024, needs 3 byte address + _spi->write(0x03); + _spi->write(startAdr>>16); + _spi->write(HIGH(startAdr)); + _spi->write(LOW(startAdr)); + } + // read data into buffer + for (int i=0;i<len;i++) { + ret[i]=_spi->write(0); + } + wait_us(1); + _enable->write(1); + return ret; +} + +bool Ser25LCxxx::write(unsigned int startAdr, unsigned int len, const char* data) { + if (startAdr+len>_size) + return -1; + + int ofs=0; + while (ofs<len) { + // calculate amount of data to write into current page + int pageLen=_pageSize-((startAdr+ofs)%_pageSize); + if (ofs+pageLen>len) + pageLen=len-ofs; + // write single page + bool b=writePage(startAdr+ofs,pageLen,data+ofs); + if (!b) + return false; + // and switch to next page + ofs+=pageLen; + } + return true; +} + +bool Ser25LCxxx::writePage(unsigned int startAdr, unsigned int len, const char* data) { + enableWrite(); + + _enable->write(0); + wait_us(1); + + if (_size<512) { // 256 and 128 bytes + _spi->write(0x02); + _spi->write(LOW(startAdr)); + } else if (512==_size) { // 4k variant adds 9th address bit to command + _spi->write(startAdr>255?0xa:0x2); + _spi->write(LOW(startAdr)); + } else if (_size<131072) { // everything up to 512k + _spi->write(0x02); + _spi->write(HIGH(startAdr)); + _spi->write(LOW(startAdr)); + } else { // 25xx1024, needs 3 byte address + _spi->write(0x02); + _spi->write(startAdr>>16); + _spi->write(HIGH(startAdr)); + _spi->write(LOW(startAdr)); + } + + // do real write + for (int i=0;i<len;i++) { + _spi->write(data[i]); + } + wait_us(1); + // disable to start physical write + _enable->write(1); + + waitForWrite(); + + return true; +} + +bool Ser25LCxxx::clearPage(unsigned int pageNum) { + enableWrite(); + if (_size<65535) { + char* s=(char*)malloc(_pageSize); + for (int i=0;i<_pageSize;i++) { + s[i]=0xff; + } + bool b=writePage(_pageSize*pageNum,_pageSize,s); + delete s; + return b; + } else { + _enable->write(0); + wait_us(1); + _spi->write(0x42); + _spi->write(HIGH(_pageSize*pageNum)); + _spi->write(LOW(_pageSize*pageNum)); + wait_us(1); + _enable->write(1); + + waitForWrite(); + } + return true; +} + +void Ser25LCxxx::clearMem() { + enableWrite(); + if (_size<65535) { + for (int i=0;i<_size/_pageSize;i++) { + if (!clearPage(i)) + break; + } + } + else + { + _enable->write(0); + wait_us(1); + _spi->write(0xc7); + wait_us(1); + _enable->write(1); + + waitForWrite(); + } +} + +int Ser25LCxxx::readStatus() { + _enable->write(0); + wait_us(1); + _spi->write(0x5); + int status=_spi->write(0x00); + wait_us(1); + _enable->write(1); + return status; +} + +void Ser25LCxxx::waitForWrite() { + while (true) { + if (0==readStatus()&1) + break; + wait_us(10); + } +} + +void Ser25LCxxx::enableWrite() +{ + _enable->write(0); + wait_us(1); + _spi->write(0x06); + wait_us(1); + _enable->write(1); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Ser25lcxxx.h Wed Jan 26 22:14:41 2011 +0000 @@ -0,0 +1,72 @@ +#ifndef __SER25LCXXX_H__ +#define __SER25LCXXX_H__ + +#include "mbed.h" + +/** +A class to read and write all 25* serial SPI eeprom devices from Microchip (from 25xx010 to 25xx1024). + +One needs to provide total size and page size, since this cannot be read from the devices, +and the page size differs even by constant size (look up the data sheet for your part!) +*/ +class Ser25LCxxx +{ + public: + /** + create the handler class + @param spi the SPI port where the eeprom is connected. Must be set to format(8,3), and with a speed matching the one of your device (up to 5MHz should work) + @param enable the pin name for the port where /CS is connected + @param bytes the size of you eeprom in bytes (NOT bits, eg. a 25LC010 has 128 bytes) + @param pagesize the size of a single page, to provide overruns + */ + Ser25LCxxx(SPI *spi, PinName enable, int bytes, int pagesize); + + /** + destroys the handler, and frees the /CS pin + */ + ~Ser25LCxxx(); + + /** + read a part of the eeproms memory. The buffer will be allocated here, and must be freed by the user + @param startAdr the adress where to start reading. Doesn't need to match a page boundary + @param len the number of bytes to read (must not exceed the end of memory) + @return NULL if the adresses are out of range, the pointer to the data otherwise + */ + char* read(unsigned int startAdr, unsigned int len); + + /** + writes the give buffer into the memory. This function handles dividing the write into + pages, and waites until the phyiscal write has finished + @param startAdr the adress where to start writing. Doesn't need to match a page boundary + @param len the number of bytes to read (must not exceed the end of memory) + @return false if the adresses are out of range + */ + bool write(unsigned int startAdr, unsigned int len, const char* data); + + /** + fills the given page with 0xFF + @param pageNum the page number to clear + @return if the pageNum is out of range + */ + bool clearPage(unsigned int pageNum); + + /** + fills the while eeprom with 0xFF + */ + void clearMem(); + private: + bool writePage(unsigned int startAdr, unsigned int len, const char* data); + int readStatus(); + void waitForWrite(); + void enableWrite(); + + + SPI* _spi; + DigitalOut* _enable; + int _size,_pageSize; + +}; + + + +#endif