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 EEProm *
00070 eeprom_new (int size, uint8_t eecr_mask)
00071 {
00072 EEProm *eeprom;
00073
00074 eeprom = avr_new (EEProm, 1);
00075 eeprom_construct (eeprom, size, eecr_mask);
00076 class_overload_destroy ((AvrClass *)eeprom, eeprom_destroy);
00077
00078 return eeprom;
00079 }
00080
00081 void
00082 eeprom_construct (EEProm *eeprom, int size, uint8_t eecr_mask)
00083 {
00084 int i;
00085
00086 if (eeprom == NULL)
00087 avr_error ("passed null ptr");
00088
00089 eeprom->stor = storage_new (0 , size);
00090
00091
00092 for (i = 0; i < size; i++)
00093 storage_writeb (eeprom->stor, i, 0xff);
00094
00095 eeprom->eecr_mask = eecr_mask;
00096
00097 eeprom_reg_reset ((VDevice *)eeprom);
00098
00099 vdev_construct ((VDevice *)eeprom, eeprom_reg_read, eeprom_reg_write,
00100 eeprom_reg_reset, vdev_def_AddAddr);
00101 }
00102
00103 void
00104 eeprom_destroy (void *eeprom)
00105 {
00106 EEProm *_eeprom = (EEProm *)eeprom;
00107
00108 if (eeprom == NULL)
00109 return;
00110
00111 class_unref ((AvrClass *)_eeprom->stor);
00112
00113 vdev_destroy (eeprom);
00114 }
00115
00116 int
00117 eeprom_get_size (EEProm *eeprom)
00118 {
00119 return storage_get_size (eeprom->stor);
00120 }
00121
00122 static uint8_t
00123 eeprom_reg_read (VDevice *dev, int addr)
00124 {
00125 EEProm *ee = (EEProm *)dev;
00126
00127 switch (addr)
00128 {
00129 case EECR_ADDR:
00130 return ee->eecr;
00131 case EEDR_ADDR:
00132 return ee->eedr;
00133 case EEARL_ADDR:
00134 return ee->eearl;
00135 case EEARH_ADDR:
00136 return ee->eearh;
00137 }
00138 avr_error ("Bad address: %d", addr);
00139 return 0;
00140 }
00141
00142 static void
00143 eeprom_reg_write (VDevice *dev, int addr, uint8_t val)
00144 {
00145 EEProm *ee = (EEProm *)dev;
00146
00147 if (ee->eecr & mask_EEWE)
00148 {
00149
00150
00151
00152
00153
00154
00155
00156 avr_error ("Attempt to write to EEPROM I/O reg during write "
00157 "operation");
00158 }
00159
00160 switch (addr)
00161 {
00162 case EECR_ADDR:
00163 eeprom_wr_eecr (ee, val);
00164 return;
00165 case EEDR_ADDR:
00166 ee->eedr = val;
00167 return;
00168 case EEARL_ADDR:
00169 ee->eearl = val;
00170 return;
00171 case EEARH_ADDR:
00172 ee->eearh = val;
00173 return;
00174 }
00175 avr_error ("Bad address: %d", addr);
00176 }
00177
00178 static void
00179 eeprom_reg_reset (VDevice *dev)
00180 {
00181 EEProm *ee = (EEProm *)dev;
00182
00183 ee->wr_op_cb = NULL;
00184 ee->wr_op_clk = 0;
00185
00186 ee->mwe_clr_cb = NULL;
00187 ee->mwe_clk = 0;
00188
00189 ee->eecr = ee->eedr = ee->eearl = ee->eearh = 0;
00190 }
00191
00192 static void
00193 eeprom_wr_eecr (EEProm *ee, uint8_t val)
00194 {
00195 int addr = (ee->eearh << 8) | ee->eearl;
00196
00197 CallBack *cb;
00198
00199 switch (val & ee->eecr_mask)
00200 {
00201 case mask_EERE:
00202
00203
00204
00205
00206 ee->eedr = storage_readb (ee->stor, addr);
00207 break;
00208
00209 case mask_EEWE:
00210 if (((ee->eecr_mask & mask_EEMWE) == 0)
00211
00212 || (ee->eecr & ee->eecr_mask & mask_EEMWE))
00213
00214 {
00215 ee->eecr |= mask_EEWE;
00216 ee->wr_op_clk = EEPROM_WR_OP_CLKS;
00217
00218
00219 if (ee->wr_op_cb == NULL)
00220 {
00221 cb = callback_new (eeprom_wr_op_cb, (AvrClass *)ee);
00222 ee->wr_op_cb = cb;
00223 avr_core_async_cb_add ((AvrCore *)
00224 vdev_get_core ((VDevice *)ee), cb);
00225 }
00226 }
00227 break;
00228
00229 case mask_EEMWE:
00230 ee->eecr |= mask_EEMWE;
00231 ee->mwe_clk = EEPROM_MWE_CLKS;
00232
00233 if (ee->mwe_clr_cb == NULL)
00234 {
00235 cb = callback_new (eeprom_mwe_clr_cb, (AvrClass *)ee);
00236 ee->mwe_clr_cb = cb;
00237 avr_core_clk_cb_add ((AvrCore *)vdev_get_core ((VDevice *)ee),
00238 cb);
00239 }
00240 break;
00241
00242 case (mask_EEMWE | mask_EEWE):
00243
00244 eeprom_wr_eecr (ee, mask_EEWE);
00245 break;
00246
00247 default:
00248 avr_error ("Unknown eeprom control register write operation: "
00249 "0x%02x", val);
00250 }
00251 }
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261 static int
00262 eeprom_wr_op_cb (uint64_t time, AvrClass *data)
00263 {
00264 EEProm *ee = (EEProm *)data;
00265 int addr;
00266
00267
00268
00269
00270
00271
00272
00273
00274 if (ee->wr_op_clk > 0)
00275 {
00276
00277 ee->wr_op_clk--;
00278 return CB_RET_RETAIN;
00279 }
00280
00281
00282 addr = (ee->eearh << 8) | ee->eearl;
00283 avr_warning ("writing 0x%02x to eeprom at 0x%04x\n", ee->eedr, addr);
00284 display_eeprom (addr, 1, &ee->eedr);
00285 storage_writeb (ee->stor, addr, ee->eedr);
00286
00287
00288 ee->eecr &= ~(mask_EEWE);
00289 ee->wr_op_cb = NULL;
00290
00291 return CB_RET_REMOVE;
00292 }
00293
00294
00295
00296
00297
00298 static int
00299 eeprom_mwe_clr_cb (uint64_t time, AvrClass *data)
00300 {
00301 EEProm *ee = (EEProm *)data;
00302
00303 if (ee->mwe_clk > 0)
00304 {
00305 ee->mwe_clk--;
00306 return CB_RET_RETAIN;
00307 }
00308
00309 ee->eecr &= ~(mask_EEMWE);
00310 ee->mwe_clr_cb = NULL;
00311
00312 return CB_RET_REMOVE;
00313 }
00314
00315 static int
00316 eeprom_load_from_bin_file (EEProm *eeprom, char *file)
00317 {
00318 int fd, res;
00319 int addr = 0;
00320 uint8_t datum;
00321
00322 fd = open (file, O_RDONLY);
00323 if (fd < 0)
00324 avr_error ("Couldn't open binary eeprom image file: %s: %s", file,
00325 strerror (errno));
00326
00327 while ((res = read (fd, &datum, sizeof (datum))) != 0)
00328 {
00329 if (res == -1)
00330 avr_error ("Error reading binary eeprom image file: %s: %s", file,
00331 strerror (errno));
00332
00333 storage_writeb (eeprom->stor, addr, datum);
00334
00335 addr++;
00336 }
00337
00338 close (fd);
00339
00340 return 0;
00341 }
00342
00343
00344
00345 int
00346 eeprom_load_from_file (EEProm *eeprom, char *file, int format)
00347 {
00348 switch (format)
00349 {
00350 case FFMT_BIN:
00351 return eeprom_load_from_bin_file (eeprom, file);
00352 case FFMT_IHEX:
00353 case FFMT_ELF:
00354 default:
00355 avr_warning ("Unsupported file format\n");
00356 }
00357
00358 return -1;
00359 }
00360
00361 void
00362 eeprom_dump_core (EEProm *eeprom, FILE * f_core)
00363 {
00364 int i;
00365 int dup = 0;
00366 int ndat = 16;
00367 char line[80];
00368 char last_line[80];
00369 char buf[80];
00370 int size = storage_get_size (eeprom->stor);
00371
00372 fprintf (f_core, "EEPROM Memory Dump:\n");
00373
00374 line[0] = last_line[0] = '\0';
00375
00376 for (i = 0; i < size; i++)
00377 {
00378 if (((i % ndat) == 0) && strlen (line))
00379 {
00380 if (strncmp (line, last_line, 80) == 0)
00381 {
00382 dup++;
00383 }
00384 else
00385 {
00386 if (dup > 0)
00387 fprintf (f_core, " -- last line repeats --\n");
00388 fprintf (f_core, "%04x : %s\n", i - ndat, line);
00389 dup = 0;
00390 }
00391 strncpy (last_line, line, 80);
00392 line[0] = '\0';
00393 }
00394 snprintf (buf, 80, "%02x ", storage_readb (eeprom->stor, i));
00395 strncat (line, buf, 80);
00396 }
00397 if (dup > 0)
00398 {
00399 fprintf (f_core, " -- last line repeats --\n");
00400 fprintf (f_core, "%04x : %s\n", i - ndat, line);
00401 }
00402 fprintf (f_core, "\n");
00403 }