Driver library for Microchip I2C EERAM (47x04 and 47x16) 4 kbit or 16 kbit EEPROM backed SRAM.
Embed:
(wiki syntax)
Show/hide line numbers
EERAM.h
Go to the documentation of this file.
00001 /** 00002 * @file EERAM.h 00003 * @brief mbed driver for Microchip I2C EERAM devices (47x04 and 47x16) 00004 * @author Mark Peter Vargha, vmp@varghamarkpeter.hu 00005 * @version 1.4.0 00006 * 00007 * Copyright (c) 2017 00008 * 00009 * Licensed under the Apache License, Version 2.0 (the "License"); 00010 * you may not use this file except in compliance with the License. 00011 * You may obtain a copy of the License at 00012 * 00013 * http://www.apache.org/licenses/LICENSE-2.0 00014 * 00015 * Unless required by applicable law or agreed to in writing, software 00016 * distributed under the License is distributed on an "AS IS" BASIS, 00017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00018 * See the License for the specific language governing permissions and 00019 * limitations under the License. 00020 */ 00021 00022 #ifndef EERAM_h 00023 #define EERAM_h 00024 00025 #include "mbed.h" 00026 00027 //#define DEBUG_EERAM 00028 00029 #ifdef DEBUG_EERAM 00030 extern Serial serial; 00031 #endif 00032 00033 enum ProtectedMemoryArea 00034 { 00035 NONE = 0, U64, U32, U16, U8, U4, U2, ALL 00036 }; 00037 00038 /** An I2C EERAM interface to communicate with Microchip 47x04 and 47x16 devices 00039 * 4 kbit (512 byte) or 16 kbit (2048 byte) EEPROM backed I2C SRAM 00040 * The device could detect power down and stores SRAM contents in EEPROM. The SRAM is recalled from EEPROM on power up. 00041 * 00042 * <a href="http://ww1.microchip.com/downloads/en/DeviceDoc/20005371C.pdf">47x04 and 47x16 datasheet</a> 00043 * <a href="http://ww1.microchip.com/downloads/cn/AppNotes/cn588417.pdf">Recommended Usage of Microchip I2C EERAM Devices</a> 00044 * <a href="http://ww1.microchip.com/downloads/en/AppNotes/00002257A.pdf">Choosing the Right EERAM VCAP Capacitor</a> 00045 * 00046 * Example: 00047 * @code 00048 #include "mbed.h" 00049 #include "EERAM.h" 00050 00051 EERAM eeram(PC_9, PA_8, 2048); //SDA, SCL 00052 00053 int main() 00054 { 00055 if (!eeram.isReady(100)) //Checks device with 100 ms timeout 00056 { 00057 printf("Device is not present."); 00058 while (1); 00059 } 00060 eeram.readStatus(); //Reads status register 00061 eeram.setAutoStoreEnabled(true, true); //Set auto store on power down to true and stores if not stored before 00062 while (1) 00063 { 00064 char dataStore[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; 00065 eeram.writeBytes(0x100, dataStore, 16); //We can not wear EEPROM out, so it is ok to write data to the device frequently. 00066 wait(2.0); 00067 char dataRead[16]; 00068 eeram.readBytes(0x100, dataRead, 16); 00069 wait(2.0); 00070 float floatToWrite = -1.976f; 00071 const uint16_t address = 0x200; 00072 eeram.write(address, &floatToWrite); 00073 wait(2.0); 00074 float floatToRead = 0; 00075 eeram.read(address, &floatToWrite); 00076 wait(2.0); 00077 } 00078 } 00079 00080 * @endcode 00081 */ 00082 class EERAM 00083 { 00084 00085 public: 00086 00087 /** Create an I2C EERAM interface, connected to the specified pins, with specified size and with the specified address pins 00088 * @param SDA I2C data line pin 00089 * @param SCL I2C clock line pin 00090 * @param memorySize Size of EERAM, 512 for 47x04 and 2048 for 47x16 00091 * @param A1 EERAM A1 pin state (true = high, false = low) 00092 * @param A2 EERAM A2 pin state (true = high, false = low) 00093 */ 00094 // EERAM(PinName SDA, PinName SCL, uint16_t memorySize, bool A1 = false, bool A2 = false) : 00095 // _i2c(SDA, SCL), 00096 // _memorySize(memorySize) 00097 // { 00098 // initialize(A1, A2); 00099 // }; 00100 00101 /** Create an I2C EERAM interface, connected to the I2C, with specified size and with the specified address pins. 00102 * @param 12c I2C 00103 * @param memorySize Size of EERAM, 512 for 47x04 and 2048 for 47x16 00104 * @param A1 EERAM A1 pin state (true = high, false = low) 00105 * @param A2 EERAM A2 pin state (true = high, false = low) 00106 */ 00107 EERAM(I2C &i2c, uint16_t memorySize, bool A1 = false, bool A2 = false) : 00108 _i2c(i2c), 00109 _memorySize(memorySize) 00110 { 00111 initialize(A1, A2); 00112 }; 00113 00114 /** Puts the given 16 bit SRAM address into the first two bytes of the given buffer. The buffer size shall be minimum two bytes. No length check. 00115 */ 00116 static void putAddressIntoBuffer(uint16_t address, char *data); 00117 00118 /** Copies the bytes from the given memory area to the given buffer. Uses the size of T to determine write length. 00119 * @param buffer Buffer to put bytes into 00120 * @param source Pointer to the memory location 00121 * 00122 * @return Number of written bytes. 00123 */ 00124 template <typename T> 00125 static int putIntoBuffer(char *buffer, const int bufferSize, T *source) 00126 { 00127 const int length = sizeof(T); 00128 if (length <= bufferSize) 00129 { 00130 char *bytes = static_cast<char*>(static_cast<void*>(source)); 00131 memcpy(buffer, bytes, length); 00132 return length; 00133 } 00134 else 00135 { 00136 return 0; 00137 } 00138 } 00139 00140 /** Copies the bytes from the given buffer to the given memory area. Uses the size of T to determine read length. 00141 * @param buffer Buffer to get bytes from 00142 * @param destination Pointer to the memory location 00143 * 00144 * @return Number of read bytes. 00145 */ 00146 template <typename T> 00147 static int getFromBuffer(char *buffer, const int bufferSize, T *destination) 00148 { 00149 const int length = sizeof(T); 00150 if (length <= bufferSize) 00151 { 00152 char *bytes = static_cast<char*>(static_cast<void*>(destination)); 00153 memcpy(bytes, buffer, length); 00154 return length; 00155 } 00156 else 00157 { 00158 return 0; 00159 } 00160 } 00161 00162 /** Copies the bytes from the given memory area to the given EERAM address. Uses the size of T and the length to determine write length. Allowed types: Primitives, fixed arrays and structs without pointers. 00163 * @param source Pointer to memory where copy from. 00164 * @param length Length of the array. Pass 1 here if it is not an array. 00165 * 00166 * @return Number of written bytes. 00167 */ 00168 template <typename T> 00169 int write(uint16_t address, T *source, const int length = 1) 00170 { 00171 bool success = false; 00172 const int typeLength = sizeof(T); 00173 const int writeLength = typeLength * length; 00174 const int addressLength = sizeof(uint16_t); 00175 char *sourceAsBytes = static_cast<char*>(static_cast<void*>(source)); 00176 success = checkAddressRange(address, writeLength); 00177 if (success) //Address range check 00178 { 00179 uint16_t addressPtr = address; 00180 int sourcePtr = 0; 00181 for (int i = 0; i < length; i++) 00182 { 00183 const int bufferSize = typeLength + addressLength; 00184 char buffer[bufferSize]; 00185 putAddressIntoBuffer(addressPtr, buffer); 00186 memcpy(buffer + addressLength, sourceAsBytes + sourcePtr, typeLength); 00187 success = writeBytes(buffer, bufferSize); 00188 if (success) //Write to I2C 00189 { 00190 addressPtr += typeLength; 00191 sourcePtr += typeLength; 00192 } 00193 else 00194 { 00195 break; 00196 } 00197 } 00198 } 00199 return success ? writeLength : 0; 00200 } 00201 00202 /** Copies the bytes from the given EERAM address to the given memory area. Uses the size of T and the length to determine read length. Allowed types: Primitives, fixed arrays and structs without pointers. Destination shall be allocated. 00203 * @param destination Pointer to memory where copy to. 00204 * @param length Length of the array. Pass 1 here if it is not an array. 00205 * @param direct Applicable only when length > 1. If true reads all items of the array in one I2C read, otherwise read them in blocks. 00206 * 00207 * @return Number of read bytes. 00208 */ 00209 template <typename T> 00210 int read(uint16_t address, T *destination, const int length = 1, bool direct = false) 00211 { 00212 bool success = false; 00213 const int typeLength = sizeof(T); 00214 const int readLength = typeLength * length; 00215 char *destinationAsBytes = static_cast<char*>(static_cast<void*>(destination)); 00216 success = checkAddressRange(address, readLength); 00217 if (success) success = setMemoryPointer(address, true); 00218 if (success) 00219 { 00220 if (direct) 00221 { 00222 success = _i2c.read(_sramAddressRead, destinationAsBytes, readLength) == 0; 00223 } 00224 else 00225 { 00226 uint16_t addressPtr = address; 00227 int destinationPtr = 0; 00228 for (int i = 0; i < length; i++) 00229 { 00230 const int bufferSize = typeLength; 00231 char buffer[bufferSize]; 00232 success = readBytes(addressPtr, buffer, bufferSize); 00233 if (success) 00234 { 00235 memcpy(destinationAsBytes + destinationPtr, buffer, bufferSize); 00236 addressPtr += typeLength; 00237 destinationPtr += typeLength; 00238 } 00239 else 00240 { 00241 break; 00242 } 00243 } 00244 } 00245 } 00246 return success ? readLength : 0; 00247 } 00248 00249 /** Writes bytes to the specified address. 00250 * @param address The 16 bit destination address 00251 * @param data Pointer to the data buffer to read from 00252 * @param length Data length 00253 * 00254 * @return 00255 * true on success 00256 * false on fail 00257 */ 00258 bool writeBytes(uint16_t address, char *data, int length); 00259 00260 /** Writes data to the SRAM. The first two bytes shall be the address. 00261 * @param data Pointer to the data buffer to read from 00262 * @param length Data length 00263 * 00264 * @return 00265 * true on success 00266 * false on fail 00267 */ 00268 bool writeBytes(char *data, int length); 00269 00270 /** Reads data from the specified address. 00271 * @param address The 16 bit source address 00272 * @param data Pointer to the data buffer to read to 00273 * @param length Data length 00274 * 00275 * @return 00276 * true on success 00277 * false on fail 00278 */ 00279 bool readBytes(uint16_t address, char *data, int length); 00280 00281 /** Reads data to the specified buffer. The first two bytes shall be the address. These bytes will be unchanged. 00282 * @param data Pointer to the data buffer to read to 00283 * @param length Data length 00284 * 00285 * @return 00286 * true on success 00287 * false on fail 00288 */ 00289 bool readBytes(char *data, int length); 00290 00291 /** Fills memory with the specified byte from the specified address 00292 * @param address The 16 bit destination address 00293 * @param data The byte to write 00294 * @param length Memory are to fill with the data byte 00295 * 00296 * @return 00297 * true on success 00298 * false on fail 00299 */ 00300 bool fillMemory(uint16_t address, char data, int length); 00301 00302 /** Fills the whole memory with the specified byte 00303 * @param data The byte to write 00304 * 00305 * @return 00306 * true on success 00307 * false on fail 00308 */ 00309 bool fillMemory(char data); 00310 00311 /** Continuously checks I2C EERAM device till ready or reaches timeout 00312 * @param timeout_ms Timeout for busy-wait I2C device polling 00313 * 00314 * @return 00315 * true on ready 00316 * false on timeout 00317 */ 00318 bool isReady(int timeout_ms); 00319 00320 /** Checks I2C EERAM device one time 00321 * 00322 * @return 00323 * true on ready 00324 * false on not ready 00325 */ 00326 bool isReady(); 00327 00328 /** Store SRAM in EEPROM 00329 * @param block If true, busy waits for operation end. 00330 * 00331 * @return 00332 * true on success 00333 * false on fail 00334 */ 00335 bool store(bool block); 00336 00337 /** Recall SRAM from EEPROM 00338 * @param block If true, busy waits for operation end. 00339 * 00340 * @return 00341 * true on success 00342 * false on fail 00343 */ 00344 bool recall(bool block); 00345 00346 /** Reads status register 00347 * 00348 * @return 00349 * true on success 00350 * false on fail 00351 */ 00352 bool readStatus(); 00353 00354 /** Gets status register 00355 * 00356 * @return The content of the 8 bit status register 00357 */ 00358 inline uint8_t getStatus() const 00359 { 00360 return _status; 00361 } 00362 00363 /** Writes the 8 bit status register to the I2C device 00364 * @param block If true, busy waits for operation end. 00365 * 00366 * @return 00367 * true on success 00368 * false on fail 00369 */ 00370 bool writeStatus(bool block); 00371 00372 /** Writes the 8 bit status register to the I2C device if changed 00373 * @param block If true, busy waits for operation end. 00374 */ 00375 void writeStatusIfChanged(bool block); 00376 00377 /** Sets protected memory area. The selected area will be write protected. 00378 * @param protectedMemoryArea The enum represents the area from NONE through upper 64, 32, 16, 8, 4, 2 to ALL 00379 * @param store If true, calls writeStatusIfChanged() 00380 */ 00381 void setProtectedMemoryArea(ProtectedMemoryArea protectedMemoryArea, bool store = false); 00382 00383 /** Gets protected memory area 00384 * Have to call readStatus() to read register's fresh value. 00385 */ 00386 ProtectedMemoryArea getProtectedMemoryArea(); 00387 00388 /** Gets Memory Modified 00389 * Have to call readStatus() to read register's fresh value. 00390 * @return 00391 * true The SRAM memory have been modified since the last store or recall operation 00392 * false The SRAM memory have not been modified since the last store or recall operation 00393 */ 00394 bool isMemoryModified(); 00395 00396 /** Sets Auto Store Enabled 00397 * @param enabled Auto store SRAM to EEPROM on power down enabled 00398 * @param store If true, calls writeStatusIfChanged() 00399 */ 00400 void setAutoStoreEnabled(bool enabled, bool store = false); 00401 00402 /** Gets Auto Store Enabled 00403 * Have to call readStatus() to read register's fresh value. 00404 * @return 00405 * true Auto Store is Enabled 00406 * false Auto Store is not Enabled 00407 */ 00408 bool isAutoStoreEnabled(); 00409 00410 /** Sets event detected 00411 * @param detected The value of the detected bit 00412 * @param store If true, calls writeStatusIfChanged() 00413 */ 00414 void setEventDetected(bool detected, bool store); 00415 00416 /** Gets event detected 00417 * Have to call readStatus() to read register's fresh value. 00418 * @return 00419 * true External store event detected (The HS pin pulled up) 00420 * false External event not detected 00421 */ 00422 bool isEventDetected(); 00423 00424 /** Prints the SRAM content from the given address to the given serial port in human readable format in 1-32 byte long lines 00425 * @param serial The port to print to 00426 */ 00427 void dump(Serial &serial, uint16_t start, uint16_t length, int lineSize = 16); 00428 00429 /** Prints the whole SRAM content to the given serial port in human readable format in 16 byte long lines 00430 * @param serial The port to print to 00431 */ 00432 void dump(Serial &serial); 00433 00434 /** Prints the 8 bit status register's contents to the given serial port in human readable format 00435 * @param serial The port to print to 00436 */ 00437 void dumpRegisters(Serial &serial); 00438 00439 private: 00440 static const uint8_t RW_BIT = 0; 00441 static const uint8_t A1_BIT = 2; 00442 static const uint8_t A2_BIT = 3; 00443 static const uint8_t STATUS_AM_BIT = 7; 00444 static const uint8_t STATUS_ASE_BIT = 1; 00445 static const uint8_t STATUS_EVENT_BIT = 0; 00446 static const uint8_t OPCODE_SRAM = 0b10100000; 00447 static const uint8_t OPCODE_CONTROL = 0b00110000; 00448 static const uint8_t REGISTER_STATUS = 0x0; 00449 static const uint8_t REGISTER_COMMAND = 0x55; 00450 static const uint8_t COMMAND_STORE = 0b00110011; 00451 static const uint8_t COMMAND_RECALL = 0b11011101; 00452 static const int TIME_RECALL_16_MS = 5; 00453 static const int TIME_RECALL_04_MS = 2; 00454 static const int TIME_STORE_16_MS = 25; 00455 static const int TIME_STORE_04_MS = 8; 00456 static const int TIME_STORE_STATUS_MS = 1; 00457 I2C &_i2c; 00458 uint16_t _memorySize; 00459 uint8_t _sramAddressWrite; 00460 uint8_t _sramAddressRead; 00461 uint8_t _controlAddressWrite; 00462 uint8_t _controlAddressRead; 00463 uint8_t _status; 00464 uint8_t _statusToWrite; 00465 void initialize(bool A1 = false, bool A2 = false); 00466 bool checkAddressRange(uint16_t start, uint16_t length); 00467 bool writeRegister(uint8_t registerAddress, uint8_t data); 00468 bool setMemoryPointer(uint16_t address, bool stop = true); 00469 bool setMemoryPointer(uint8_t address_0, uint8_t address_1, bool stop = true); 00470 }; 00471 00472 #endif //EERAM_h
Generated on Fri Jul 15 2022 21:14:32 by 1.7.2