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
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 }

Automatically generated by Doxygen 1.8.2 on Sat Mar 7 2015.