device.c
Go to the documentation of this file.
1 /*
2  * $Id: device.c,v 1.15 2004/01/30 07:09:56 troth 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 
32 #include "avrerror.h"
33 #include "avrmalloc.h"
34 #include "avrclass.h"
35 #include "utils.h"
36 #include "callback.h"
37 #include "op_names.h"
38 
39 #include "storage.h"
40 #include "flash.h"
41 
42 #include "vdevs.h"
43 #include "memory.h"
44 #include "stack.h"
45 #include "register.h"
46 #include "sram.h"
47 #include "eeprom.h"
48 #include "timers.h"
49 #include "ports.h"
50 
51 #include "avrcore.h"
52 
53 /** \file device.c
54  * \brief VDevice methods
55  *
56  * These functions are the base for all other devices
57  * mapped into the device space.
58  */
59 
60 /** \brief Create a new VDevice. */
61 VDevice *
62 vdev_new (char *name, VDevFP_Read rd, VDevFP_Write wr, VDevFP_Reset reset,
63  VDevFP_AddAddr add_addr)
64 {
65  VDevice *dev;
66 
67  dev = avr_new0 (VDevice, 1);
68  vdev_construct (dev, rd, wr, reset, add_addr);
69  class_overload_destroy ((AvrClass *)dev, vdev_destroy);
70 
71  return dev;
72 }
73 
74 /** \brief Default AddAddr method.
75 
76  This generate a warning that the should let the developer know that the
77  vdev needs to be updated. */
78 
79 void
80 vdev_def_AddAddr (VDevice *dev, int addr, char *name, int related_addr,
81  void *data)
82 {
83  avr_warning ("Default AddAddr called [addr=0x%x; '%s']\n", addr, name);
84 }
85 
86 
87 /** \brief Constructor for a VDevice. */
88 void
89 vdev_construct (VDevice *dev, VDevFP_Read rd, VDevFP_Write wr,
90  VDevFP_Reset reset, VDevFP_AddAddr add_addr)
91 {
92  if (dev == NULL)
93  avr_error ("passed null ptr");
94 
95  class_construct ((AvrClass *)dev);
96 
97  dev->read = rd;
98  dev->write = wr;
99  dev->reset = reset;
100  dev->add_addr = add_addr;
101 }
102 
103 /** \brief Destructor for a VDevice. */
104 void
105 vdev_destroy (void *dev)
106 {
107  if (dev == NULL)
108  return;
109 
110  class_destroy (dev);
111 }
112 
113 #if 0
114 
115 /** \brief Compare the names of 2 devices
116  * \param c1 The first device.
117  * \param c2 is a string and not an AvrClass object, because this function is
118  * called by dlist_lookup() which passes two AvrClass pointers. So the string
119  * is casted to an *AvrClass.
120  */
121 int
122 vdev_name_cmp (AvrClass *c1, AvrClass *c2)
123 {
124  return strcmp (((VDevice *)c1)->name, (char *)c2);
125 }
126 
127 #endif
128 
129 #if 0
130 /** \brief Checks if a address is in the device's address range
131  * \param c1 \c AvrClass to check.
132  * \param c2 The address to check.
133  *
134  * \return The different between the device's address bounds and \a c2 or if
135  * \a c2 is within the address range 0.
136  *
137  * \note When comparing an addr, c2 is really just a pointer (see
138  * vdev_name_cmp() for details) to int and then we see if d1->base <= addr <
139  * (d1->base+d1->size).
140  */
141 int
142 vdev_addr_cmp (AvrClass *c1, AvrClass *c2)
143 {
144  VDevice *d1 = (VDevice *)c1;
145  int addr = *(int *)c2;
146 
147  if (addr < d1->base)
148  return (addr - d1->base);
149 
150  if (addr >= (d1->base + d1->size))
151  /* Add one to ensure we don't return zero. */
152  return (1 + addr - (d1->base + d1->size));
153 
154  /* addr is in device's range */
155  return 0;
156 }
157 #endif
158 
159 /** \brief Reads the device's value in the register at \a addr. */
160 uint8_t
161 vdev_read (VDevice *dev, int addr)
162 {
163  return dev->read (dev, addr);
164 }
165 
166 /** \brief Writes an value to the register at \a addr. */
167 void
168 vdev_write (VDevice *dev, int addr, uint8_t val)
169 {
170  dev->write (dev, addr, val);
171 }
172 
173 /** \brief Resets a device. */
174 void
175 vdev_reset (VDevice *dev)
176 {
177  dev->reset (dev);
178 }
179 
180 /** \brief Set the core field. */
181 void
182 vdev_set_core (VDevice *dev, AvrClass *core)
183 {
184  dev->core = (AvrClass *)core;
185 }
186 
187 /** \brief Get the core field. */
188 extern inline AvrClass *vdev_get_core (VDevice *dev);
189 
190 /** \brief Inform the vdevice that it needs to handle another address.
191 
192  This is primarily used when creating the core in dev_supp_create_core(). */
193 
194 extern void
195 vdev_add_addr (VDevice *dev, int addr, char *name, int rel_addr, void *data)
196 {
197  if (dev->add_addr)
198  {
199  dev->add_addr (dev, addr, name, rel_addr, data);
200  }
201  else
202  {
203  avr_warning ("attempt to add addr to vdev with no add_addr() method: "
204  "%s [0x%04x]\n", name, addr);
205  }
206 }
207 
208 #if 0
209 /** \brief Get the device's base address. */
210 int
211 vdev_get_base (VDevice *dev)
212 {
213  return dev->base;
214 }
215 #endif
216 
217 #if 0
218 /** \brief Set the device's size (the number of bytes of the address space it
219  * consumes). */
220 int
221 vdev_get_size (VDevice *dev)
222 {
223  return dev->size;
224 }
225 #endif
226 
227 #if 0
228 /** \brief Get the device's name. */
229 char *
230 vdev_get_name (VDevice *dev)
231 {
232  return dev->name;
233 }
234 #endif

Automatically generated by Doxygen 1.8.2 on Tue Aug 13 2013.