Main Page

devsupp.c
Go to the documentation of this file.
1 /*
2 * $Id: devsupp.c,v 1.31 2008/03/19 22:39:01 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 /**
27 * \file devsupp.c
28 * \brief Contains definitions for device types (i.e. at90s8515, at90s2313,
29 * etc.)
30 *
31 * This module is used to define the attributes for each device in the AVR
32 * family. A generic constructor is used to create a new AvrCore object with
33 * the proper ports, built-in peripherals, memory layout, registers, and
34 * interrupt vectors, etc.
35 */
36
37 #include <config.h>
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42
43 #include "avrerror.h"
44 #include "avrmalloc.h"
45 #include "avrclass.h"
46 #include "utils.h"
47 #include "callback.h"
48 #include "op_names.h"
49
50 #include "storage.h"
51 #include "flash.h"
52
53 #include "vdevs.h"
54 #include "memory.h"
55 #include "stack.h"
56 #include "register.h"
57 #include "sram.h"
58 #include "eeprom.h"
59 #include "timers.h"
60 #include "ports.h"
61 #include "spi.h"
62 #include "adc.h"
63 #include "usb.h"
64 #include "uart.h"
65
66 #include "avrcore.h"
67
68 #include "devsupp.h"
69
70 #ifndef DOXYGEN /* don't expose to doxygen */
71
72 /*
73 * Used to select which vector table the device uses.
74 * The value is an index into the global_vtable_list[] array
75 * defined in intvects.c.
76 */
77 enum _vector_table_select
78 {
79 VTAB_AT90S1200 = 0,
80 VTAB_AT90S2313,
81 VTAB_AT90S4414,
82 VTAB_ATMEGA8,
83 VTAB_ATMEGA16,
84 VTAB_ATMEGA32,
85 VTAB_ATMEGA103,
86 VTAB_ATMEGA128,
87 VTAB_AT43USB355,
88 VTAB_AT43USB320,
89 VTAB_AT43USB325,
90 VTAB_AT43USB326,
91 };
92
93 /* IO Register Definition. */
94
95 struct io_reg_defn {
96 uint16_t addr; /* The address of the register (in memory
97 space, not IO space). */
98 char *name; /* The register name as given by the
99 datasheet. */
100 uint16_t ref_addr; /* Use the vdev reference at the given
101 address. If not zero, use the same vdev
102 pointer at the given register address. The
103 vdev must have already been created at that
104 address. Remember that address zero is
105 General Register 0 which is not an IO
106 register. This value should never be less
107 than 0x20. */
108 uint16_t related; /* A related address. For example, if a device
109 has more than one timer, each timer has
110 it's own instance of the timer vdev, but
111 all timers need access to the TIMSK
112 register which should have the addr
113 specified here. There might be more than
114 one related address for a vdev, so this may
115 need to become an array. */
116 VDevCreate vdev_create; /* The vdev creation function to be used to
117 create the vdev. Note that this should be a
118 wrapper around the vdev's new method. This
119 field is ignored if rel_addr is greater
120 than 0x1f. */
121 void *data; /* Optional data that may be needed by the
122 vdev. May be address specific too. */
123 int flags; /* Flags that can change the behaviour of the
124 value. (e.g. FL_SET_ON_RESET) */
125 uint8_t reset_value; /* Initialize the register to this value after
126 reset. */
127
128 /* These should handle PORT width automagically. */
129
130 uint8_t rd_mask; /* Mask of the readable bits in the
131 register. */
132 uint8_t wr_mask; /* Mask of the writable bits in the
133 register. */
134 };
135
136 #define IO_REG_DEFN_TERMINATOR { .name = NULL, }
137
138 /* Structure for defining a supported device */
139
140 struct _DevSuppDefn
141 {
142 char *name; /* name of device type */
143
144 StackType stack_type; /* STACK_HARDWARE or STACK_MEMORY */
145 int has_ext_io_reg; /* does the device have extened IO registers */
146 int irq_vect_idx; /* interrupt vector table index */
147
148 struct
149 {
150 int pc; /* width of program counter (usually 2, maybe
151 3) */
152 int stack; /* depth of stack (only used by hardware
153 stack) */
154 int flash; /* bytes of flash memory */
155 int sram; /* bytes of sram memory */
156 int eeprom; /* bytes of eeprom memory */
157 int xram; /* bytes of external SRAM supported */
158 } size;
159
160 /* This _must_ be the last field of the structure since it is a variable
161 length array. (This is new in C99.) */
162
163 struct io_reg_defn io_reg[]; /* Definitions for for all the IO registers
164 the device provides. */
165 };
166
167 #endif /* DOXYGEN */
168
169 int
170 dev_supp_has_ext_io_reg (DevSuppDefn *dev)
171 {
172 return dev->has_ext_io_reg;
173 }
174
175 int
176 dev_supp_get_flash_sz (DevSuppDefn *dev)
177 {
178 return dev->size.flash;
179 }
180
181 int
182 dev_supp_get_PC_sz (DevSuppDefn *dev)
183 {
184 return dev->size.pc;
185 }
186
187 int
188 dev_supp_get_stack_sz (DevSuppDefn *dev)
189 {
190 return dev->size.stack;
191 }
192
193 int
194 dev_supp_get_vtab_idx (DevSuppDefn *dev)
195 {
196 return dev->irq_vect_idx;
197 }
198
199 int
200 dev_supp_get_sram_sz (DevSuppDefn *dev)
201 {
202 return dev->size.sram;
203 }
204
205 int
206 dev_supp_get_eeprom_sz (DevSuppDefn *dev)
207 {
208 return dev->size.eeprom;
209 }
210
211 int
212 dev_supp_get_xram_sz (DevSuppDefn *dev)
213 {
214 return dev->size.xram;
215 }
216
217 /*
218 * Device Definitions
219 */
220
221 #define IN_DEVSUPP_C
222
223 #include "defn/90s1200.h"
224 #include "defn/90s2313.h"
225 #include "defn/90s4414.h"
226 #include "defn/90s8515.h"
227
228 #include "defn/mega8.h"
229 #include "defn/mega16.h"
230 #include "defn/mega32.h"
231 #include "defn/mega103.h"
232 #include "defn/mega128.h"
233
234 #include "defn/43usb320.h"
235 #include "defn/43usb325.h"
236 #include "defn/43usb326.h"
237
238 #include "defn/43usb351.h"
239 #include "defn/43usb353.h"
240 #include "defn/43usb355.h"
241
242 #undef IN_DEVSUPP_C
243
244 /** \brief List of supported devices. */
245
246 static DevSuppDefn *devices_supported[] = {
247 &defn_at90s1200,
248 &defn_at90s2313,
249 &defn_at90s4414,
250 &defn_at90s8515,
251 &defn_atmega8,
252 &defn_atmega16,
253 &defn_atmega32,
254 &defn_atmega103,
255 &defn_atmega128,
256 &defn_at43usb351,
257 &defn_at43usb353,
258 &defn_at43usb355,
259 &defn_at43usb320,
260 &defn_at43usb325,
261 &defn_at43usb326,
262 NULL
263 };
264
265 /**
266 * \brief Look up a device name in support list.
267 *
268 * \returns An opaque pointer to DevSuppDefn or NULL if not found.
269 */
270
271 DevSuppDefn *
272 dev_supp_lookup_device (char *dev_name)
273 {
274 DevSuppDefn **dev = devices_supported;
275 int len;
276
277 while ((*dev))
278 {
279 len = strlen ((*dev)->name);
280
281 if (strncmp ((*dev)->name, dev_name, len) == 0)
282 return (*dev);
283
284 dev++;
285 }
286 return NULL;
287 }
288
289 /** \brief Print a list of supported devices to a file pointer. */
290
291 void
292 dev_supp_list_devices (FILE * fp)
293 {
294 DevSuppDefn **dev;
295
296 for (dev = devices_supported; (*dev); dev++)
297 fprintf (fp, " %s\n", (*dev)->name);
298 }
299
300 void
301 dev_supp_attach_io_regs (AvrCore *core, DevSuppDefn *dev)
302 {
303 VDevice *vdev;
304 struct io_reg_defn *reg = dev->io_reg;
305
306 while (reg->name)
307 {
308 if (reg->ref_addr)
309 {
310 if (reg->ref_addr < 0x20)
311 {
312 avr_error ("can't attach IO reg into general register space");
313 }
314
315 /* Get the referenced vdev. */
316
317 vdev = avr_core_get_vdev_by_addr (core, reg->ref_addr);
318 if (vdev == NULL)
319 {
320 /* This means that the implementor of the vdev screwed up. */
321 avr_error ("reference vdev hasn't been created yet");
322 }
323
324 vdev_add_addr (vdev, reg->addr, reg->name, reg->related,
325 reg->data);
326
327 avr_core_attach_vdev (core, reg->addr, reg->name, vdev, reg->flags,
328 reg->reset_value, reg->rd_mask,
329 reg->wr_mask);
330
331 avr_message ("attach: IO Reg '%s' at 0x%04x: ref = 0x%04x\n",
332 reg->name, reg->addr, reg->ref_addr);
333 }
334
335 else if (reg->vdev_create)
336 {
337 vdev = reg->vdev_create (reg->addr, reg->name, reg->related,
338 reg->data);
339 avr_core_attach_vdev (core, reg->addr, reg->name, vdev, reg->flags,
340 reg->reset_value, reg->rd_mask,
341 reg->wr_mask);
342
343 /* Attaching implicitly references the device so we need to unref
344 the newly created vdev since we're done with it here. */
345 class_unref ((AvrClass *)vdev);
346
347 avr_message ("attach: IO Reg '%s' at 0x%04x: created\n",
348 reg->name, reg->addr);
349 }
350
351 else
352 {
353 avr_message ("TODO: attach IO Reg '%s' at 0x%04x\n", reg->name,
354 reg->addr);
355
356 avr_core_set_addr_name (core, reg->addr, reg->name);
357 }
358
359 reg++;
360 }
361 }
vdev_add_addr
void vdev_add_addr(VDevice *dev, int addr, char *name, int rel_addr, void *data)
Inform the vdevice that it needs to handle another address.
Definition: device.c:195
avr_core_attach_vdev
void avr_core_attach_vdev(AvrCore *core, uint16_t addr, char *name, VDevice *vdev, int flags, uint8_t reset_value, uint8_t rd_mask, uint8_t wr_mask)
Attach a virtual device into the Memory.
dev_supp_lookup_device
DevSuppDefn * dev_supp_lookup_device(char *dev_name)
Look up a device name in support list.
Definition: devsupp.c:272
avr_core_get_vdev_by_addr
VDevice * avr_core_get_vdev_by_addr(AvrCore *core, int addr)
Returns the VDevice which handles the address addr.
dev_supp_list_devices
void dev_supp_list_devices(FILE *fp)
Print a list of supported devices to a file pointer.
Definition: devsupp.c:292
class_unref
void class_unref(AvrClass *klass)
Decrements the reference count for the klass object.
Definition: avrclass.c:120
avr_error
#define avr_error(fmt, args...)
Print an error message to stderr and terminate program.
Definition: avrerror.c:50
avr_message
#define avr_message(fmt, args...)
Print an ordinary message to stdout.
Definition: avrerror.c:42

Automatically generated by Doxygen 1.8.12 on Sun Apr 2 2017.