devsupp.c

Go to the documentation of this file.
00001 /*
00002  * $Id: devsupp.c,v 1.31 2008/03/19 22:39:01 joerg_wunsch Exp $
00003  *
00004  ****************************************************************************
00005  *
00006  * simulavr - A simulator for the Atmel AVR family of microcontrollers.
00007  * Copyright (C) 2001, 2002, 2003, 2004  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 devsupp.c
00028  * \brief Contains definitions for device types (i.e. at90s8515, at90s2313,
00029  * etc.)
00030  *
00031  * This module is used to define the attributes for each device in the AVR
00032  * family. A generic constructor is used to create a new AvrCore object with
00033  * the proper ports, built-in peripherals, memory layout, registers, and
00034  * interrupt vectors, etc.
00035  */
00036 
00037 #include <config.h>
00038 
00039 #include <stdio.h>
00040 #include <stdlib.h>
00041 #include <string.h>
00042 
00043 #include "avrerror.h"
00044 #include "avrmalloc.h"
00045 #include "avrclass.h"
00046 #include "utils.h"
00047 #include "callback.h"
00048 #include "op_names.h"
00049 
00050 #include "storage.h"
00051 #include "flash.h"
00052 
00053 #include "vdevs.h"
00054 #include "memory.h"
00055 #include "stack.h"
00056 #include "register.h"
00057 #include "sram.h"
00058 #include "eeprom.h"
00059 #include "timers.h"
00060 #include "ports.h"
00061 #include "spi.h"
00062 #include "adc.h"
00063 #include "usb.h"
00064 #include "uart.h"
00065 
00066 #include "avrcore.h"
00067 
00068 #include "devsupp.h"
00069 
00070 #ifndef DOXYGEN                 /* don't expose to doxygen */
00071 
00072 /*
00073  * Used to select which vector table the device uses.
00074  * The value is an index into the global_vtable_list[] array 
00075  * defined in intvects.c.
00076  */
00077 enum _vector_table_select
00078 {
00079     VTAB_AT90S1200 = 0,
00080     VTAB_AT90S2313,
00081     VTAB_AT90S4414,
00082     VTAB_ATMEGA8,
00083     VTAB_ATMEGA16,
00084     VTAB_ATMEGA32,
00085     VTAB_ATMEGA103,
00086     VTAB_ATMEGA128,
00087     VTAB_AT43USB355,
00088     VTAB_AT43USB320,
00089     VTAB_AT43USB325,
00090     VTAB_AT43USB326,
00091 };
00092 
00093 /* IO Register Definition.  */
00094 
00095 struct io_reg_defn {
00096     uint16_t addr;              /* The address of the register (in memory
00097                                    space, not IO space). */
00098     char *name;                 /* The register name as given by the
00099                                    datasheet. */
00100     uint16_t ref_addr;          /* Use the vdev reference at the given
00101                                    address.  If not zero, use the same vdev
00102                                    pointer at the given register address. The
00103                                    vdev must have already been created at that
00104                                    address.  Remember that address zero is
00105                                    General Register 0 which is not an IO
00106                                    register. This value should never be less
00107                                    than 0x20. */
00108     uint16_t related;           /* A related address. For example, if a device
00109                                    has more than one timer, each timer has
00110                                    it's own instance of the timer vdev, but
00111                                    all timers need access to the TIMSK
00112                                    register which should have the addr
00113                                    specified here. There might be more than
00114                                    one related address for a vdev, so this may
00115                                    need to become an array. */
00116     VDevCreate vdev_create;     /* The vdev creation function to be used to
00117                                    create the vdev. Note that this should be a
00118                                    wrapper around the vdev's new method. This
00119                                    field is ignored if rel_addr is greater
00120                                    than 0x1f. */
00121     void *data;                 /* Optional data that may be needed by the
00122                                    vdev. May be address specific too. */
00123     int flags;                  /* Flags that can change the behaviour of the
00124                                    value. (e.g. FL_SET_ON_RESET) */
00125     uint8_t reset_value;        /* Initialize the register to this value after
00126                                    reset. */
00127 
00128     /* These should handle PORT width automagically. */
00129 
00130     uint8_t rd_mask;            /* Mask of the readable bits in the
00131                                    register. */
00132     uint8_t wr_mask;            /* Mask of the writable bits in the
00133                                    register. */
00134 };
00135 
00136 #define IO_REG_DEFN_TERMINATOR { .name = NULL, }
00137 
00138 /* Structure for defining a supported device */
00139 
00140 struct _DevSuppDefn
00141 {
00142     char *name;                 /* name of device type */
00143 
00144     StackType stack_type;       /* STACK_HARDWARE or STACK_MEMORY */
00145     int has_ext_io_reg;         /* does the device have extened IO registers */
00146     int irq_vect_idx;           /* interrupt vector table index */
00147 
00148     struct
00149     {
00150         int pc;                 /* width of program counter (usually 2, maybe
00151                                    3) */
00152         int stack;              /* depth of stack (only used by hardware
00153                                    stack) */
00154         int flash;              /* bytes of flash memory */
00155         int sram;               /* bytes of sram memory */
00156         int eeprom;             /* bytes of eeprom memory */
00157         int xram;               /* bytes of external SRAM supported */
00158     } size;
00159 
00160     /* This _must_ be the last field of the structure since it is a variable
00161        length array. (This is new in C99.) */
00162 
00163     struct io_reg_defn io_reg[]; /* Definitions for for all the IO registers
00164                                     the device provides. */
00165 };
00166 
00167 #endif /* DOXYGEN */
00168 
00169 int
00170 dev_supp_has_ext_io_reg (DevSuppDefn *dev)
00171 {
00172     return dev->has_ext_io_reg;
00173 }
00174 
00175 int
00176 dev_supp_get_flash_sz (DevSuppDefn *dev)
00177 {
00178     return dev->size.flash;
00179 }
00180 
00181 int
00182 dev_supp_get_PC_sz (DevSuppDefn *dev)
00183 {
00184     return dev->size.pc;
00185 }
00186 
00187 int
00188 dev_supp_get_stack_sz (DevSuppDefn *dev)
00189 {
00190     return dev->size.stack;
00191 }
00192 
00193 int
00194 dev_supp_get_vtab_idx (DevSuppDefn *dev)
00195 {
00196     return dev->irq_vect_idx;
00197 }
00198 
00199 int
00200 dev_supp_get_sram_sz (DevSuppDefn *dev)
00201 {
00202     return dev->size.sram;
00203 }
00204 
00205 int
00206 dev_supp_get_eeprom_sz (DevSuppDefn *dev)
00207 {
00208     return dev->size.eeprom;
00209 }
00210 
00211 int
00212 dev_supp_get_xram_sz (DevSuppDefn *dev)
00213 {
00214     return dev->size.xram;
00215 }
00216 
00217 /*
00218  * Device Definitions
00219  */
00220 
00221 #define IN_DEVSUPP_C
00222 
00223 #include "defn/90s1200.h"
00224 #include "defn/90s2313.h"
00225 #include "defn/90s4414.h"
00226 #include "defn/90s8515.h"
00227 
00228 #include "defn/mega8.h"
00229 #include "defn/mega16.h"
00230 #include "defn/mega32.h"
00231 #include "defn/mega103.h"
00232 #include "defn/mega128.h"
00233 
00234 #include "defn/43usb320.h"
00235 #include "defn/43usb325.h"
00236 #include "defn/43usb326.h"
00237 
00238 #include "defn/43usb351.h"
00239 #include "defn/43usb353.h"
00240 #include "defn/43usb355.h"
00241 
00242 #undef IN_DEVSUPP_C
00243 
00244 /** \brief List of supported devices. */
00245 
00246 static DevSuppDefn *devices_supported[] = {
00247     &defn_at90s1200,
00248     &defn_at90s2313,
00249     &defn_at90s4414,
00250     &defn_at90s8515,
00251     &defn_atmega8,
00252     &defn_atmega16,
00253     &defn_atmega32,
00254     &defn_atmega103,
00255     &defn_atmega128,
00256     &defn_at43usb351,
00257     &defn_at43usb353,
00258     &defn_at43usb355,
00259     &defn_at43usb320,
00260     &defn_at43usb325,
00261     &defn_at43usb326,
00262     NULL
00263 };
00264 
00265 /**
00266  * \brief Look up a device name in support list.
00267  *
00268  * \returns An opaque pointer to DevSuppDefn or NULL if not found.
00269  */
00270 
00271 DevSuppDefn *
00272 dev_supp_lookup_device (char *dev_name)
00273 {
00274     DevSuppDefn **dev = devices_supported;
00275     int len;
00276 
00277     while ((*dev))
00278     {
00279         len = strlen ((*dev)->name);
00280 
00281         if (strncmp ((*dev)->name, dev_name, len) == 0)
00282             return (*dev);
00283 
00284         dev++;
00285     }
00286     return NULL;
00287 }
00288 
00289 /** \brief Print a list of supported devices to a file pointer. */
00290 
00291 void
00292 dev_supp_list_devices (FILE * fp)
00293 {
00294     DevSuppDefn **dev;
00295 
00296     for (dev = devices_supported; (*dev); dev++)
00297         fprintf (fp, "  %s\n", (*dev)->name);
00298 }
00299 
00300 void
00301 dev_supp_attach_io_regs (AvrCore *core, DevSuppDefn *dev)
00302 {
00303     VDevice *vdev;
00304     struct io_reg_defn *reg = dev->io_reg;
00305 
00306     while (reg->name)
00307     {
00308         if (reg->ref_addr)
00309         {
00310             if (reg->ref_addr < 0x20)
00311             {
00312                 avr_error ("can't attach IO reg into general register space");
00313             }
00314 
00315             /* Get the referenced vdev. */
00316 
00317             vdev = avr_core_get_vdev_by_addr (core, reg->ref_addr);
00318             if (vdev == NULL)
00319             {
00320                 /* This means that the implementor of the vdev screwed up. */
00321                 avr_error ("reference vdev hasn't been created yet");
00322             }
00323 
00324             vdev_add_addr (vdev, reg->addr, reg->name, reg->related,
00325                            reg->data);
00326 
00327             avr_core_attach_vdev (core, reg->addr, reg->name, vdev, reg->flags,
00328                                   reg->reset_value, reg->rd_mask,
00329                                   reg->wr_mask);
00330 
00331             avr_message ("attach: IO Reg '%s' at 0x%04x: ref = 0x%04x\n",
00332                          reg->name, reg->addr, reg->ref_addr);
00333         }
00334 
00335         else if (reg->vdev_create)
00336         {
00337             vdev = reg->vdev_create (reg->addr, reg->name, reg->related,
00338                                      reg->data);
00339             avr_core_attach_vdev (core, reg->addr, reg->name, vdev, reg->flags,
00340                                   reg->reset_value, reg->rd_mask,
00341                                   reg->wr_mask);
00342 
00343             /* Attaching implicitly references the device so we need to unref
00344                the newly created vdev since we're done with it here. */
00345             class_unref ((AvrClass *)vdev);
00346 
00347             avr_message ("attach: IO Reg '%s' at 0x%04x: created\n",
00348                          reg->name, reg->addr);
00349         }
00350 
00351         else
00352         {
00353             avr_message ("TODO: attach IO Reg '%s' at 0x%04x\n", reg->name,
00354                          reg->addr);
00355 
00356             avr_core_set_addr_name (core, reg->addr, reg->name);
00357         }
00358 
00359         reg++;
00360     }
00361 }