00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <config.h>
00027
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <string.h>
00031 #include <errno.h>
00032
00033 #include "avrerror.h"
00034 #include "avrmalloc.h"
00035 #include "avrclass.h"
00036 #include "utils.h"
00037 #include "callback.h"
00038 #include "op_names.h"
00039
00040 #include "storage.h"
00041 #include "flash.h"
00042
00043 #include "vdevs.h"
00044 #include "memory.h"
00045 #include "stack.h"
00046 #include "register.h"
00047 #include "sram.h"
00048 #include "eeprom.h"
00049 #include "timers.h"
00050 #include "ports.h"
00051
00052 #include "avrcore.h"
00053
00054 #include "devsupp.h"
00055 #include "display.h"
00056
00057 #include "gdb.h"
00058 #include "gnu_getopt.h"
00059
00060
00061
00062
00063
00064
00065
00066 static char *global_device_type = NULL;
00067
00068 static int global_eeprom_image_type = FFMT_BIN;
00069 static char *global_eeprom_image_file = NULL;
00070
00071 static int global_flash_image_type = FFMT_BIN;
00072 static char *global_flash_image_file = NULL;
00073
00074 static int global_gdbserver_mode = 0;
00075 static int global_gdbserver_port = 1212;
00076 static int global_gdb_debug = 0;
00077
00078 static char *global_disp_prog = NULL;
00079 static int global_disp_without_xterm = 0;
00080
00081 static int global_dump_core = 0;
00082
00083 static int global_clock_freq = 8000000;
00084
00085
00086
00087
00088 #define LEN_BREAK_LIST 50
00089 static int global_break_count = 0;
00090 static int global_break_list[LEN_BREAK_LIST];
00091
00092 static AvrCore *global_core = NULL;
00093
00094
00095 static GdbComm_T global_gdb_comm[1] = {{
00096 .user_data = NULL,
00097
00098 .read_reg = (CommFuncReadReg) avr_core_gpwr_get,
00099 .write_reg = (CommFuncWriteReg) avr_core_gpwr_set,
00100
00101 .read_sreg = (CommFuncReadSREG) avr_core_sreg_get,
00102 .write_sreg = (CommFuncWriteSREG) avr_core_sreg_set,
00103
00104 .read_pc = (CommFuncReadPC) avr_core_PC_get,
00105 .write_pc = (CommFuncWritePC) avr_core_PC_set,
00106 .max_pc = (CommFuncMaxPC) avr_core_PC_max,
00107
00108 .read_sram = (CommFuncReadSRAM) avr_core_mem_read,
00109 .write_sram = (CommFuncWriteSRAM) avr_core_mem_write,
00110
00111 .read_flash = (CommFuncReadFlash) avr_core_flash_read,
00112 .write_flash = (CommFuncWriteFlash) avr_core_flash_write,
00113 .write_flash_lo8 = (CommFuncWriteFlashLo8) avr_core_flash_write_lo8,
00114 .write_flash_hi8 = (CommFuncWriteFlashHi8) avr_core_flash_write_hi8,
00115
00116 .insert_break = (CommFuncInsertBreak) avr_core_insert_breakpoint,
00117 .remove_break = (CommFuncRemoveBreak) avr_core_remove_breakpoint,
00118 .enable_breakpts = (CommFuncEnableBrkpts) avr_core_enable_breakpoints,
00119 .disable_breakpts = (CommFuncDisableBrkpts) avr_core_disable_breakpoints,
00120
00121 .step = (CommFuncStep) avr_core_step,
00122 .reset = (CommFuncReset) avr_core_reset,
00123
00124 .io_fetch = (CommFuncIORegFetch) avr_core_io_fetch,
00125
00126 .irq_raise = (CommFuncIrqRaise) avr_core_irq_raise,
00127 }};
00128
00129 static char *usage_fmt_str =
00130 "\nUsage: %s [OPTIONS]... [flash_image]\n" "\n"
00131 "Simulate an avr device. The optional flash_image file is loaded\n"
00132 "into the flash program memory space of the device.\n" "\n" "Options:\n"
00133 " -h, --help : Show this message\n"
00134 " -D, --debug : Debug instruction output\n"
00135 " -v, --version : Print out the version number and exit\n"
00136 " -g, --gdbserver : Run as a gdbserver process\n"
00137 " -G, --gdb-debug : Print out debug messages for gdbserver\n"
00138 " -p, --port <port> : Listen for gdb connection on TCP port\n"
00139 " -d, --device <dev> : Specify device type\n"
00140 " -e, --eeprom-image <img> : Specify an eeprom image file\n"
00141 " -E, --eeprom-type <type> : Specify the type of the eeprom image file\n"
00142 " -F, --flash-type <type> : Specify the type of the flash image file\n"
00143 " -L, --list-devices : Print supported devices to stdout and exit\n"
00144 " -P, --disp-prog <prog> : Display register and memory info with prog\n"
00145 " -X, --without-xterm : Don't start disp prog in an xterm\n"
00146 " -C, --core-dump : Dump a core memory image to file on exit\n"
00147 " -c, --clock-freq <freq> : Set the simulated mcu clock freqency (in Hz)\n"
00148 " -B, --breakpoint <addr> : Set a breakpoint (address is a byte address)\n"
00149 "\n" "If the image file types for eeprom or flash images are not given,\n"
00150 "the default file type is binary.\n" "\n"
00151 "If you wish to run the simulator in gdbserver mode, you do not\n"
00152 "have to specify a flash-image file since the program can be loaded\n"
00153 "from gdb via the `load` command.\n" "\n"
00154 "If '--port' option is given, and '--gdbserver' is not, port is ignored\n"
00155 "\n" "If running in gdbserver mode and port is not specified, a default\n"
00156 "port of 1212 is used.\n" "\n"
00157 "If using the '--breakpoint' option, note the simulator will terminate when\n"
00158 "the address is hit if you are not running in gdbserver mode. This feature\n"
00159 "not intended for use in gdbserver mode. It is really intended for testing\n"
00160 "the simulator itself, but may be useful for testing avr programs too.\n"
00161 "\n" "Currently available device types:\n";
00162
00163
00164
00165
00166
00167
00168 static void
00169 usage (char *prog)
00170 {
00171 fprintf (stdout, usage_fmt_str, prog);
00172 dev_supp_list_devices (stdout);
00173 fprintf (stdout, "\n");
00174
00175 exit (1);
00176 }
00177
00178
00179 static struct option long_opts[] = {
00180
00181 { "help", 0, 0, 'h' },
00182 { "debug", 0, 0, 'D' },
00183 { "version", 0, 0, 'v' },
00184 { "gdbserver", 0, 0, 'g' },
00185 { "gdb-debug", 0, 0, 'G' },
00186 { "port", 1, 0, 'p' },
00187 { "device", 1, 0, 'd' },
00188 { "eeprom-type", 1, 0, 'E' },
00189 { "eeprom-image", 1, 0, 'e' },
00190 { "flash-type", 1, 0, 'F' },
00191 { "list-devices", 0, 0, 'L' },
00192 { "disp-prog", 1, 0, 'P' },
00193 { "without-xterm", 1, 0, 'X' },
00194 { "core-dump", 0, 0, 'C' },
00195 { "clock-freq", 1, 0, 'c' },
00196 { "breakpoint", 1, 0, 'B' },
00197 { NULL, 0, 0, 0 }
00198 };
00199
00200
00201
00202
00203
00204 static void
00205 parse_cmd_line (int argc, char **argv)
00206 {
00207 int c;
00208 char *prog = argv[0];
00209 char *basename;
00210 int option_index;
00211 char dummy_char;
00212 int break_addr;
00213
00214 opterr = 0;
00215
00216 while (1)
00217 {
00218 c = getopt_long (argc, argv, "hgGvDLd:e:E:F:p:P:XCc:B:", long_opts,
00219 &option_index);
00220 if (c == -1)
00221 break;
00222
00223 switch (c)
00224 {
00225 case 'h':
00226 case '?':
00227 usage (prog);
00228 case 'g':
00229 global_gdbserver_mode = 1;
00230 break;
00231 case 'G':
00232 global_gdb_debug = 1;
00233 break;
00234 case 'p':
00235 global_gdbserver_port = atoi (optarg);
00236 break;
00237 case 'v':
00238 printf ("\n%s version %s\n", PACKAGE, VERSION);
00239 printf ("Copyright 2001, 2002, 2003, 2004"
00240 " Theodore A. Roth.\n");
00241 printf ("\n%s is free software, covered by the GNU General "
00242 "Public License,\n", PACKAGE);
00243 printf ("and you are welcome to change it and/or distribute "
00244 "copies of it under\n");
00245 printf ("the conditions of the GNU General Public License."
00246 "\n\n");
00247 exit (0);
00248 case 'D':
00249 global_debug_inst_output = 1;
00250 break;
00251 case 'd':
00252 global_device_type = optarg;
00253 break;
00254 case 'e':
00255 global_eeprom_image_file = avr_strdup (optarg);
00256 break;
00257 case 'E':
00258 break;
00259 global_eeprom_image_type = str2ffmt (optarg);
00260 case 'F':
00261 global_flash_image_type = str2ffmt (optarg);
00262 break;
00263 case 'L':
00264 dev_supp_list_devices (stdout);
00265 exit (0);
00266 case 'P':
00267 global_disp_prog = avr_strdup (optarg);
00268 break;
00269 case 'X':
00270 global_disp_without_xterm = 1;
00271 break;
00272 case 'C':
00273 global_dump_core = 1;
00274 break;
00275 case 'c':
00276 if (sscanf (optarg, "%d%c", &global_clock_freq, &dummy_char)
00277 != 1)
00278 {
00279 avr_error ("Invalid clock value: %s", optarg);
00280 }
00281 avr_warning ("Clock frequency option is not yet "
00282 "implemented.\n");
00283 break;
00284 case 'B':
00285 if (sscanf (optarg, "%i%c", &break_addr, &dummy_char) != 1)
00286 {
00287 avr_error ("Ignoring invalid break addres: %s", optarg);
00288 }
00289
00290 if (global_break_count < LEN_BREAK_LIST)
00291 {
00292 global_break_list[global_break_count] = break_addr;
00293 global_break_count++;
00294 }
00295 else
00296 {
00297 avr_warning ("Too many break points: igoring %s\n",
00298 optarg);
00299 }
00300
00301 break;
00302 default:
00303 avr_error ("getop() did something screwey");
00304 }
00305 }
00306
00307 if ((optind + 1) == argc)
00308 global_flash_image_file = argv[optind];
00309 else if (optind != argc)
00310 usage (prog);
00311
00312
00313
00314
00315 if ((global_eeprom_image_type != FFMT_BIN)
00316 || (global_flash_image_type != FFMT_BIN))
00317 {
00318 fprintf (stderr,
00319 "Only the bin file format is currently "
00320 "implemented. Sorry.\n");
00321 exit (1);
00322 }
00323
00324
00325
00326
00327 if (global_device_type == NULL)
00328 {
00329
00330 basename = strrchr (prog, '/');
00331 if (basename == NULL)
00332
00333 global_device_type = prog;
00334 else
00335 global_device_type = ++basename;
00336 }
00337 }
00338
00339 uint8_t
00340 ext_port_rd (int addr)
00341 {
00342 int data;
00343 char line[80];
00344
00345 while (1)
00346 {
00347 fprintf (stderr, "\nEnter a byte of data to read into 0x%04x: ",
00348 addr);
00349
00350
00351 if (fgets (line, sizeof (line), stdin) == NULL)
00352 continue;
00353
00354
00355 if (sscanf (line, "%i\n", &data) != 1)
00356 continue;
00357
00358 break;
00359 }
00360 return (uint8_t) (data & 0xff);
00361 }
00362
00363 void
00364 ext_port_wr (int addr, uint8_t val)
00365 {
00366 fprintf (stderr, "writing 0x%02x to 0x%04x\n", val, addr);
00367 fflush (stderr);
00368 }
00369
00370
00371
00372 void
00373 atexit_cleanup (void)
00374 {
00375 FILE *dump;
00376
00377 if (global_dump_core)
00378 {
00379 if ((dump = fopen ("core_avr_dump.core", "w")) == NULL)
00380 {
00381
00382 fprintf (stderr, "fopen failed: core_avr_dump.core: %s\n",
00383 strerror (errno));
00384 }
00385 else
00386 {
00387 avr_core_dump_core (global_core, dump);
00388 fclose (dump);
00389 }
00390 }
00391
00392 class_unref ((AvrClass *)global_core);
00393 }
00394
00395
00396
00397
00398
00399 int
00400 main (int argc, char **argv)
00401 {
00402 int i;
00403 int flash_sz = 0, sram_sz = 0, eeprom_sz = 0;
00404 int sram_start = 0;
00405
00406 parse_cmd_line (argc, argv);
00407
00408 global_core = avr_core_new (global_device_type);
00409 if (global_core == NULL)
00410 {
00411 avr_warning ("Device not supported: %s\n", global_device_type);
00412 exit (1);
00413 }
00414
00415 avr_message ("Simulating clock frequency of %d Hz\n", global_clock_freq);
00416
00417 avr_core_get_sizes (global_core, &flash_sz, &sram_sz, &sram_start,
00418 &eeprom_sz);
00419 display_open (global_disp_prog, global_disp_without_xterm, flash_sz,
00420 sram_sz, sram_start, eeprom_sz);
00421 avr_core_io_display_names (global_core);
00422
00423
00424 display_clock (0);
00425
00426
00427 if (atexit (atexit_cleanup))
00428 avr_error ("Failed to install exit handler");
00429
00430 #if 0
00431
00432 avr_core_add_ext_rd_wr (global_core, PORT_B_BASE, ext_port_rd,
00433 ext_port_wr);
00434 avr_core_add_ext_rd_wr (global_core, PORT_C_BASE, ext_port_rd,
00435 ext_port_wr);
00436 avr_core_add_ext_rd_wr (global_core, PORT_D_BASE, ext_port_rd,
00437 ext_port_wr);
00438 #endif
00439
00440
00441 if (global_flash_image_file)
00442 avr_core_load_program (global_core, global_flash_image_file,
00443 global_flash_image_type);
00444
00445
00446 if (global_eeprom_image_file)
00447 avr_core_load_eeprom (global_core, global_eeprom_image_file,
00448 global_eeprom_image_type);
00449
00450 for (i = 0; i < global_break_count; i++)
00451 {
00452
00453
00454
00455
00456 avr_message ("Setting breakpoint at 0x%x.\n", global_break_list[i]);
00457 avr_core_insert_breakpoint (global_core, global_break_list[i] / 2);
00458 }
00459
00460 if (global_gdbserver_mode == 1)
00461 {
00462 global_gdb_comm->user_data = global_core;
00463 gdb_interact (global_gdb_comm, global_gdbserver_port,
00464 global_gdb_debug);
00465 }
00466 else
00467 {
00468 if (global_flash_image_file)
00469
00470 avr_core_run (global_core);
00471 else
00472 fprintf (stderr, "No program was specified to be run.\n");
00473 }
00474
00475 display_close ();
00476
00477 exit (0);
00478 return 0;
00479 }