Main Page | File List | Globals | Related Pages

memory.c

Go to the documentation of this file.
00001 /* 00002 * $Id: memory.c,v 1.17 2003/12/01 09:10:15 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 /** 00027 * \file memory.c 00028 * \brief Memory access functions. 00029 * 00030 * This module provides functions for reading and writing to simulated memory. 00031 * The Memory class is a subclass of AvrClass. 00032 */ 00033 00034 #include <config.h> 00035 00036 #include <stdio.h> 00037 #include <stdlib.h> 00038 #include <string.h> 00039 00040 #include "avrerror.h" 00041 #include "avrmalloc.h" 00042 #include "avrclass.h" 00043 #include "utils.h" 00044 #include "callback.h" 00045 #include "op_names.h" 00046 00047 #include "storage.h" 00048 #include "flash.h" 00049 00050 #include "vdevs.h" 00051 #include "memory.h" 00052 #include "stack.h" 00053 #include "register.h" 00054 #include "sram.h" 00055 #include "eeprom.h" 00056 #include "timers.h" 00057 #include "ports.h" 00058 00059 #include "avrcore.h" 00060 00061 #include "display.h" 00062 00063 /** \brief Allocates memory for a new memory object. */ 00064 00065 Memory * 00066 mem_new (void) 00067 { 00068 Memory *mem; 00069 00070 mem = avr_new (Memory, 1); 00071 mem_construct (mem); 00072 class_overload_destroy ((AvrClass *)mem, mem_destroy); 00073 00074 return mem; 00075 } 00076 00077 /** \brief Constructor for the memory object. */ 00078 00079 void 00080 mem_construct (Memory *mem) 00081 { 00082 if (mem == NULL) 00083 avr_error ("passed null ptr"); 00084 00085 class_construct ((AvrClass *)mem); 00086 00087 mem->dev = NULL; 00088 } 00089 00090 /** \brief Descructor for the memory object. */ 00091 00092 void 00093 mem_destroy (void *mem) 00094 { 00095 Memory *this = (Memory *)mem; 00096 00097 if (mem == NULL) 00098 return; 00099 00100 dlist_delete_all (this->dev); 00101 00102 class_destroy (mem); 00103 } 00104 00105 /** \brief Attach a device to the device list. 00106 00107 Devices that are accessed more often should be attached 00108 last so that they will be at the front of the list. 00109 00110 A default virtual device can be overridden by attaching 00111 a new device ahead of it in the list. */ 00112 00113 void 00114 mem_attach (Memory *mem, VDevice *dev) 00115 { 00116 if (mem == NULL) 00117 avr_error ("passed null ptr"); 00118 00119 if (dev == NULL) 00120 avr_error ("attempt to attach null device"); 00121 00122 /* push the new dev to front of list to allow overriding */ 00123 mem->dev = dlist_add_head (mem->dev, (AvrClass *)dev); 00124 } 00125 00126 /** \brief Find the VDevice associated with the given address. */ 00127 00128 VDevice * 00129 mem_get_vdevice_by_addr (Memory *mem, int addr) 00130 { 00131 return (VDevice *)dlist_lookup (mem->dev, (AvrClass *)&addr, 00132 vdev_addr_cmp); 00133 } 00134 00135 /** \brief Find the VDevice associated with the given name. */ 00136 00137 VDevice * 00138 mem_get_vdevice_by_name (Memory *mem, char *name) 00139 { 00140 return (VDevice *)dlist_lookup (mem->dev, (AvrClass *)name, 00141 vdev_name_cmp); 00142 } 00143 00144 /** \brief Reads byte from memory and sanity-checks for valid address. 00145 * 00146 * \param mem A pointer to the memory object 00147 * \param addr The address to be read 00148 * \return The byte found at that address addr 00149 */ 00150 00151 uint8_t 00152 mem_read (Memory *mem, int addr) 00153 { 00154 VDevice *dev = mem_get_vdevice_by_addr (mem, addr); 00155 00156 if (dev == NULL) 00157 { 00158 avr_warning ("**** Attempt to read invalid addr: 0x%04x\n", addr); 00159 return 0; 00160 } 00161 00162 return vdev_read (dev, addr); 00163 } 00164 00165 /** \brief Writes byte to memory and updates display for io registers. 00166 * 00167 * \param mem A pointer to a memory object 00168 * \param addr The address to be written to 00169 * \param val The value to be written there 00170 */ 00171 00172 void 00173 mem_write (Memory *mem, int addr, uint8_t val) 00174 { 00175 VDevice *dev = mem_get_vdevice_by_addr (mem, addr); 00176 00177 if (dev == NULL) 00178 { 00179 avr_warning ("**** Attempt to write invalid addr: 0x%04x\n", addr); 00180 return; 00181 } 00182 00183 /* update the display for io registers here */ 00184 00185 if ((addr >= IO_REG_ADDR_BEGIN) && (addr < IO_REG_ADDR_END)) 00186 display_io_reg (addr - IO_REG_ADDR_BEGIN, val); 00187 00188 vdev_write (dev, addr, val); 00189 } 00190 00191 static int 00192 mem_reset_iter_func (AvrClass *data, void *user_data) 00193 { 00194 vdev_reset ((VDevice *)data); 00195 return 0; /* don't delete data from list */ 00196 } 00197 00198 /** \brief Resets every device in the memory object. 00199 * \param mem A pointer to the memory object. 00200 */ 00201 00202 void 00203 mem_reset (Memory *mem) 00204 { 00205 mem->dev = dlist_iterator (mem->dev, mem_reset_iter_func, NULL); 00206 } 00207 00208 static void 00209 mem_reg_dump_core (Memory *mem, FILE * f_core) 00210 { 00211 int i, j; 00212 00213 fprintf (f_core, "General Purpose Register Dump:\n"); 00214 for (i = 0; i < 32; i += 8) 00215 { 00216 for (j = i; j < (i + 8); j++) 00217 fprintf (f_core, "r%02d=%02x ", j, mem_read (mem, j)); 00218 fprintf (f_core, "\n"); 00219 } 00220 fprintf (f_core, "\n"); 00221 } 00222 00223 /** \brief Fetch the name and value of the io register (addr). 00224 * 00225 * \param mem A pointer to the memory object. 00226 * \param addr The address to fetch from. 00227 * \param val A pointer where the value of the register is to be copied. 00228 * \param buf A pointer to where the name of the register should be copied. 00229 * \param bufsiz The maximum size of the the buf string. 00230 */ 00231 00232 void 00233 mem_io_fetch (Memory *mem, int addr, uint8_t * val, char *buf, int bufsiz) 00234 { 00235 VDevice *dev; 00236 int is_port; 00237 00238 if ((addr < IO_REG_ADDR_BEGIN) || (addr >= IO_REG_ADDR_END)) 00239 { 00240 *val = 0; 00241 strncpy (buf, "NOT AN IO REG", bufsiz); 00242 } 00243 else 00244 { 00245 dev = mem_get_vdevice_by_addr (mem, addr); 00246 if (dev == NULL) 00247 { 00248 strncpy (buf, "Reserved", bufsiz); 00249 *val = 0; 00250 } 00251 else 00252 { 00253 strncpy (buf, vdev_get_reg_name (dev, addr), bufsiz); 00254 00255 is_port = 0; 00256 if (strncmp (vdev_get_name (dev), "PORT", 4) == 0) 00257 { 00258 is_port = 1; 00259 port_ext_disable ((Port *)dev); 00260 } 00261 *val = vdev_read (dev, addr); 00262 if (is_port) 00263 port_ext_enable ((Port *)dev); 00264 } 00265 } 00266 } 00267 00268 static void 00269 mem_io_reg_dump_core (Memory *mem, FILE * f_core) 00270 { 00271 int i, j; 00272 char name[80]; 00273 uint8_t val; 00274 00275 int begin = IO_REG_ADDR_BEGIN; 00276 int end = IO_REG_ADDR_END; 00277 int half = (end - begin) / 2; 00278 int mid = begin + half; 00279 00280 fprintf (f_core, "IO Register Dump:\n"); 00281 for (i = begin; i < mid; i++) 00282 { 00283 for (j = i; j < end; j += half) 00284 { 00285 memset (name, '\0', sizeof (name)); 00286 mem_io_fetch (mem, j, &val, name, sizeof (name) - 1); 00287 00288 fprintf (f_core, "%02x : %-10s : 0x%02x ", j - half, 00289 name, val); 00290 } 00291 fprintf (f_core, "\n"); 00292 } 00293 fprintf (f_core, "\n"); 00294 } 00295 00296 static void 00297 mem_sram_display (VDevice *dev, FILE * f_core, int base, int size) 00298 { 00299 int i; 00300 int dup = 0; 00301 int ndat = 16; 00302 char line[80]; 00303 char last_line[80]; 00304 char buf[80]; 00305 line[0] = last_line[0] = '\0'; 00306 00307 for (i = base; i < (base + size); i++) 00308 { 00309 if (((i % ndat) == 0) && strlen (line)) 00310 { 00311 if (strncmp (line, last_line, 80) == 0) 00312 { 00313 dup++; 00314 } 00315 else 00316 { 00317 if (dup > 0) 00318 fprintf (f_core, " -- last line repeats --\n"); 00319 fprintf (f_core, "%04x : %s\n", i - ndat, line); 00320 dup = 0; 00321 } 00322 strncpy (last_line, line, 80); 00323 line[0] = '\0'; 00324 } 00325 snprintf (buf, 80, "%02x ", vdev_read (dev, i)); 00326 strncat (line, buf, 80); 00327 } 00328 if (dup > 0) 00329 { 00330 fprintf (f_core, " -- last line repeats --\n"); 00331 fprintf (f_core, "%04x : %s\n", i - ndat, line); 00332 } 00333 fprintf (f_core, "\n"); 00334 } 00335 00336 static void 00337 mem_sram_dump_core (Memory *mem, FILE * f_core) 00338 { 00339 VDevice *dev; 00340 int size, base; 00341 00342 /* 00343 * Dump the internal sram 00344 */ 00345 dev = mem_get_vdevice_by_name (mem, "SRAM"); 00346 if (dev == NULL) 00347 return; /* device has no sram */ 00348 00349 fprintf (f_core, "Internal SRAM Memory Dump:\n"); 00350 base = vdev_get_base (dev); 00351 size = vdev_get_size (dev); 00352 mem_sram_display (dev, f_core, base, size); 00353 00354 /* 00355 * If external sram present, dump it too. 00356 */ 00357 00358 dev = mem_get_vdevice_by_name (mem, "ESRAM"); 00359 if (dev == NULL) 00360 return; /* device has no sram */ 00361 00362 fprintf (f_core, "External SRAM Memory Dump:\n"); 00363 base = vdev_get_base (dev); 00364 size = vdev_get_size (dev); 00365 mem_sram_display (dev, f_core, base, size); 00366 00367 } 00368 00369 static void 00370 mem_eeprom_dump_core (Memory *mem, FILE * f_core) 00371 { 00372 VDevice *dev = mem_get_vdevice_by_name (mem, "EEProm"); 00373 00374 if (dev != NULL) 00375 eeprom_dump_core ((EEProm *)dev, f_core); 00376 } 00377 00378 /** \brief Dump all the various memory locations to a file descriptor 00379 * in text format. 00380 * 00381 * \param mem A memory object. 00382 * \param f_core An open file descriptor. 00383 */ 00384 00385 void 00386 mem_dump_core (Memory *mem, FILE * f_core) 00387 { 00388 mem_reg_dump_core (mem, f_core); 00389 mem_io_reg_dump_core (mem, f_core); 00390 mem_sram_dump_core (mem, f_core); 00391 mem_eeprom_dump_core (mem, f_core); 00392 }

Automatically generated by Doxygen 1.3.8 on 11 Aug 2004.