Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: Test_I2CEeprom Alternator2020_06
I2CEeprom.cpp
00001 /* Simple access class for I2C EEPROM chips like Microchip 24LC 00002 * Copyright (c) 2015 Robin Hourahane 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #include "I2CEeprom.h" 00017 00018 I2CEeprom::I2CEeprom(PinName sda, PinName scl, int address, size_t pageSize, size_t chipSize, int busSpeed): 00019 m_i2c(sda, scl), 00020 m_i2cAddress(address), 00021 m_chipSize(chipSize), 00022 m_pageSize(pageSize) 00023 { 00024 m_i2c.frequency(busSpeed); 00025 } 00026 00027 size_t I2CEeprom::read(size_t address, char &value) { 00028 // Check the address and size fit onto the chip. 00029 if (!checkSpace(address, 1)) 00030 return 0; 00031 00032 char values[] = { (address >> 8), (address & 0xFF) }; 00033 if (m_i2c.write(m_i2cAddress, values, 2) == 0) { 00034 if (m_i2c.read(m_i2cAddress, &value, 1) == 0) { 00035 return 1; 00036 } 00037 } 00038 00039 return 0; 00040 } 00041 00042 size_t I2CEeprom::read(size_t address, char *buffer, size_t size) { 00043 // Check the address and size fit onto the chip. 00044 if (!checkSpace(address, size)) 00045 return 0; 00046 00047 char values[] = { (address >> 8), (address & 0xFF) }; 00048 if (m_i2c.write(m_i2cAddress, values, 2) == 0) { 00049 if (m_i2c.read(m_i2cAddress, buffer, size) == 0) { 00050 return size; 00051 } 00052 } 00053 00054 return 0; 00055 } 00056 00057 size_t I2CEeprom::write(size_t address, char value) { 00058 // Check the address and size fit onto the chip. 00059 if (!checkSpace(address, 1)) 00060 return 0; 00061 00062 char values[] = { (address >> 8), (address & 0xFF), value }; 00063 if (m_i2c.write(m_i2cAddress, values, 3) != 0) { 00064 return 0; 00065 } 00066 00067 waitForWrite(); 00068 00069 return 1; 00070 } 00071 00072 size_t I2CEeprom::write(size_t address, const char *buffer, size_t size) { 00073 // Check the address and size fit onto the chip. 00074 if (!checkSpace(address, size)) 00075 return 0; 00076 00077 const char *page = buffer; 00078 size_t left = size; 00079 00080 // Whle we have some more data to write. 00081 while (left != 0) { 00082 // Calculate the number of bytes we can write in the current page. 00083 // If the address is not page aligned then write enough to page 00084 // align it. 00085 size_t toWrite; 00086 if ((address % m_pageSize) != 0) { 00087 toWrite = (((address / m_pageSize) + 1) * m_pageSize) - address; 00088 if (toWrite > size) { 00089 toWrite = size; 00090 } 00091 } else { 00092 if (left <= m_pageSize) { 00093 toWrite = left; 00094 } else { 00095 toWrite = m_pageSize; 00096 } 00097 } 00098 00099 //printf("Writing [%.*s] at %d size %d\n\r", toWrite, page, address, toWrite); 00100 // Start the page write with the addres ine one write call. 00101 char values[] = { (address >> 8), (address & 0xFF) }; 00102 if (m_i2c.write(m_i2cAddress, values, 2, true) != 0) { 00103 // Write failed to return bytes written so far. 00104 return size - left; 00105 } 00106 00107 // Write the bytes out one at a time to avoid having to copy them to 00108 // another buffer. 00109 for (int count = 0; count != toWrite; ++count) { 00110 if (m_i2c.write(*page) == 0) { 00111 // Write failed to return bytes written so far. 00112 return size - left; 00113 } 00114 ++page; 00115 } 00116 00117 // Stop the transaction now we've completed the page 00118 // write. 00119 m_i2c.stop(); 00120 00121 waitForWrite(); 00122 00123 // Update the counters with the amount we've just written 00124 left -= toWrite; 00125 address += toWrite; 00126 } 00127 00128 return size; 00129 } 00130 00131 size_t I2CEeprom::fill(size_t address, char value, size_t size) { 00132 // Check the address and size fit onto the chip. 00133 if (!checkSpace(address, size)) 00134 return 0; 00135 00136 size_t left = size; 00137 00138 while (left != 0) { 00139 size_t toWrite; 00140 if ((address % m_pageSize) != 0) { 00141 toWrite = (((address / m_pageSize) + 1) * 64) - address; 00142 if (toWrite > size) { 00143 toWrite = size; 00144 } 00145 } else { 00146 if (left <= m_pageSize) { 00147 toWrite = left; 00148 } else { 00149 toWrite = m_pageSize; 00150 } 00151 } 00152 00153 //printf("Writing %d at %d size %d\n\r", value, address, toWrite); 00154 char values[] = { (address >> 8), (address & 0xFF) }; 00155 if (m_i2c.write(m_i2cAddress, values, 2, true) != 0) { 00156 return size - left; 00157 } 00158 00159 for (int count = 0; count != toWrite; ++count) { 00160 if (m_i2c.write(value) == 0) 00161 return size - left; 00162 } 00163 00164 m_i2c.stop(); 00165 00166 waitForWrite(); 00167 00168 left -= toWrite; 00169 address += toWrite; 00170 } 00171 00172 return size; 00173 } 00174 00175 void I2CEeprom::waitForWrite() { 00176 // The chip doesn't ACK while writing to the actual EEPROM 00177 // so loop trying to do a zero byte write until it is ACKed 00178 // by the chip. 00179 while (m_i2c.write(m_i2cAddress, 0, 0) != 0) { 00180 // Wait for ack. 00181 wait_ms(1); 00182 } 00183 } 00184 00185 bool I2CEeprom::checkSpace(size_t address, size_t size) { 00186 // Only check if chip size is non-zero. 00187 if (m_chipSize != 0) { 00188 // Check that the address start in the chip and doesn't 00189 // extend past. 00190 if ((address >= m_chipSize) || ((address + size) >= m_chipSize)) 00191 return false; 00192 else 00193 return true; 00194 } 00195 00196 return true; 00197 } 00198
Generated on Wed Jul 13 2022 23:59:54 by
1.7.2