eeprom.c
1 /*
2  * $Id: eeprom.c,v 1.21 2008/03/19 22:39:02 joerg_wunsch Exp $
3  *
4  ****************************************************************************
5  *
6  * simulavr - A simulator for the Atmel AVR family of microcontrollers.
7  * Copyright (C) 2001, 2002, 2003, 2004 Theodore A. Roth
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22  *
23  ****************************************************************************
24  */
25 
26 #include <config.h>
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <unistd.h>
33 
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <fcntl.h>
37 
38 #include "avrerror.h"
39 #include "avrmalloc.h"
40 #include "avrclass.h"
41 #include "utils.h"
42 #include "callback.h"
43 #include "op_names.h"
44 
45 #include "storage.h"
46 #include "flash.h"
47 
48 #include "vdevs.h"
49 #include "memory.h"
50 #include "stack.h"
51 #include "register.h"
52 #include "sram.h"
53 #include "eeprom.h"
54 #include "timers.h"
55 #include "ports.h"
56 
57 #include "avrcore.h"
58 
59 #include "display.h"
60 
61 static uint8_t eeprom_reg_read (VDevice *dev, int addr);
62 static void eeprom_reg_write (VDevice *dev, int addr, uint8_t val);
63 static void eeprom_reg_reset (VDevice *dev);
64 static void eeprom_wr_eecr (EEProm *ee, uint8_t val);
65 
66 static int eeprom_wr_op_cb (uint64_t time, AvrClass *data);
67 static int eeprom_mwe_clr_cb (uint64_t time, AvrClass *data);
68 
69 /* XXX */
70 static VDevice *global_eeprom;
71 
72 /**
73  * \brief Create a new EEPROM control register set instance.
74  *
75  * This should only be used in DevSuppDefn initializers.
76  */
77 
78 VDevice *
79 eeprom_create (int addr, char *name, int rel_addr, void *data)
80 {
81  if (rel_addr == 0 && addr != EECR_ADDR)
82  avr_error("Attempt to create EEPROM control register at unknown address: 0x%02x != 0x%02x",
83  addr, EECR_ADDR);
84 
85  return global_eeprom;
86 }
87 
88 EEProm *
89 eeprom_new (int size, uint8_t eecr_mask)
90 {
91  EEProm *eeprom;
92 
93  if (global_eeprom != NULL)
94  avr_error("Global EEPROM does already exist");
95 
96  eeprom = avr_new (EEProm, 1);
97  eeprom_construct (eeprom, size, eecr_mask);
98  class_overload_destroy ((AvrClass *)eeprom, eeprom_destroy);
99 
100  global_eeprom = (VDevice *)eeprom;
101 
102  return eeprom;
103 }
104 
105 void
106 eeprom_construct (EEProm *eeprom, int size, uint8_t eecr_mask)
107 {
108  int i;
109 
110  if (eeprom == NULL)
111  avr_error ("passed null ptr");
112 
113  eeprom->stor = storage_new (0 /*base */ , size);
114 
115  /* init eeprom to ones */
116  for (i = 0; i < size; i++)
117  storage_writeb (eeprom->stor, i, 0xff);
118 
119  eeprom->eecr_mask = eecr_mask;
120 
121  eeprom_reg_reset ((VDevice *)eeprom);
122 
123  vdev_construct ((VDevice *)eeprom, eeprom_reg_read, eeprom_reg_write,
124  eeprom_reg_reset, vdev_def_AddAddr);
125 }
126 
127 void
128 eeprom_destroy (void *eeprom)
129 {
130  EEProm *_eeprom = (EEProm *)eeprom;
131 
132  if (eeprom == NULL)
133  return;
134 
135  class_unref ((AvrClass *)_eeprom->stor);
136 
137  vdev_destroy (eeprom);
138 }
139 
140 int
141 eeprom_get_size (EEProm *eeprom)
142 {
143  return storage_get_size (eeprom->stor);
144 }
145 
146 static uint8_t
147 eeprom_reg_read (VDevice *dev, int addr)
148 {
149  EEProm *ee = (EEProm *)dev;
150 
151  switch (addr)
152  {
153  case EECR_ADDR:
154  return ee->eecr;
155  case EEDR_ADDR:
156  return ee->eedr;
157  case EEARL_ADDR:
158  return ee->eearl;
159  case EEARH_ADDR:
160  return ee->eearh;
161  }
162  avr_error ("Bad address: %d", addr);
163  return 0;
164 }
165 
166 static void
167 eeprom_reg_write (VDevice *dev, int addr, uint8_t val)
168 {
169  EEProm *ee = (EEProm *)dev;
170 
171  if (ee->eecr & mask_EEWE)
172  {
173  /*
174  * From the 8515 data sheet: The user should poll the EEWE bit before
175  * starting the read operaton. If a write operation is in progress
176  * when new data or address is written to the EEPROM I/O registers,
177  * the write operation will be interrupted, and the result is
178  * undefined.
179  */
180  avr_error ("Attempt to write to EEPROM I/O reg during write "
181  "operation");
182  }
183 
184  switch (addr)
185  {
186  case EECR_ADDR:
187  eeprom_wr_eecr (ee, val);
188  return;
189  case EEDR_ADDR:
190  ee->eedr = val;
191  return;
192  case EEARL_ADDR:
193  ee->eearl = val;
194  return;
195  case EEARH_ADDR:
196  ee->eearh = val;
197  return;
198  }
199  avr_error ("Bad address: %d", addr);
200 }
201 
202 static void
203 eeprom_reg_reset (VDevice *dev)
204 {
205  EEProm *ee = (EEProm *)dev;
206 
207  ee->wr_op_cb = NULL;
208  ee->wr_op_clk = 0;
209 
210  ee->mwe_clr_cb = NULL;
211  ee->mwe_clk = 0;
212 
213  ee->eecr = ee->eedr = ee->eearl = ee->eearh = 0;
214 }
215 
216 static void
217 eeprom_wr_eecr (EEProm *ee, uint8_t val)
218 {
219  int addr = (ee->eearh << 8) | ee->eearl;
220 
221  CallBack *cb;
222 
223  switch (val & ee->eecr_mask)
224  {
225  case mask_EERE:
226  /*
227  * we never need to set EERE bit one,
228  * just more data from eeprom array into eedr.
229  */
230  ee->eedr = storage_readb (ee->stor, addr);
231  break;
232 
233  case mask_EEWE:
234  if (((ee->eecr_mask & mask_EEMWE) == 0) /* device has no MWE
235  function */
236  || (ee->eecr & ee->eecr_mask & mask_EEMWE)) /* or MWE bit is
237  set */
238  {
239  ee->eecr |= mask_EEWE;
240  ee->wr_op_clk = EEPROM_WR_OP_CLKS;
241 
242  /* start write operation */
243  if (ee->wr_op_cb == NULL)
244  {
245  cb = callback_new (eeprom_wr_op_cb, (AvrClass *)ee);
246  ee->wr_op_cb = cb;
247  avr_core_async_cb_add ((AvrCore *)
248  vdev_get_core ((VDevice *)ee), cb);
249  }
250  }
251  break;
252 
253  case mask_EEMWE:
254  ee->eecr |= mask_EEMWE;
255  ee->mwe_clk = EEPROM_MWE_CLKS;
256 
257  if (ee->mwe_clr_cb == NULL)
258  {
259  cb = callback_new (eeprom_mwe_clr_cb, (AvrClass *)ee);
260  ee->mwe_clr_cb = cb;
261  avr_core_clk_cb_add ((AvrCore *)vdev_get_core ((VDevice *)ee),
262  cb);
263  }
264  break;
265 
266  case (mask_EEMWE | mask_EEWE):
267  /* just call this function again, but without EEMWE set in val */
268  eeprom_wr_eecr (ee, mask_EEWE);
269  break;
270 
271  default:
272  avr_error ("Unknown eeprom control register write operation: "
273  "0x%02x", val);
274  }
275 }
276 
277 /*
278  * The data sheets say that a write operation takes 2.5 to 4.0 ms to complete
279  * depending on Vcc voltage. Since the get_program_time() function only has
280  * 10 ms resolution, we'll just simulate a timer with counting down from
281  * EEPROM_WR_OP_CLKS to zero. 2500 clocks would be 2.5 ms if simulator is
282  * running at 1 MHz. I really don't think that this variation should be
283  * critical in most apps, but I'd wouldn't mind being proven wrong.
284  */
285 static int
286 eeprom_wr_op_cb (uint64_t time, AvrClass *data)
287 {
288  EEProm *ee = (EEProm *)data;
289  int addr;
290 
291  /*
292  * FIXME: At some point in the future, we might need to check if
293  * any of the I/O registers have been written to during the write
294  * operation which would cause the write op to be interrupted.
295  * Right now, the simulator is aborted in that situation.
296  */
297 
298  if (ee->wr_op_clk > 0)
299  {
300  /* write is not complete yet */
301  ee->wr_op_clk--;
302  return CB_RET_RETAIN;
303  }
304 
305  /* write the data in eedr into eeprom at addr */
306  addr = (ee->eearh << 8) | ee->eearl;
307  //avr_warning ("writing 0x%02x to eeprom at 0x%04x\n", ee->eedr, addr);
308  display_eeprom (addr, 1, &ee->eedr);
309  storage_writeb (ee->stor, addr, ee->eedr);
310 
311  /* Now it's ok to start another write operation */
312  ee->eecr &= ~(mask_EEWE); /* clear the write enable bit */
313  ee->wr_op_cb = NULL; /* remove callback */
314 
315  return CB_RET_REMOVE;
316 }
317 
318 /*
319  * Once set, the hardware will automatically clear the EEMWE bit
320  * after EEPROM_MWE_CLKS clock cycles.
321  */
322 static int
323 eeprom_mwe_clr_cb (uint64_t time, AvrClass *data)
324 {
325  EEProm *ee = (EEProm *)data;
326 
327  if (ee->mwe_clk > 0)
328  {
329  ee->mwe_clk--;
330  return CB_RET_RETAIN;
331  }
332 
333  ee->eecr &= ~(mask_EEMWE); /* clear the EEMWE bit */
334  ee->mwe_clr_cb = NULL; /* remove callback */
335 
336  return CB_RET_REMOVE;
337 }
338 
339 static int
340 eeprom_load_from_bin_file (EEProm *eeprom, char *file)
341 {
342  int fd, res;
343  int addr = 0;
344  uint8_t datum;
345 
346  fd = open (file, O_RDONLY);
347  if (fd < 0)
348  avr_error ("Couldn't open binary eeprom image file: %s: %s", file,
349  strerror (errno));
350 
351  while ((res = read (fd, &datum, sizeof (datum))) != 0)
352  {
353  if (res == -1)
354  avr_error ("Error reading binary eeprom image file: %s: %s", file,
355  strerror (errno));
356 
357  storage_writeb (eeprom->stor, addr, datum);
358 
359  addr++;
360  }
361 
362  close (fd);
363 
364  return 0;
365 }
366 
367 /** \brief Load data into eeprom from a file. */
368 
369 int
370 eeprom_load_from_file (EEProm *eeprom, char *file, int format)
371 {
372  switch (format)
373  {
374  case FFMT_BIN:
375  return eeprom_load_from_bin_file (eeprom, file);
376  case FFMT_IHEX:
377  case FFMT_ELF:
378  default:
379  avr_warning ("Unsupported file format\n");
380  }
381 
382  return -1;
383 }
384 
385 void
386 eeprom_dump_core (EEProm *eeprom, FILE * f_core)
387 {
388  int i;
389  int dup = 0;
390  int ndat = 16;
391  char line[80];
392  char last_line[80];
393  char buf[80];
394  int size = storage_get_size (eeprom->stor);
395 
396  fprintf (f_core, "EEPROM Memory Dump:\n");
397 
398  line[0] = last_line[0] = '\0';
399 
400  for (i = 0; i < size; i++)
401  {
402  if (((i % ndat) == 0) && strlen (line))
403  {
404  if (strncmp (line, last_line, 80) == 0)
405  {
406  dup++;
407  }
408  else
409  {
410  if (dup > 0)
411  fprintf (f_core, " -- last line repeats --\n");
412  fprintf (f_core, "%04x : %s\n", i - ndat, line);
413  dup = 0;
414  }
415  strncpy (last_line, line, 80);
416  line[0] = '\0';
417  }
418  snprintf (buf, 80, "%02x ", storage_readb (eeprom->stor, i));
419  strncat (line, buf, 80 - strlen(line) - 1);
420  }
421  if (dup > 0)
422  {
423  fprintf (f_core, " -- last line repeats --\n");
424  fprintf (f_core, "%04x : %s\n", i - ndat, line);
425  }
426  fprintf (f_core, "\n");
427 }

Automatically generated by Doxygen 1.8.2 on Fri Mar 20 2015.