Main Page | File List | Globals | Related Pages

eeprom.c

00001 /* 00002 * $Id: eeprom.c,v 1.19 2003/12/01 09:10:14 troth Exp $ 00003 * 00004 **************************************************************************** 00005 * 00006 * simulavr - A simulator for the Atmel AVR family of microcontrollers. 00007 * Copyright (C) 2001, 2002, 2003 Theodore A. Roth 00008 * 00009 * This program is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software 00021 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 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 /*base */ , size); 00092 00093 /* init eeprom to ones */ 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 * From the 8515 data sheet: The user should poll the EEWE bit before 00154 * starting the read operaton. If a write operation is in progress 00155 * when new data or address is written to the EEPROM I/O registers, 00156 * the write operation will be interrupted, and the result is 00157 * undefined. 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 * we never need to set EERE bit one, 00225 * just more data from eeprom array into eedr. 00226 */ 00227 ee->eedr = storage_readb (ee->stor, addr); 00228 break; 00229 00230 case mask_EEWE: 00231 if (((ee->eecr_mask & mask_EEMWE) == 0) /* device has no MWE 00232 function */ 00233 || (ee->eecr & ee->eecr_mask & mask_EEMWE)) /* or MWE bit is 00234 set */ 00235 { 00236 ee->eecr |= mask_EEWE; 00237 ee->wr_op_clk = EEPROM_WR_OP_CLKS; 00238 00239 /* start write operation */ 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 /* just call this function again, but without EEMWE set in val */ 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 * The data sheets say that a write operation takes 2.5 to 4.0 ms to complete 00276 * depending on Vcc voltage. Since the get_program_time() function only has 00277 * 10 ms resolution, we'll just simulate a timer with counting down from 00278 * EEPROM_WR_OP_CLKS to zero. 2500 clocks would be 2.5 ms if simulator is 00279 * running at 1 MHz. I really don't think that this variation should be 00280 * critical in most apps, but I'd wouldn't mind being proven wrong. 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 * FIXME: At some point in the future, we might need to check if 00290 * any of the I/O registers have been written to during the write 00291 * operation which would cause the write op to be interrupted. 00292 * Right now, the simulator is aborted in that situation. 00293 */ 00294 00295 if (ee->wr_op_clk > 0) 00296 { 00297 /* write is not complete yet */ 00298 ee->wr_op_clk--; 00299 return CB_RET_RETAIN; 00300 } 00301 00302 /* write the data in eedr into eeprom at addr */ 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 /* Now it's ok to start another write operation */ 00309 ee->eecr &= ~(mask_EEWE); /* clear the write enable bit */ 00310 ee->wr_op_cb = NULL; /* remove callback */ 00311 00312 return CB_RET_REMOVE; 00313 } 00314 00315 /* 00316 * Once set, the hardware will automatically clear the EEMWE bit 00317 * after EEPROM_MWE_CLKS clock cycles. 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); /* clear the EEMWE bit */ 00331 ee->mwe_clr_cb = NULL; /* remove callback */ 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 /** \brief Load data into eeprom from a file. */ 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 }

Automatically generated by Doxygen 1.3.8 on 11 Aug 2004.