00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <config.h>
00027
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <string.h>
00031 #include <errno.h>
00032 #include <unistd.h>
00033
00034 #include <sys/types.h>
00035 #include <sys/stat.h>
00036 #include <fcntl.h>
00037
00038 #include "avrerror.h"
00039 #include "avrmalloc.h"
00040 #include "avrclass.h"
00041 #include "utils.h"
00042 #include "callback.h"
00043 #include "op_names.h"
00044
00045 #include "storage.h"
00046 #include "flash.h"
00047
00048 #include "vdevs.h"
00049 #include "memory.h"
00050 #include "stack.h"
00051 #include "register.h"
00052 #include "sram.h"
00053 #include "eeprom.h"
00054 #include "timers.h"
00055 #include "ports.h"
00056
00057 #include "avrcore.h"
00058
00059 #include "display.h"
00060
00061 static uint8_t eeprom_reg_read (VDevice *dev, int addr);
00062 static void eeprom_reg_write (VDevice *dev, int addr, uint8_t val);
00063 static void eeprom_reg_reset (VDevice *dev);
00064 static void eeprom_wr_eecr (EEProm *ee, uint8_t val);
00065
00066 static int eeprom_wr_op_cb (uint64_t time, AvrClass *data);
00067 static int eeprom_mwe_clr_cb (uint64_t time, AvrClass *data);
00068
00069
00070 static VDevice *global_eeprom;
00071
00072
00073
00074
00075
00076
00077
00078 VDevice *
00079 eeprom_create (int addr, char *name, int rel_addr, void *data)
00080 {
00081 if (rel_addr == 0 && addr != EECR_ADDR)
00082 avr_error("Attempt to create EEPROM control register at unknown address: 0x%02x != 0x%02x",
00083 addr, EECR_ADDR);
00084
00085 return global_eeprom;
00086 }
00087
00088 EEProm *
00089 eeprom_new (int size, uint8_t eecr_mask)
00090 {
00091 EEProm *eeprom;
00092
00093 if (global_eeprom != NULL)
00094 avr_error("Global EEPROM does already exist");
00095
00096 eeprom = avr_new (EEProm, 1);
00097 eeprom_construct (eeprom, size, eecr_mask);
00098 class_overload_destroy ((AvrClass *)eeprom, eeprom_destroy);
00099
00100 global_eeprom = (VDevice *)eeprom;
00101
00102 return eeprom;
00103 }
00104
00105 void
00106 eeprom_construct (EEProm *eeprom, int size, uint8_t eecr_mask)
00107 {
00108 int i;
00109
00110 if (eeprom == NULL)
00111 avr_error ("passed null ptr");
00112
00113 eeprom->stor = storage_new (0 , size);
00114
00115
00116 for (i = 0; i < size; i++)
00117 storage_writeb (eeprom->stor, i, 0xff);
00118
00119 eeprom->eecr_mask = eecr_mask;
00120
00121 eeprom_reg_reset ((VDevice *)eeprom);
00122
00123 vdev_construct ((VDevice *)eeprom, eeprom_reg_read, eeprom_reg_write,
00124 eeprom_reg_reset, vdev_def_AddAddr);
00125 }
00126
00127 void
00128 eeprom_destroy (void *eeprom)
00129 {
00130 EEProm *_eeprom = (EEProm *)eeprom;
00131
00132 if (eeprom == NULL)
00133 return;
00134
00135 class_unref ((AvrClass *)_eeprom->stor);
00136
00137 vdev_destroy (eeprom);
00138 }
00139
00140 int
00141 eeprom_get_size (EEProm *eeprom)
00142 {
00143 return storage_get_size (eeprom->stor);
00144 }
00145
00146 static uint8_t
00147 eeprom_reg_read (VDevice *dev, int addr)
00148 {
00149 EEProm *ee = (EEProm *)dev;
00150
00151 switch (addr)
00152 {
00153 case EECR_ADDR:
00154 return ee->eecr;
00155 case EEDR_ADDR:
00156 return ee->eedr;
00157 case EEARL_ADDR:
00158 return ee->eearl;
00159 case EEARH_ADDR:
00160 return ee->eearh;
00161 }
00162 avr_error ("Bad address: %d", addr);
00163 return 0;
00164 }
00165
00166 static void
00167 eeprom_reg_write (VDevice *dev, int addr, uint8_t val)
00168 {
00169 EEProm *ee = (EEProm *)dev;
00170
00171 if (ee->eecr & mask_EEWE)
00172 {
00173
00174
00175
00176
00177
00178
00179
00180 avr_error ("Attempt to write to EEPROM I/O reg during write "
00181 "operation");
00182 }
00183
00184 switch (addr)
00185 {
00186 case EECR_ADDR:
00187 eeprom_wr_eecr (ee, val);
00188 return;
00189 case EEDR_ADDR:
00190 ee->eedr = val;
00191 return;
00192 case EEARL_ADDR:
00193 ee->eearl = val;
00194 return;
00195 case EEARH_ADDR:
00196 ee->eearh = val;
00197 return;
00198 }
00199 avr_error ("Bad address: %d", addr);
00200 }
00201
00202 static void
00203 eeprom_reg_reset (VDevice *dev)
00204 {
00205 EEProm *ee = (EEProm *)dev;
00206
00207 ee->wr_op_cb = NULL;
00208 ee->wr_op_clk = 0;
00209
00210 ee->mwe_clr_cb = NULL;
00211 ee->mwe_clk = 0;
00212
00213 ee->eecr = ee->eedr = ee->eearl = ee->eearh = 0;
00214 }
00215
00216 static void
00217 eeprom_wr_eecr (EEProm *ee, uint8_t val)
00218 {
00219 int addr = (ee->eearh << 8) | ee->eearl;
00220
00221 CallBack *cb;
00222
00223 switch (val & ee->eecr_mask)
00224 {
00225 case mask_EERE:
00226
00227
00228
00229
00230 ee->eedr = storage_readb (ee->stor, addr);
00231 break;
00232
00233 case mask_EEWE:
00234 if (((ee->eecr_mask & mask_EEMWE) == 0)
00235
00236 || (ee->eecr & ee->eecr_mask & mask_EEMWE))
00237
00238 {
00239 ee->eecr |= mask_EEWE;
00240 ee->wr_op_clk = EEPROM_WR_OP_CLKS;
00241
00242
00243 if (ee->wr_op_cb == NULL)
00244 {
00245 cb = callback_new (eeprom_wr_op_cb, (AvrClass *)ee);
00246 ee->wr_op_cb = cb;
00247 avr_core_async_cb_add ((AvrCore *)
00248 vdev_get_core ((VDevice *)ee), cb);
00249 }
00250 }
00251 break;
00252
00253 case mask_EEMWE:
00254 ee->eecr |= mask_EEMWE;
00255 ee->mwe_clk = EEPROM_MWE_CLKS;
00256
00257 if (ee->mwe_clr_cb == NULL)
00258 {
00259 cb = callback_new (eeprom_mwe_clr_cb, (AvrClass *)ee);
00260 ee->mwe_clr_cb = cb;
00261 avr_core_clk_cb_add ((AvrCore *)vdev_get_core ((VDevice *)ee),
00262 cb);
00263 }
00264 break;
00265
00266 case (mask_EEMWE | mask_EEWE):
00267
00268 eeprom_wr_eecr (ee, mask_EEWE);
00269 break;
00270
00271 default:
00272 avr_error ("Unknown eeprom control register write operation: "
00273 "0x%02x", val);
00274 }
00275 }
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285 static int
00286 eeprom_wr_op_cb (uint64_t time, AvrClass *data)
00287 {
00288 EEProm *ee = (EEProm *)data;
00289 int addr;
00290
00291
00292
00293
00294
00295
00296
00297
00298 if (ee->wr_op_clk > 0)
00299 {
00300
00301 ee->wr_op_clk--;
00302 return CB_RET_RETAIN;
00303 }
00304
00305
00306 addr = (ee->eearh << 8) | ee->eearl;
00307
00308 display_eeprom (addr, 1, &ee->eedr);
00309 storage_writeb (ee->stor, addr, ee->eedr);
00310
00311
00312 ee->eecr &= ~(mask_EEWE);
00313 ee->wr_op_cb = NULL;
00314
00315 return CB_RET_REMOVE;
00316 }
00317
00318
00319
00320
00321
00322 static int
00323 eeprom_mwe_clr_cb (uint64_t time, AvrClass *data)
00324 {
00325 EEProm *ee = (EEProm *)data;
00326
00327 if (ee->mwe_clk > 0)
00328 {
00329 ee->mwe_clk--;
00330 return CB_RET_RETAIN;
00331 }
00332
00333 ee->eecr &= ~(mask_EEMWE);
00334 ee->mwe_clr_cb = NULL;
00335
00336 return CB_RET_REMOVE;
00337 }
00338
00339 static int
00340 eeprom_load_from_bin_file (EEProm *eeprom, char *file)
00341 {
00342 int fd, res;
00343 int addr = 0;
00344 uint8_t datum;
00345
00346 fd = open (file, O_RDONLY);
00347 if (fd < 0)
00348 avr_error ("Couldn't open binary eeprom image file: %s: %s", file,
00349 strerror (errno));
00350
00351 while ((res = read (fd, &datum, sizeof (datum))) != 0)
00352 {
00353 if (res == -1)
00354 avr_error ("Error reading binary eeprom image file: %s: %s", file,
00355 strerror (errno));
00356
00357 storage_writeb (eeprom->stor, addr, datum);
00358
00359 addr++;
00360 }
00361
00362 close (fd);
00363
00364 return 0;
00365 }
00366
00367
00368
00369 int
00370 eeprom_load_from_file (EEProm *eeprom, char *file, int format)
00371 {
00372 switch (format)
00373 {
00374 case FFMT_BIN:
00375 return eeprom_load_from_bin_file (eeprom, file);
00376 case FFMT_IHEX:
00377 case FFMT_ELF:
00378 default:
00379 avr_warning ("Unsupported file format\n");
00380 }
00381
00382 return -1;
00383 }
00384
00385 void
00386 eeprom_dump_core (EEProm *eeprom, FILE * f_core)
00387 {
00388 int i;
00389 int dup = 0;
00390 int ndat = 16;
00391 char line[80];
00392 char last_line[80];
00393 char buf[80];
00394 int size = storage_get_size (eeprom->stor);
00395
00396 fprintf (f_core, "EEPROM Memory Dump:\n");
00397
00398 line[0] = last_line[0] = '\0';
00399
00400 for (i = 0; i < size; i++)
00401 {
00402 if (((i % ndat) == 0) && strlen (line))
00403 {
00404 if (strncmp (line, last_line, 80) == 0)
00405 {
00406 dup++;
00407 }
00408 else
00409 {
00410 if (dup > 0)
00411 fprintf (f_core, " -- last line repeats --\n");
00412 fprintf (f_core, "%04x : %s\n", i - ndat, line);
00413 dup = 0;
00414 }
00415 strncpy (last_line, line, 80);
00416 line[0] = '\0';
00417 }
00418 snprintf (buf, 80, "%02x ", storage_readb (eeprom->stor, i));
00419 strncat (line, buf, 80);
00420 }
00421 if (dup > 0)
00422 {
00423 fprintf (f_core, " -- last line repeats --\n");
00424 fprintf (f_core, "%04x : %s\n", i - ndat, line);
00425 }
00426 fprintf (f_core, "\n");
00427 }