devsupp.c

Go to the documentation of this file.
00001 /*
00002  * $Id: devsupp.c,v 1.28 2004/02/26 07:22:15 troth 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_ATMEGA103,
00085     VTAB_ATMEGA128,
00086     VTAB_AT43USB355,
00087     VTAB_AT43USB320,
00088     VTAB_AT43USB325,
00089     VTAB_AT43USB326,
00090 };
00091 
00092 /* IO Register Definition.  */
00093 
00094 struct io_reg_defn {
00095     uint16_t addr;              /* The address of the register (in memory
00096                                    space, not IO space). */
00097     char *name;                 /* The register name as given by the
00098                                    datasheet. */
00099     uint16_t ref_addr;          /* Use the vdev reference at the given
00100                                    address.  If not zero, use the same vdev
00101                                    pointer at the given register address. The
00102                                    vdev must have already been created at that
00103                                    address.  Remember that address zero is
00104                                    General Register 0 which is not an IO
00105                                    register. This value should never be less
00106                                    than 0x20. */
00107     uint16_t related;           /* A related address. For example, if a device
00108                                    has more than one timer, each timer has
00109                                    it's own instance of the timer vdev, but
00110                                    all timers need access to the TIMSK
00111                                    register which should have the addr
00112                                    specified here. There might be more than
00113                                    one related address for a vdev, so this may
00114                                    need to become an array. */
00115     VDevCreate vdev_create;     /* The vdev creation function to be used to
00116                                    create the vdev. Note that this should be a
00117                                    wrapper around the vdev's new method. This
00118                                    field is ignored if rel_addr is greater
00119                                    than 0x1f. */
00120     void *data;                 /* Optional data that may be needed by the
00121                                    vdev. May be address specific too. */
00122     int flags;                  /* Flags that can change the behaviour of the
00123                                    value. (e.g. FL_SET_ON_RESET) */
00124     uint8_t reset_value;        /* Initialize the register to this value after
00125                                    reset. */
00126 
00127     /* These should handle PORT width automagically. */
00128 
00129     uint8_t rd_mask;            /* Mask of the readable bits in the
00130                                    register. */
00131     uint8_t wr_mask;            /* Mask of the writable bits in the
00132                                    register. */
00133 };
00134 
00135 #define IO_REG_DEFN_TERMINATOR { .name = NULL, }
00136 
00137 /* Structure for defining a supported device */
00138 
00139 struct _DevSuppDefn
00140 {
00141     char *name;                 /* name of device type */
00142 
00143     StackType stack_type;       /* STACK_HARDWARE or STACK_MEMORY */
00144     int has_ext_io_reg;         /* does the device have extened IO registers */
00145     int irq_vect_idx;           /* interrupt vector table index */
00146 
00147     struct
00148     {
00149         int pc;                 /* width of program counter (usually 2, maybe
00150                                    3) */
00151         int stack;              /* depth of stack (only used by hardware
00152                                    stack) */
00153         int flash;              /* bytes of flash memory */
00154         int sram;               /* bytes of sram memory */
00155         int eeprom;             /* bytes of eeprom memory */
00156     } size;
00157 
00158     /* This _must_ be the last field of the structure since it is a variable
00159        length array. (This is new in C99.) */
00160 
00161     struct io_reg_defn io_reg[]; /* Definitions for for all the IO registers
00162                                     the device provides. */
00163 };
00164 
00165 #endif /* DOXYGEN */
00166 
00167 int
00168 dev_supp_has_ext_io_reg (DevSuppDefn *dev)
00169 {
00170     return dev->has_ext_io_reg;
00171 }
00172 
00173 int
00174 dev_supp_get_flash_sz (DevSuppDefn *dev)
00175 {
00176     return dev->size.flash;
00177 }
00178 
00179 int
00180 dev_supp_get_PC_sz (DevSuppDefn *dev)
00181 {
00182     return dev->size.pc;
00183 }
00184 
00185 int
00186 dev_supp_get_stack_sz (DevSuppDefn *dev)
00187 {
00188     return dev->size.stack;
00189 }
00190 
00191 int
00192 dev_supp_get_vtab_idx (DevSuppDefn *dev)
00193 {
00194     return dev->irq_vect_idx;
00195 }
00196 
00197 int
00198 dev_supp_get_sram_sz (DevSuppDefn *dev)
00199 {
00200     return dev->size.sram;
00201 }
00202 
00203 /*
00204  * Device Definitions
00205  */
00206 
00207 #define IN_DEVSUPP_C
00208 
00209 #include "defn/90s1200.h"
00210 #include "defn/90s2313.h"
00211 #include "defn/90s4414.h"
00212 #include "defn/90s8515.h"
00213 
00214 #include "defn/mega8.h"
00215 #include "defn/mega16.h"
00216 #include "defn/mega103.h"
00217 #include "defn/mega128.h"
00218 
00219 #include "defn/43usb320.h"
00220 #include "defn/43usb325.h"
00221 #include "defn/43usb326.h"
00222 
00223 #include "defn/43usb351.h"
00224 #include "defn/43usb353.h"
00225 #include "defn/43usb355.h"
00226 
00227 #undef IN_DEVSUPP_C
00228 
00229 /** \brief List of supported devices. */
00230 
00231 static DevSuppDefn *devices_supported[] = {
00232     &defn_at90s1200,
00233     &defn_at90s2313,
00234     &defn_at90s4414,
00235     &defn_at90s8515,
00236     &defn_atmega8,
00237     &defn_atmega16,
00238     &defn_atmega103,
00239     &defn_atmega128,
00240     &defn_at43usb351,
00241     &defn_at43usb353,
00242     &defn_at43usb355,
00243     &defn_at43usb320,
00244     &defn_at43usb325,
00245     &defn_at43usb326,
00246     NULL
00247 };
00248 
00249 /**
00250  * \brief Look up a device name in support list.
00251  *
00252  * \returns An opaque pointer to DevSuppDefn or NULL if not found.
00253  */
00254 
00255 DevSuppDefn *
00256 dev_supp_lookup_device (char *dev_name)
00257 {
00258     DevSuppDefn **dev = devices_supported;
00259     int len;
00260 
00261     while ((*dev))
00262     {
00263         len = strlen ((*dev)->name);
00264 
00265         if (strncmp ((*dev)->name, dev_name, len) == 0)
00266             return (*dev);
00267 
00268         dev++;
00269     }
00270     return NULL;
00271 }
00272 
00273 /** \brief Print a list of supported devices to a file pointer. */
00274 
00275 void
00276 dev_supp_list_devices (FILE * fp)
00277 {
00278     DevSuppDefn **dev;
00279 
00280     for (dev = devices_supported; (*dev); dev++)
00281         fprintf (fp, "  %s\n", (*dev)->name);
00282 }
00283 
00284 void
00285 dev_supp_attach_io_regs (AvrCore *core, DevSuppDefn *dev)
00286 {
00287     VDevice *vdev;
00288     struct io_reg_defn *reg = dev->io_reg;
00289 
00290     while (reg->name)
00291     {
00292         if (reg->ref_addr)
00293         {
00294             if (reg->ref_addr < 0x20)
00295             {
00296                 avr_error ("can't attach IO reg into general register space");
00297             }
00298 
00299             /* Get the referenced vdev. */
00300 
00301             vdev = avr_core_get_vdev_by_addr (core, reg->ref_addr);
00302             if (vdev == NULL)
00303             {
00304                 /* This means that the implementor of the vdev screwed up. */
00305                 avr_error ("reference vdev hasn't been created yet");
00306             }
00307 
00308             vdev_add_addr (vdev, reg->addr, reg->name, reg->related,
00309                            reg->data);
00310 
00311             avr_core_attach_vdev (core, reg->addr, reg->name, vdev, reg->flags,
00312                                   reg->reset_value, reg->rd_mask,
00313                                   reg->wr_mask);
00314 
00315             avr_message ("attach: IO Reg '%s' at 0x%04x: ref = 0x%04x\n",
00316                          reg->name, reg->addr, reg->ref_addr);
00317         }
00318 
00319         else if (reg->vdev_create)
00320         {
00321             vdev = reg->vdev_create (reg->addr, reg->name, reg->related,
00322                                      reg->data);
00323             avr_core_attach_vdev (core, reg->addr, reg->name, vdev, reg->flags,
00324                                   reg->reset_value, reg->rd_mask,
00325                                   reg->wr_mask);
00326 
00327             /* Attaching implicitly references the device so we need to unref
00328                the newly created vdev since we're done with it here. */
00329             class_unref ((AvrClass *)vdev);
00330 
00331             avr_message ("attach: IO Reg '%s' at 0x%04x: created\n",
00332                          reg->name, reg->addr);
00333         }
00334 
00335         else
00336         {
00337             avr_message ("TODO: attach IO Reg '%s' at 0x%04x\n", reg->name,
00338                          reg->addr);
00339 
00340             avr_core_set_addr_name (core, reg->addr, reg->name);
00341         }
00342 
00343         reg++;
00344     }
00345 }

Automatically generated by Doxygen 1.5.2 on 3 Jan 2008.