00001
00042 #include "eeprom.h"
00043
00044 #include <cfg/debug.h>
00045 #include <appconfig.h>
00046 #include <cfg/macros.h>
00047 #include <cpu/attr.h>
00048 #include CPU_HEADER(twi)
00049 #include <drv/wdt.h>
00050 #include <mware/byteorder.h>
00051
00052 #include <string.h>
00053
00054
00055
00056 #if !defined(CONFIG_EEPROM_VERIFY) || (CONFIG_EEPROM_VERIFY != 0 && CONFIG_EEPROM_VERIFY != 1)
00057 #error CONFIG_EEPROM_VERIFY must be defined to either 0 or 1
00058 #endif
00059
00063 #define EEPROM_ID 0xA0
00064
00068 #define EEPROM_ADDR(x) (EEPROM_ID | (((uint8_t)(x)) << 1))
00069
00070
00071
00072
00077 static bool eeprom_writeRaw(e2addr_t addr, const void *buf, size_t count)
00078 {
00079 bool result = true;
00080 ASSERT(addr + count <= EEPROM_SIZE);
00081
00082 while (count && result)
00083 {
00084
00085
00086
00087
00088 size_t size =
00089 MIN(count, (size_t)(EEPROM_BLKSIZE - (addr & (EEPROM_BLKSIZE - 1))));
00090
00091 #if CONFIG_EEPROM_TYPE == EEPROM_24XX16
00092
00093
00094
00095
00096 uint8_t blk_addr = (uint8_t)((addr >> 8) & 0x07);
00097 uint8_t blk_offs = (uint8_t)addr;
00098
00099 result =
00100 twi_start_w(EEPROM_ADDR(blk_addr))
00101 && twi_send(&blk_offs, sizeof blk_offs)
00102 && twi_send(buf, size);
00103
00104 #elif CONFIG_EEPROM_TYPE == EEPROM_24XX256
00105
00106
00107 uint16_t addr_be = cpu_to_be16(addr);
00108
00109 result =
00110 twi_start_w(EEPROM_ID)
00111 && twi_send((uint8_t *)&addr_be, sizeof addr_be)
00112 && twi_send(buf, size);
00113
00114 #else
00115 #error Unknown device type
00116 #endif
00117
00118 twi_stop();
00119
00120
00121
00122
00123
00124
00125
00126
00127 count -= size;
00128 addr += size;
00129 buf = ((const char *)buf) + size;
00130 }
00131
00132 if (!result)
00133 TRACEMSG("Write error!");
00134 return result;
00135 }
00136
00137
00138 #if CONFIG_EEPROM_VERIFY
00139
00145 static bool eeprom_verify(e2addr_t addr, const void *buf, size_t count)
00146 {
00147 uint8_t verify_buf[16];
00148 bool result = true;
00149
00150 while (count && result)
00151 {
00152
00153 size_t size = MIN(count, sizeof verify_buf);
00154
00155
00156 if (eeprom_read(addr, verify_buf, size))
00157 {
00158 if (memcmp(buf, verify_buf, size) != 0)
00159 {
00160 TRACEMSG("Data mismatch!");
00161 result = false;
00162 }
00163 }
00164 else
00165 {
00166 TRACEMSG("Read error!");
00167 result = false;
00168 }
00169
00170
00171 count -= size;
00172 addr += size;
00173 buf = ((const char *)buf) + size;
00174 }
00175
00176 return result;
00177 }
00178 #endif
00179
00180
00181 bool eeprom_write(e2addr_t addr, const void *buf, size_t count)
00182 {
00183 #if CONFIG_EEPROM_VERIFY
00184 int retries = 5;
00185
00186 while (retries--)
00187 if (eeprom_writeRaw(addr, buf, count)
00188 && eeprom_verify(addr, buf, count))
00189 return true;
00190
00191 return false;
00192
00193 #else
00194 return eeprom_writeRaw(addr, buf, count);
00195 #endif
00196 }
00197
00198
00205 bool eeprom_read(e2addr_t addr, void *buf, size_t count)
00206 {
00207 ASSERT(addr + count <= EEPROM_SIZE);
00208
00209 #if CONFIG_EEPROM_TYPE == EEPROM_24XX16
00210
00211
00212
00213
00214 uint8_t blk_addr = (uint8_t)((addr >> 8) & 0x07);
00215 uint8_t blk_offs = (uint8_t)addr;
00216
00217 bool res =
00218 twi_start_w(EEPROM_ADDR(blk_addr))
00219 && twi_send(&blk_offs, sizeof blk_offs)
00220 && twi_start_r(EEPROM_ADDR(blk_addr))
00221 && twi_recv(buf, count);
00222
00223 #elif CONFIG_EEPROM_TYPE == EEPROM_24XX256
00224
00225
00226 addr = cpu_to_be16(addr);
00227
00228 bool res =
00229 twi_start_w(EEPROM_ID)
00230 && twi_send((uint8_t *)&addr, sizeof(addr))
00231 && twi_start_r(EEPROM_ID)
00232 && twi_recv(buf, count);
00233 #else
00234 #error Unknown device type
00235 #endif
00236
00237 twi_stop();
00238
00239 if (!res)
00240 TRACEMSG("Read error!");
00241 return res;
00242 }
00243
00244
00248 bool eeprom_write_char(e2addr_t addr, char c)
00249 {
00250 return eeprom_write(addr, &c, 1);
00251 }
00252
00253
00259 int eeprom_read_char(e2addr_t addr)
00260 {
00261 char c;
00262
00263 if (eeprom_read(addr, &c, 1))
00264 return c;
00265 else
00266 return -1;
00267 }
00268
00269
00276 void eeprom_erase(e2addr_t addr, size_t count)
00277 {
00278 uint8_t buf[EEPROM_BLKSIZE];
00279 memset(buf, 0xFF, sizeof buf);
00280
00281
00282 while (count)
00283 {
00284
00285 wdt_reset();
00286
00287 size_t size = MIN(count, sizeof buf);
00288 eeprom_write(addr, buf, size);
00289 addr += size;
00290 count -= size;
00291 }
00292 }
00293
00294
00298 void eeprom_init(void)
00299 {
00300 twi_init();
00301 }
00302
00303
00304 #ifdef _DEBUG
00305
00306 #include <string.h>
00307
00308 void eeprom_test(void)
00309 {
00310 static const char magic[14] = "Humpty Dumpty";
00311 char buf[sizeof magic];
00312 size_t i;
00313
00314
00315 for (i = 0; i < 42; ++i)
00316 {
00317 wdt_reset();
00318 eeprom_write(i * sizeof magic, magic, sizeof magic);
00319 }
00320
00321
00322 for (i = 0; i < 42 * sizeof magic; ++i)
00323 {
00324 wdt_reset();
00325 eeprom_read(i, buf, 1);
00326 kprintf("EEPROM byte read: %c (%d)\n", buf[0], buf[0]);
00327 ASSERT(buf[0] == magic[i % sizeof magic]);
00328 }
00329
00330
00331 for (i = 0; i < 42; ++i)
00332 {
00333 wdt_reset();
00334 memset(buf, 0, sizeof buf);
00335 eeprom_read(i * sizeof magic, buf, sizeof magic);
00336 kprintf("EEPROM seq read @ 0x%x: '%s'\n", i * sizeof magic, buf);
00337 ASSERT(memcmp(buf, magic, sizeof magic) == 0);
00338 }
00339 }
00340
00341 #endif // _DEBUG