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