simio: added "simio" command and device/CPU interfaces.
This commit is contained in:
parent
115683c8bc
commit
5f40c55f4e
4
Makefile
4
Makefile
|
@ -16,7 +16,7 @@
|
|||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
CC ?= gcc
|
||||
CC = gcc
|
||||
INSTALL = /usr/bin/install
|
||||
PREFIX ?= /usr/local
|
||||
LDFLAGS ?= -s
|
||||
|
@ -63,7 +63,7 @@ mspdebug: main.o fet.o rf2500.o dis.o uif.o olimex.o ihex.o elf32.o stab.o \
|
|||
util.o bsl.o sim.o symmap.o gdb.o btree.o rtools.o sym.o devcmd.o \
|
||||
reader.o vector.o output_util.o expr.o fet_error.o binfile.o \
|
||||
fet_db.o usbutil.o titext.o srec.o device.o coff.o opdb.o output.o \
|
||||
cmddb.o stdcmd.o prog.o flash_bsl.o
|
||||
cmddb.o stdcmd.o prog.o flash_bsl.o list.o simio.o
|
||||
$(CC) $(LDFLAGS) $(PORTS_LDFLAGS) -o $@ $^ -lusb $(READLINE_LIBS)
|
||||
|
||||
.c.o:
|
||||
|
|
20
cmddb.c
20
cmddb.c
|
@ -26,6 +26,7 @@
|
|||
#include "rtools.h"
|
||||
#include "sym.h"
|
||||
#include "stdcmd.h"
|
||||
#include "simio.h"
|
||||
|
||||
const struct cmddb_record commands[] = {
|
||||
{
|
||||
|
@ -240,6 +241,25 @@ const struct cmddb_record commands[] = {
|
|||
.help =
|
||||
"exit\n"
|
||||
" Exit from MSPDebug.\n"
|
||||
},
|
||||
{
|
||||
.name = "simio",
|
||||
.func = cmd_simio,
|
||||
.help =
|
||||
"simio add <class> <name> [args ...]\n"
|
||||
" Add a new device to the IO simulator's bus.\n"
|
||||
"simio del <name>\n"
|
||||
" Delete a device from the bus.\n"
|
||||
"simio devices\n"
|
||||
" Show all devices attached to the bus.\n"
|
||||
"simio classes\n"
|
||||
" Show the types of devices which may be attached.\n"
|
||||
"simio help <class>\n"
|
||||
" Obtain more information about a device type.\n"
|
||||
"simio config <name> <param> [args ...]\n"
|
||||
" Change settings of an attached device.\n"
|
||||
"simio info <name>\n"
|
||||
" Print status information for an attached device.\n"
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/* MSPDebug - debugging tool for MSP430 MCUs
|
||||
* Copyright (C) 2009, 2010 Daniel Beer
|
||||
*
|
||||
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "list.h"
|
||||
|
||||
void list_init(struct list_node *head)
|
||||
{
|
||||
head->next = head;
|
||||
head->prev = head;
|
||||
}
|
||||
|
||||
void list_insert(struct list_node *item, struct list_node *after)
|
||||
{
|
||||
item->next = after;
|
||||
item->prev = after->prev;
|
||||
|
||||
after->prev->next = item;
|
||||
after->prev = item;
|
||||
}
|
||||
|
||||
void list_remove(struct list_node *item)
|
||||
{
|
||||
item->next->prev = item->prev;
|
||||
item->prev->next = item->next;
|
||||
|
||||
item->prev = NULL;
|
||||
item->next = NULL;
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/* MSPDebug - debugging tool for MSP430 MCUs
|
||||
* Copyright (C) 2009, 2010 Daniel Beer
|
||||
*
|
||||
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef LIST_H_
|
||||
#define LIST_H_
|
||||
|
||||
/* This is the list node definition. It's intended to be embedded within
|
||||
* another data structure.
|
||||
*
|
||||
* All lists are circular and doubly-linked. So, to iterate over the
|
||||
* members of a list, do something like this:
|
||||
*
|
||||
* struct list_node *n;
|
||||
*
|
||||
* for (n = list->next; n != list; n = n->next) {
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* An empty list must be created first with list_init(). This sets the
|
||||
* next and prev pointers to the list head itself.
|
||||
*/
|
||||
struct list_node {
|
||||
struct list_node *next;
|
||||
struct list_node *prev;
|
||||
};
|
||||
|
||||
/* Check to see if a list contains anything. */
|
||||
#define LIST_EMPTY(h) ((h)->next == (h))
|
||||
|
||||
/* Create an empty list */
|
||||
void list_init(struct list_node *head);
|
||||
|
||||
/* Add an item to a list. The item will appear before the item
|
||||
* specified as after.
|
||||
*/
|
||||
void list_insert(struct list_node *item, struct list_node *after);
|
||||
|
||||
/* Remove a node from its containing list. */
|
||||
void list_remove(struct list_node *item);
|
||||
|
||||
#endif
|
5
main.c
5
main.c
|
@ -38,6 +38,7 @@
|
|||
#include "opdb.h"
|
||||
#include "reader.h"
|
||||
#include "output.h"
|
||||
#include "simio.h"
|
||||
|
||||
#include "sim.h"
|
||||
#include "bsl.h"
|
||||
|
@ -511,6 +512,8 @@ int main(int argc, char **argv)
|
|||
if (setup_driver(&args) < 0)
|
||||
return -1;
|
||||
|
||||
simio_init();
|
||||
|
||||
if (!args.no_rc)
|
||||
process_rc_file();
|
||||
|
||||
|
@ -527,6 +530,8 @@ int main(int argc, char **argv)
|
|||
reader_loop();
|
||||
}
|
||||
|
||||
simio_exit();
|
||||
|
||||
stab_destroy(stab_default);
|
||||
device_default->destroy(device_default);
|
||||
|
||||
|
|
|
@ -0,0 +1,384 @@
|
|||
/* MSPDebug - debugging tool for MSP430 MCUs
|
||||
* Copyright (C) 2009, 2010 Daniel Beer
|
||||
*
|
||||
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "output.h"
|
||||
#include "dis.h"
|
||||
#include "simio.h"
|
||||
#include "simio_cpu.h"
|
||||
#include "simio_device.h"
|
||||
|
||||
static const struct simio_class *const class_db[] = {
|
||||
/* FIXME: nothing here yet */
|
||||
};
|
||||
|
||||
/* Simulator data. We keep a list of devices on the bus, and the special
|
||||
* function registers.
|
||||
*
|
||||
* Currently, MCLK and SMCLK are tied together, and ACLK runs at a fixed
|
||||
* ratio of 1:256 with MCLK. aclk_counter counts fractional cycles.
|
||||
*/
|
||||
static struct list_node device_list;
|
||||
static uint8_t sfr_data[16];
|
||||
static int aclk_counter;
|
||||
|
||||
static void destroy_device(struct simio_device *dev)
|
||||
{
|
||||
list_remove(&dev->node);
|
||||
dev->type->destroy(dev);
|
||||
}
|
||||
|
||||
void simio_init(void)
|
||||
{
|
||||
list_init(&device_list);
|
||||
simio_reset();
|
||||
}
|
||||
|
||||
void simio_exit(void)
|
||||
{
|
||||
while (!LIST_EMPTY(&device_list))
|
||||
destroy_device((struct simio_device *)&device_list.next);
|
||||
}
|
||||
|
||||
static const struct simio_class *find_class(const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_LEN(class_db); i++) {
|
||||
const struct simio_class *t = class_db[i];
|
||||
|
||||
if (!strcasecmp(t->name, name))
|
||||
return t;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct simio_device *find_device(const char *name)
|
||||
{
|
||||
struct list_node *n;
|
||||
|
||||
for (n = device_list.next; n != &device_list; n = n->next) {
|
||||
struct simio_device *dev = (struct simio_device *)n;
|
||||
|
||||
if (!strcasecmp(dev->name, name))
|
||||
return dev;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int cmd_add(char **arg_text)
|
||||
{
|
||||
const char *name_text = get_arg(arg_text);
|
||||
const char *type_text = get_arg(arg_text);
|
||||
const struct simio_class *type;
|
||||
struct simio_device *dev;
|
||||
|
||||
if (!(name_text && type_text)) {
|
||||
printc_err("simio add: device name and class must be "
|
||||
"specified.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (find_device(name_text)) {
|
||||
printc_err("simio add: device name is not unique: %s\n",
|
||||
name_text);
|
||||
return -1;
|
||||
}
|
||||
|
||||
type = find_class(type_text);
|
||||
if (!type) {
|
||||
printc_err("simio add: unknown type.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
dev = type->create(arg_text);
|
||||
if (!dev) {
|
||||
printc_err("simio add: failed to create device.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
list_insert(&dev->node, &device_list);
|
||||
strncpy(dev->name, name_text, sizeof(dev->name));
|
||||
dev->name[sizeof(dev->name) - 1] = 0;
|
||||
|
||||
printc_dbg("Added new device \"%s\" of type \"%s\".\n",
|
||||
dev->name, dev->type->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_del(char **arg_text)
|
||||
{
|
||||
const char *name_text = get_arg(arg_text);
|
||||
struct simio_device *dev;
|
||||
|
||||
if (!name_text) {
|
||||
printc_err("simio del: device name must be specified.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
dev = find_device(name_text);
|
||||
if (!dev) {
|
||||
printc_err("simio del: no such device: %s\n", name_text);
|
||||
return -1;
|
||||
}
|
||||
|
||||
destroy_device(dev);
|
||||
printc_dbg("Destroyed device \"%s\".\n", name_text);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_devices(char **arg_text)
|
||||
{
|
||||
struct list_node *n;
|
||||
|
||||
for (n = device_list.next; n != &device_list; n = n->next) {
|
||||
struct simio_device *dev = (struct simio_device *)&n;
|
||||
int irq = dev->type->check_interrupt(dev);
|
||||
|
||||
printc(" %-10s (type %s", dev->name, dev->type->name);
|
||||
if (irq < 0)
|
||||
printc(")\n");
|
||||
else
|
||||
printc(", IRQ pending: %d)\n", irq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_classes(char **arg_text)
|
||||
{
|
||||
struct vector v;
|
||||
int i;
|
||||
|
||||
vector_init(&v, sizeof(const char *));
|
||||
for (i = 0; i < ARRAY_LEN(class_db); i++) {
|
||||
if (vector_push(&v, &class_db[i]->name, 1) < 0) {
|
||||
printc_err("simio classes: can't allocate memory\n");
|
||||
vector_destroy(&v);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
printc("Available device classes:\n");
|
||||
namelist_print(&v);
|
||||
vector_destroy(&v);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_help(char **arg_text)
|
||||
{
|
||||
const char *name = get_arg(arg_text);
|
||||
const struct simio_class *type;
|
||||
|
||||
if (!name) {
|
||||
printc_err("simio help: you must specify a device class\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
type = find_class(name);
|
||||
if (!type) {
|
||||
printc_err("simio help: unknown device class: %s\n", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printc("\x1b[1mDEVICE CLASS: %s\x1b[0m\n%s\n", type->name, type->help);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_config(char **arg_text)
|
||||
{
|
||||
const char *name = get_arg(arg_text);
|
||||
const char *param = get_arg(arg_text);
|
||||
struct simio_device *dev;
|
||||
|
||||
if (!(name && param)) {
|
||||
printc_err("simio config: you must specify a device name and "
|
||||
"a parameter\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
dev = find_device(name);
|
||||
if (!dev) {
|
||||
printc_err("simio config: no such device: %s\n", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return dev->type->config(dev, param, arg_text);
|
||||
}
|
||||
|
||||
static int cmd_info(char **arg_text)
|
||||
{
|
||||
const char *name = get_arg(arg_text);
|
||||
struct simio_device *dev;
|
||||
|
||||
if (!name) {
|
||||
printc_err("simio info: you must specify a device name\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
dev = find_device(name);
|
||||
if (!dev) {
|
||||
printc_err("simio info: no such device: %s\n", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return dev->type->info(dev);
|
||||
}
|
||||
|
||||
int cmd_simio(char **arg_text)
|
||||
{
|
||||
const char *subcmd = get_arg(arg_text);
|
||||
static const struct {
|
||||
const char *name;
|
||||
int (*func)(char **arg_text);
|
||||
} cmd_table[] = {
|
||||
{"add", cmd_add},
|
||||
{"del", cmd_del},
|
||||
{"devices", cmd_devices},
|
||||
{"classes", cmd_classes},
|
||||
{"help", cmd_help},
|
||||
{"config", cmd_config},
|
||||
{"info", cmd_info}
|
||||
};
|
||||
int i;
|
||||
|
||||
if (!subcmd) {
|
||||
printc_err("simio: a subcommand is required\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_LEN(cmd_table); i++)
|
||||
if (!strcasecmp(cmd_table[i].name, subcmd))
|
||||
return cmd_table[i].func(arg_text);
|
||||
|
||||
printc_err("simio: unknown subcommand: %s\n", subcmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void simio_reset(void)
|
||||
{
|
||||
memset(sfr_data, 0, sizeof(sfr_data));
|
||||
aclk_counter = 0;
|
||||
}
|
||||
|
||||
#define IO_REQUEST_FUNC(name, method, datatype) \
|
||||
int name(address_t addr, datatype data) { \
|
||||
struct list_node *n; \
|
||||
int ret = 1; \
|
||||
\
|
||||
for (n = device_list.next; n != &device_list; n = n->next) { \
|
||||
struct simio_device *dev = (struct simio_device *)n; \
|
||||
const struct simio_class *type = dev->type; \
|
||||
\
|
||||
if (type->method) { \
|
||||
int r = type->method(dev, addr, data); \
|
||||
\
|
||||
if (r < ret) \
|
||||
ret = r; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
return ret; \
|
||||
}
|
||||
|
||||
IO_REQUEST_FUNC(simio_write, write, uint16_t)
|
||||
IO_REQUEST_FUNC(simio_read, read, uint16_t *)
|
||||
IO_REQUEST_FUNC(simio_write_b, write_b, uint8_t)
|
||||
IO_REQUEST_FUNC(simio_read_b, read_b, uint8_t *)
|
||||
|
||||
int simio_check_interrupt(void)
|
||||
{
|
||||
int irq = -1;
|
||||
struct list_node *n;
|
||||
|
||||
for (n = device_list.next; n != &device_list; n = n->next) {
|
||||
struct simio_device *dev = (struct simio_device *)n;
|
||||
const struct simio_class *type = dev->type;
|
||||
|
||||
if (type->check_interrupt) {
|
||||
int i = type->check_interrupt(dev);
|
||||
|
||||
if (i > irq)
|
||||
irq = i;
|
||||
}
|
||||
}
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
void simio_ack_interrupt(void)
|
||||
{
|
||||
struct list_node *n;
|
||||
|
||||
for (n = device_list.next; n != &device_list; n = n->next) {
|
||||
struct simio_device *dev = (struct simio_device *)n;
|
||||
const struct simio_class *type = dev->type;
|
||||
|
||||
if (type->ack_interrupt)
|
||||
type->ack_interrupt(dev);
|
||||
}
|
||||
}
|
||||
|
||||
void simio_step(uint16_t status_register, int cycles)
|
||||
{
|
||||
int clocks[3] = {0};
|
||||
struct list_node *n;
|
||||
|
||||
aclk_counter += cycles;
|
||||
|
||||
clocks[SIMIO_MCLK] = cycles;
|
||||
clocks[SIMIO_SMCLK] = cycles;
|
||||
clocks[SIMIO_ACLK] = aclk_counter >> 8;
|
||||
|
||||
if (status_register & MSP430_SR_CPUOFF)
|
||||
clocks[SIMIO_MCLK] = 0;
|
||||
|
||||
if (status_register & MSP430_SR_SCG1)
|
||||
clocks[SIMIO_SMCLK] = 0;
|
||||
|
||||
if (status_register & MSP430_SR_OSCOFF)
|
||||
clocks[SIMIO_ACLK] = 0;
|
||||
|
||||
for (n = device_list.next; n != &device_list; n = n->next) {
|
||||
struct simio_device *dev = (struct simio_device *)n;
|
||||
const struct simio_class *type = dev->type;
|
||||
|
||||
if (type->step)
|
||||
type->step(dev, status_register, clocks);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t simio_sfr_get(address_t which)
|
||||
{
|
||||
if (which < 0 || which > sizeof(sfr_data))
|
||||
return 0;
|
||||
|
||||
return sfr_data[which];
|
||||
}
|
||||
|
||||
void simio_sfr_modify(address_t which, uint8_t mask, uint8_t bits)
|
||||
{
|
||||
if (which < 0 || which > sizeof(sfr_data))
|
||||
return;
|
||||
|
||||
sfr_data[which] = (sfr_data[which] & ~mask) | bits;
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/* MSPDebug - debugging tool for MSP430 MCUs
|
||||
* Copyright (C) 2009, 2010 Daniel Beer
|
||||
*
|
||||
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SIMIO_H_
|
||||
#define SIMIO_H_
|
||||
|
||||
/* Initialize the IO simulator. */
|
||||
void simio_init(void);
|
||||
|
||||
/* Clean up allocated resources. */
|
||||
void simio_exit(void);
|
||||
|
||||
/* This file gives the prototype for the "simio" command function. */
|
||||
int cmd_simio(char **arg_text);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,60 @@
|
|||
/* MSPDebug - debugging tool for MSP430 MCUs
|
||||
* Copyright (C) 2009, 2010 Daniel Beer
|
||||
*
|
||||
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SIMIO_CPU_H_
|
||||
#define SIMIO_CPU_H_
|
||||
|
||||
/* This file describes the interface between the CPU simulator and the IO
|
||||
* simulator. It gives prototypes for functions which should be periodically
|
||||
* called by the CPU simulator.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "util.h"
|
||||
|
||||
/* This function should be called when the CPU is reset, to also reset
|
||||
* the IO simulator.
|
||||
*/
|
||||
void simio_reset(void);
|
||||
|
||||
/* These functions should be called to perform programmed IO requests. A
|
||||
* return value of 0 indicates success, 1 is an unhandled request, and -1
|
||||
* is an error which should cause execution to stop.
|
||||
*/
|
||||
int simio_write(address_t addr, uint16_t data);
|
||||
int simio_read(address_t addr, uint16_t *data);
|
||||
int simio_write_b(address_t addr, uint8_t data);
|
||||
int simio_read_b(address_t addr, uint8_t *data);
|
||||
|
||||
/* Check for an interrupt before executing an instruction. It returns -1 if
|
||||
* no interrupt is pending, otherwise the number of the highest priority
|
||||
* pending interrupt.
|
||||
*/
|
||||
int simio_check_interrupt(void);
|
||||
|
||||
/* When the CPU begins to handle an interrupt, it needs to notify the IO
|
||||
* simulation. Some interrupt flags are cleared automatically when handled.
|
||||
*/
|
||||
void simio_ack_interrupt(void);
|
||||
|
||||
/* This should be called after executing an instruction to advance the system
|
||||
* clocks.
|
||||
*/
|
||||
void simio_step(uint16_t status_register, int cycles);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,101 @@
|
|||
/* MSPDebug - debugging tool for MSP430 MCUs
|
||||
* Copyright (C) 2009, 2010 Daniel Beer
|
||||
*
|
||||
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SIMIO_DEVICE_H_
|
||||
#define SIMIO_DEVICE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "util.h"
|
||||
#include "list.h"
|
||||
|
||||
/* Each system clock has a unique index. After each instruction, step()
|
||||
* is invoked on each device with an array of clock transition counts.
|
||||
*/
|
||||
typedef enum {
|
||||
SIMIO_MCLK = 0,
|
||||
SIMIO_SMCLK,
|
||||
SIMIO_ACLK
|
||||
} simio_clock_t;
|
||||
|
||||
/* Access to special function registers is provided by these functions. The
|
||||
* modify function does:
|
||||
*
|
||||
* SFR = (SFR & ~mask) | bits
|
||||
*/
|
||||
uint8_t simio_sfr_get(address_t which);
|
||||
void simio_sfr_modify(address_t which, uint8_t mask, uint8_t bits);
|
||||
|
||||
struct simio_class;
|
||||
|
||||
/* Device base class.
|
||||
*
|
||||
* The node and name fields will be filled out by the IO simulator - they're
|
||||
* used for keeping track of the device list. The node member MUST be the
|
||||
* first in the struct.
|
||||
*/
|
||||
struct simio_device {
|
||||
struct list_node node;
|
||||
|
||||
char name[64];
|
||||
const struct simio_class *type;
|
||||
};
|
||||
|
||||
struct simio_class {
|
||||
const char *name;
|
||||
const char *help;
|
||||
|
||||
/* Instantiate a new device, with the given arguments. This may
|
||||
* fail, in which case NULL should be returned.
|
||||
*/
|
||||
struct simio_device *(*create)(char **arg_text);
|
||||
void (*destroy)(struct simio_device *dev);
|
||||
|
||||
/* These methods are invoked via the command interface to modify
|
||||
* device data and show status.
|
||||
*/
|
||||
int (*config)(struct simio_device *dev, const char *param,
|
||||
char **arg_text);
|
||||
int (*info)(struct simio_device *dev);
|
||||
|
||||
/* Programmed IO functions return 1 to indicate an unhandled
|
||||
* request. This scheme allows stacking.
|
||||
*/
|
||||
int (*write)(struct simio_device *dev,
|
||||
address_t addr, uint16_t data);
|
||||
int (*read)(struct simio_device *dev,
|
||||
address_t addr, uint16_t *data);
|
||||
int (*write_b)(struct simio_device *dev,
|
||||
address_t addr, uint8_t data);
|
||||
int (*read_b)(struct simio_device *dev,
|
||||
address_t addr, uint8_t *data);
|
||||
|
||||
/* Check and acknowledge interrupts. Each device may produce
|
||||
* a single interrupt request at any time.
|
||||
*/
|
||||
int (*check_interrupt)(struct simio_device *dev);
|
||||
void (*ack_interrupt)(struct simio_device *dev);
|
||||
|
||||
/* Run the clocks for this device. The counters array has one
|
||||
* array per clock, and gives the number of cycles elapsed since
|
||||
* the last call to this method.
|
||||
*/
|
||||
void (*step)(struct simio_device *dev,
|
||||
uint16_t status_register, const int *clocks);
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue