File: devsupp.c

package info (click to toggle)
simulavr 0.1.2.2-6.1
  • links: PTS
  • area: main
  • in suites: lenny, squeeze
  • size: 2,756 kB
  • ctags: 3,179
  • sloc: ansic: 19,987; sh: 3,623; python: 3,528; makefile: 406; asm: 308; yacc: 145; lex: 48
file content (345 lines) | stat: -rw-r--r-- 10,111 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
/*
 * $Id: devsupp.c,v 1.28 2004/02/26 07:22:15 troth Exp $
 *
 ****************************************************************************
 *
 * simulavr - A simulator for the Atmel AVR family of microcontrollers.
 * Copyright (C) 2001, 2002, 2003, 2004  Theodore A. Roth
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 ****************************************************************************
 */

/**
 * \file devsupp.c
 * \brief Contains definitions for device types (i.e. at90s8515, at90s2313,
 * etc.)
 *
 * This module is used to define the attributes for each device in the AVR
 * family. A generic constructor is used to create a new AvrCore object with
 * the proper ports, built-in peripherals, memory layout, registers, and
 * interrupt vectors, etc.
 */

#include <config.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "avrerror.h"
#include "avrmalloc.h"
#include "avrclass.h"
#include "utils.h"
#include "callback.h"
#include "op_names.h"

#include "storage.h"
#include "flash.h"

#include "vdevs.h"
#include "memory.h"
#include "stack.h"
#include "register.h"
#include "sram.h"
#include "eeprom.h"
#include "timers.h"
#include "ports.h"
#include "spi.h"
#include "adc.h"
#include "usb.h"
#include "uart.h"

#include "avrcore.h"

#include "devsupp.h"

#ifndef DOXYGEN                 /* don't expose to doxygen */

/*
 * Used to select which vector table the device uses.
 * The value is an index into the global_vtable_list[] array 
 * defined in intvects.c.
 */
enum _vector_table_select
{
    VTAB_AT90S1200 = 0,
    VTAB_AT90S2313,
    VTAB_AT90S4414,
    VTAB_ATMEGA8,
    VTAB_ATMEGA16,
    VTAB_ATMEGA103,
    VTAB_ATMEGA128,
    VTAB_AT43USB355,
    VTAB_AT43USB320,
    VTAB_AT43USB325,
    VTAB_AT43USB326,
};

/* IO Register Definition.  */

struct io_reg_defn {
    uint16_t addr;              /* The address of the register (in memory
                                   space, not IO space). */
    char *name;                 /* The register name as given by the
                                   datasheet. */
    uint16_t ref_addr;          /* Use the vdev reference at the given
                                   address.  If not zero, use the same vdev
                                   pointer at the given register address. The
                                   vdev must have already been created at that
                                   address.  Remember that address zero is
                                   General Register 0 which is not an IO
                                   register. This value should never be less
                                   than 0x20. */
    uint16_t related;           /* A related address. For example, if a device
                                   has more than one timer, each timer has
                                   it's own instance of the timer vdev, but
                                   all timers need access to the TIMSK
                                   register which should have the addr
                                   specified here. There might be more than
                                   one related address for a vdev, so this may
                                   need to become an array. */
    VDevCreate vdev_create;     /* The vdev creation function to be used to
                                   create the vdev. Note that this should be a
                                   wrapper around the vdev's new method. This
                                   field is ignored if rel_addr is greater
                                   than 0x1f. */
    void *data;                 /* Optional data that may be needed by the
                                   vdev. May be address specific too. */
    int flags;                  /* Flags that can change the behaviour of the
                                   value. (e.g. FL_SET_ON_RESET) */
    uint8_t reset_value;        /* Initialize the register to this value after
                                   reset. */

    /* These should handle PORT width automagically. */

    uint8_t rd_mask;            /* Mask of the readable bits in the
                                   register. */
    uint8_t wr_mask;            /* Mask of the writable bits in the
                                   register. */
};

#define IO_REG_DEFN_TERMINATOR { .name = NULL, }

/* Structure for defining a supported device */

struct _DevSuppDefn
{
    char *name;                 /* name of device type */

    StackType stack_type;       /* STACK_HARDWARE or STACK_MEMORY */
    int has_ext_io_reg;         /* does the device have extened IO registers */
    int irq_vect_idx;           /* interrupt vector table index */

    struct
    {
        int pc;                 /* width of program counter (usually 2, maybe
                                   3) */
        int stack;              /* depth of stack (only used by hardware
                                   stack) */
        int flash;              /* bytes of flash memory */
        int sram;               /* bytes of sram memory */
        int eeprom;             /* bytes of eeprom memory */
    } size;

    /* This _must_ be the last field of the structure since it is a variable
       length array. (This is new in C99.) */

    struct io_reg_defn io_reg[]; /* Definitions for for all the IO registers
                                    the device provides. */
};

#endif /* DOXYGEN */

int
dev_supp_has_ext_io_reg (DevSuppDefn *dev)
{
    return dev->has_ext_io_reg;
}

int
dev_supp_get_flash_sz (DevSuppDefn *dev)
{
    return dev->size.flash;
}

int
dev_supp_get_PC_sz (DevSuppDefn *dev)
{
    return dev->size.pc;
}

int
dev_supp_get_stack_sz (DevSuppDefn *dev)
{
    return dev->size.stack;
}

int
dev_supp_get_vtab_idx (DevSuppDefn *dev)
{
    return dev->irq_vect_idx;
}

int
dev_supp_get_sram_sz (DevSuppDefn *dev)
{
    return dev->size.sram;
}

/*
 * Device Definitions
 */

#define IN_DEVSUPP_C

#include "defn/90s1200.h"
#include "defn/90s2313.h"
#include "defn/90s4414.h"
#include "defn/90s8515.h"

#include "defn/mega8.h"
#include "defn/mega16.h"
#include "defn/mega103.h"
#include "defn/mega128.h"

#include "defn/43usb320.h"
#include "defn/43usb325.h"
#include "defn/43usb326.h"

#include "defn/43usb351.h"
#include "defn/43usb353.h"
#include "defn/43usb355.h"

#undef IN_DEVSUPP_C

/** \brief List of supported devices. */

static DevSuppDefn *devices_supported[] = {
    &defn_at90s1200,
    &defn_at90s2313,
    &defn_at90s4414,
    &defn_at90s8515,
    &defn_atmega8,
    &defn_atmega16,
    &defn_atmega103,
    &defn_atmega128,
    &defn_at43usb351,
    &defn_at43usb353,
    &defn_at43usb355,
    &defn_at43usb320,
    &defn_at43usb325,
    &defn_at43usb326,
    NULL
};

/**
 * \brief Look up a device name in support list.
 *
 * \returns An opaque pointer to DevSuppDefn or NULL if not found.
 */

DevSuppDefn *
dev_supp_lookup_device (char *dev_name)
{
    DevSuppDefn **dev = devices_supported;
    int len;

    while ((*dev))
    {
        len = strlen ((*dev)->name);

        if (strncmp ((*dev)->name, dev_name, len) == 0)
            return (*dev);

        dev++;
    }
    return NULL;
}

/** \brief Print a list of supported devices to a file pointer. */

void
dev_supp_list_devices (FILE * fp)
{
    DevSuppDefn **dev;

    for (dev = devices_supported; (*dev); dev++)
        fprintf (fp, "  %s\n", (*dev)->name);
}

void
dev_supp_attach_io_regs (AvrCore *core, DevSuppDefn *dev)
{
    VDevice *vdev;
    struct io_reg_defn *reg = dev->io_reg;

    while (reg->name)
    {
        if (reg->ref_addr)
        {
            if (reg->ref_addr < 0x20)
            {
                avr_error ("can't attach IO reg into general register space");
            }

            /* Get the referenced vdev. */

            vdev = avr_core_get_vdev_by_addr (core, reg->ref_addr);
            if (vdev == NULL)
            {
                /* This means that the implementor of the vdev screwed up. */
                avr_error ("reference vdev hasn't been created yet");
            }

            vdev_add_addr (vdev, reg->addr, reg->name, reg->related,
                           reg->data);

            avr_core_attach_vdev (core, reg->addr, reg->name, vdev, reg->flags,
                                  reg->reset_value, reg->rd_mask,
                                  reg->wr_mask);

            avr_message ("attach: IO Reg '%s' at 0x%04x: ref = 0x%04x\n",
                         reg->name, reg->addr, reg->ref_addr);
        }

        else if (reg->vdev_create)
        {
            vdev = reg->vdev_create (reg->addr, reg->name, reg->related,
                                     reg->data);
            avr_core_attach_vdev (core, reg->addr, reg->name, vdev, reg->flags,
                                  reg->reset_value, reg->rd_mask,
                                  reg->wr_mask);

            /* Attaching implicitly references the device so we need to unref
               the newly created vdev since we're done with it here. */
            class_unref ((AvrClass *)vdev);

            avr_message ("attach: IO Reg '%s' at 0x%04x: created\n",
                         reg->name, reg->addr);
        }

        else
        {
            avr_message ("TODO: attach IO Reg '%s' at 0x%04x\n", reg->name,
                         reg->addr);

            avr_core_set_addr_name (core, reg->addr, reg->name);
        }

        reg++;
    }
}