main.c
1 /*
2  * $Id: main.c,v 1.40 2004/04/17 00:03:51 troth Exp $
3  *
4  ****************************************************************************
5  *
6  * simulavr - A simulator for the Atmel AVR family of microcontrollers.
7  * Copyright (C) 2001, 2002, 2003, 2004 Theodore A. Roth
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22  *
23  ****************************************************************************
24  */
25 
26 #include <config.h>
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <errno.h>
32 
33 #include "avrerror.h"
34 #include "avrmalloc.h"
35 #include "avrclass.h"
36 #include "utils.h"
37 #include "callback.h"
38 #include "op_names.h"
39 
40 #include "storage.h"
41 #include "flash.h"
42 
43 #include "vdevs.h"
44 #include "memory.h"
45 #include "stack.h"
46 #include "register.h"
47 #include "sram.h"
48 #include "eeprom.h"
49 #include "timers.h"
50 #include "ports.h"
51 
52 #include "avrcore.h"
53 
54 #include "devsupp.h"
55 #include "display.h"
56 
57 #include "gdb.h"
58 #include "gnu_getopt.h"
59 
60 /****************************************************************************\
61  *
62  * global variables (keep them to a minimum)
63  *
64 \****************************************************************************/
65 
66 static char *global_device_type = NULL;
67 
68 static int global_eeprom_image_type = FFMT_BIN;
69 static char *global_eeprom_image_file = NULL;
70 
71 static int global_flash_image_type = FFMT_BIN;
72 static char *global_flash_image_file = NULL;
73 
74 static int global_gdbserver_mode = 0;
75 static int global_gdbserver_port = 1212; /* default port number */
76 static int global_gdb_debug = 0;
77 
78 static char *global_disp_prog = NULL;
79 static int global_disp_without_xterm = 0;
80 
81 static int global_dump_core = 0;
82 
83 static int global_clock_freq = 8000000; /* Default is 8 MHz. */
84 
85 /* If the user needs more than LEN_BREAK_LIST on the command line, they've got
86  bigger problems. */
87 
88 #define LEN_BREAK_LIST 50
89 static int global_break_count = 0;
90 static int global_break_list[LEN_BREAK_LIST];
91 
92 static AvrCore *global_core = NULL;
93 
94 /* *INDENT-OFF* */
95 static GdbComm_T global_gdb_comm[1] = {{
96  .user_data = NULL, /* user_data: will be global_core later */
97 
98  .read_reg = (CommFuncReadReg) avr_core_gpwr_get,
99  .write_reg = (CommFuncWriteReg) avr_core_gpwr_set,
100 
101  .read_sreg = (CommFuncReadSREG) avr_core_sreg_get,
102  .write_sreg = (CommFuncWriteSREG) avr_core_sreg_set,
103 
104  .read_pc = (CommFuncReadPC) avr_core_PC_get,
105  .write_pc = (CommFuncWritePC) avr_core_PC_set,
106  .max_pc = (CommFuncMaxPC) avr_core_PC_max,
107 
108  .read_sram = (CommFuncReadSRAM) avr_core_mem_read,
109  .write_sram = (CommFuncWriteSRAM) avr_core_mem_write,
110 
111  .read_flash = (CommFuncReadFlash) avr_core_flash_read,
112  .write_flash = (CommFuncWriteFlash) avr_core_flash_write,
113  .write_flash_lo8 = (CommFuncWriteFlashLo8) avr_core_flash_write_lo8,
114  .write_flash_hi8 = (CommFuncWriteFlashHi8) avr_core_flash_write_hi8,
115 
116  .insert_break = (CommFuncInsertBreak) avr_core_insert_breakpoint,
117  .remove_break = (CommFuncRemoveBreak) avr_core_remove_breakpoint,
118  .enable_breakpts = (CommFuncEnableBrkpts) avr_core_enable_breakpoints,
119  .disable_breakpts = (CommFuncDisableBrkpts) avr_core_disable_breakpoints,
120 
121  .step = (CommFuncStep) avr_core_step,
122  .reset = (CommFuncReset) avr_core_reset,
123 
124  .io_fetch = (CommFuncIORegFetch) avr_core_io_fetch,
125 
126  .irq_raise = (CommFuncIrqRaise) avr_core_irq_raise,
127 }};
128 
129 static char *usage_fmt_str =
130 "\nUsage: %s [OPTIONS]... [flash_image]\n" "\n"
131 "Simulate an avr device. The optional flash_image file is loaded\n"
132 "into the flash program memory space of the device.\n" "\n" "Options:\n"
133 " -h, --help : Show this message\n"
134 " -D, --debug : Debug instruction output\n"
135 " -v, --version : Print out the version number and exit\n"
136 " -g, --gdbserver : Run as a gdbserver process\n"
137 " -G, --gdb-debug : Print out debug messages for gdbserver\n"
138 " -p, --port <port> : Listen for gdb connection on TCP port\n"
139 " -d, --device <dev> : Specify device type\n"
140 " -e, --eeprom-image <img> : Specify an eeprom image file\n"
141 " -E, --eeprom-type <type> : Specify the type of the eeprom image file\n"
142 " -F, --flash-type <type> : Specify the type of the flash image file\n"
143 " -L, --list-devices : Print supported devices to stdout and exit\n"
144 " -P, --disp-prog <prog> : Display register and memory info with prog\n"
145 " -X, --without-xterm : Don't start disp prog in an xterm\n"
146 " -C, --core-dump : Dump a core memory image to file on exit\n"
147 " -c, --clock-freq <freq> : Set the simulated mcu clock freqency (in Hz)\n"
148 " -B, --breakpoint <addr> : Set a breakpoint (address is a byte address)\n"
149 "\n" "If the image file types for eeprom or flash images are not given,\n"
150 "the default file type is binary.\n" "\n"
151 "If you wish to run the simulator in gdbserver mode, you do not\n"
152 "have to specify a flash-image file since the program can be loaded\n"
153 "from gdb via the `load` command.\n" "\n"
154 "If '--port' option is given, and '--gdbserver' is not, port is ignored\n"
155 "\n" "If running in gdbserver mode and port is not specified, a default\n"
156 "port of 1212 is used.\n" "\n"
157 "If using the '--breakpoint' option, note the simulator will terminate when\n"
158 "the address is hit if you are not running in gdbserver mode. This feature\n"
159 "not intended for use in gdbserver mode. It is really intended for testing\n"
160 "the simulator itself, but may be useful for testing avr programs too.\n"
161 "\n" "Currently available device types:\n";
162 
163 /* *INDENT-ON* */
164 
165 /*
166  * Print usage message.
167  */
168 static void
169 usage (char *prog)
170 {
171  fprintf (stdout, usage_fmt_str, prog);
172  dev_supp_list_devices (stdout);
173  fprintf (stdout, "\n");
174 
175  exit (1);
176 }
177 
178 /* *INDENT-OFF* */
179 static struct option long_opts[] = {
180  /* name, has_arg, flag, val */
181  { "help", 0, 0, 'h' },
182  { "debug", 0, 0, 'D' },
183  { "version", 0, 0, 'v' },
184  { "gdbserver", 0, 0, 'g' },
185  { "gdb-debug", 0, 0, 'G' },
186  { "port", 1, 0, 'p' },
187  { "device", 1, 0, 'd' },
188  { "eeprom-type", 1, 0, 'E' },
189  { "eeprom-image", 1, 0, 'e' },
190  { "flash-type", 1, 0, 'F' },
191  { "list-devices", 0, 0, 'L' },
192  { "disp-prog", 1, 0, 'P' },
193  { "without-xterm", 1, 0, 'X' },
194  { "core-dump", 0, 0, 'C' },
195  { "clock-freq", 1, 0, 'c' },
196  { "breakpoint", 1, 0, 'B' },
197  { NULL, 0, 0, 0 }
198 };
199 /* *INDENT-ON* */
200 
201 /*
202  * Parse the command line arguments.
203  */
204 static void
205 parse_cmd_line (int argc, char **argv)
206 {
207  int c;
208  char *prog = argv[0];
209  char *basename;
210  int option_index;
211  char dummy_char;
212  int break_addr;
213 
214  opterr = 0; /* disable default error message */
215 
216  while (1)
217  {
218  c = getopt_long (argc, argv, "hgGvDLd:e:E:F:p:P:XCc:B:", long_opts,
219  &option_index);
220  if (c == -1)
221  break; /* no more options */
222 
223  switch (c)
224  {
225  case 'h':
226  case '?':
227  usage (prog);
228  case 'g':
229  global_gdbserver_mode = 1;
230  break;
231  case 'G':
232  global_gdb_debug = 1;
233  break;
234  case 'p':
235  global_gdbserver_port = atoi (optarg);
236  break;
237  case 'v':
238  printf ("\n%s version %s\n", PACKAGE, VERSION);
239  printf ("Copyright 2001, 2002, 2003, 2004"
240  " Theodore A. Roth.\n");
241  printf ("\n%s is free software, covered by the GNU General "
242  "Public License,\n", PACKAGE);
243  printf ("and you are welcome to change it and/or distribute "
244  "copies of it under\n");
245  printf ("the conditions of the GNU General Public License."
246  "\n\n");
247  exit (0);
248  case 'D':
250  break;
251  case 'd':
252  global_device_type = optarg;
253  break;
254  case 'e':
255  global_eeprom_image_file = avr_strdup (optarg);
256  break;
257  case 'E':
258  break;
259  global_eeprom_image_type = str2ffmt (optarg);
260  case 'F':
261  global_flash_image_type = str2ffmt (optarg);
262  break;
263  case 'L':
264  dev_supp_list_devices (stdout);
265  exit (0);
266  case 'P':
267  global_disp_prog = avr_strdup (optarg);
268  break;
269  case 'X':
270  global_disp_without_xterm = 1;
271  break;
272  case 'C':
273  global_dump_core = 1;
274  break;
275  case 'c':
276  if (sscanf (optarg, "%d%c", &global_clock_freq, &dummy_char)
277  != 1)
278  {
279  avr_error ("Invalid clock value: %s", optarg);
280  }
281  avr_warning ("Clock frequency option is not yet "
282  "implemented.\n");
283  break;
284  case 'B':
285  if (sscanf (optarg, "%i%c", &break_addr, &dummy_char) != 1)
286  {
287  avr_error ("Ignoring invalid break addres: %s", optarg);
288  }
289 
290  if (global_break_count < LEN_BREAK_LIST)
291  {
292  global_break_list[global_break_count] = break_addr;
293  global_break_count++;
294  }
295  else
296  {
297  avr_warning ("Too many break points: igoring %s\n",
298  optarg);
299  }
300 
301  break;
302  default:
303  avr_error ("getop() did something screwey");
304  }
305  }
306 
307  if ((optind + 1) == argc)
308  global_flash_image_file = argv[optind];
309  else if (optind != argc)
310  usage (prog);
311 
312  /* FIXME: Issue a warning and bail out if user selects a file format type
313  we haven't implemented yet. */
314 
315  if ((global_eeprom_image_type != FFMT_BIN)
316  || (global_flash_image_type != FFMT_BIN))
317  {
318  fprintf (stderr,
319  "Only the bin file format is currently "
320  "implemented. Sorry.\n");
321  exit (1);
322  }
323 
324  /* If user didn't specify a device type, see if it can be gleaned from the
325  name of the program. */
326 
327  if (global_device_type == NULL)
328  {
329  /* find the last '/' in dev_name */
330  basename = strrchr (prog, '/');
331  if (basename == NULL)
332  /* no slash in dev_name */
333  global_device_type = prog;
334  else
335  global_device_type = ++basename;
336  }
337 }
338 
339 uint8_t
340 ext_port_rd (int addr)
341 {
342  int data;
343  char line[80];
344 
345  while (1)
346  {
347  fprintf (stderr, "\nEnter a byte of data to read into 0x%04x: ",
348  addr);
349 
350  /* try to read in a line of input */
351  if (fgets (line, sizeof (line), stdin) == NULL)
352  continue;
353 
354  /* try to parse the line for a byte of data */
355  if (sscanf (line, "%i\n", &data) != 1)
356  continue;
357 
358  break;
359  }
360  return (uint8_t) (data & 0xff);
361 }
362 
363 void
364 ext_port_wr (int addr, uint8_t val)
365 {
366  fprintf (stderr, "writing 0x%02x to 0x%04x\n", val, addr);
367  fflush (stderr);
368 }
369 
370 /* This is called whenever the program terminates via a call to exit(). */
371 
372 void
373 atexit_cleanup (void)
374 {
375  FILE *dump;
376 
377  if (global_dump_core)
378  {
379  if ((dump = fopen ("core_avr_dump.core", "w")) == NULL)
380  {
381  /* can't call avr_error here since it could have called us */
382  fprintf (stderr, "fopen failed: core_avr_dump.core: %s\n",
383  strerror (errno));
384  }
385  else
386  {
387  avr_core_dump_core (global_core, dump);
388  fclose (dump);
389  }
390  }
391 
392  class_unref ((AvrClass *)global_core);
393 }
394 
395 /*
396  * Symlinks should be created for each supported device to the
397  * simulavr program.
398  */
399 int
400 main (int argc, char **argv)
401 {
402  int i;
403  int flash_sz = 0, sram_sz = 0, eeprom_sz = 0;
404  int sram_start = 0;
405 
406  parse_cmd_line (argc, argv);
407 
408  global_core = avr_core_new (global_device_type);
409  if (global_core == NULL)
410  {
411  avr_warning ("Device not supported: %s\n", global_device_type);
412  exit (1);
413  }
414 
415  avr_message ("Simulating clock frequency of %d Hz\n", global_clock_freq);
416 
417  avr_core_get_sizes (global_core, &flash_sz, &sram_sz, &sram_start,
418  &eeprom_sz);
419  display_open (global_disp_prog, global_disp_without_xterm, flash_sz,
420  sram_sz, sram_start, eeprom_sz);
421  avr_core_io_display_names (global_core);
422 
423  /* Send initial clock cycles to display */
424  display_clock (0);
425 
426  /* install my_atexit to be called when exit() is called */
427  if (atexit (atexit_cleanup))
428  avr_error ("Failed to install exit handler");
429 
430 #if 0
431  /* Add external device hooks to ports */
432  avr_core_add_ext_rd_wr (global_core, PORT_B_BASE, ext_port_rd,
433  ext_port_wr);
434  avr_core_add_ext_rd_wr (global_core, PORT_C_BASE, ext_port_rd,
435  ext_port_wr);
436  avr_core_add_ext_rd_wr (global_core, PORT_D_BASE, ext_port_rd,
437  ext_port_wr);
438 #endif
439 
440  /* Load program into flash */
441  if (global_flash_image_file)
442  avr_core_load_program (global_core, global_flash_image_file,
443  global_flash_image_type);
444 
445  /* Load eeprom data image into eeprom */
446  if (global_eeprom_image_file)
447  avr_core_load_eeprom (global_core, global_eeprom_image_file,
448  global_eeprom_image_type);
449 
450  for (i = 0; i < global_break_count; i++)
451  {
452  /* Note that we interpret the break address from the user as a byte
453  address instead of a word address. This makes it easier on the user
454  since binutils, gcc and gdb all work in terms of byte addresses. */
455 
456  avr_message ("Setting breakpoint at 0x%x.\n", global_break_list[i]);
457  avr_core_insert_breakpoint (global_core, global_break_list[i] / 2);
458  }
459 
460  if (global_gdbserver_mode == 1)
461  {
462  global_gdb_comm->user_data = global_core;
463  gdb_interact (global_gdb_comm, global_gdbserver_port,
464  global_gdb_debug);
465  }
466  else
467  {
468  if (global_flash_image_file)
469  /* Run the program */
470  avr_core_run (global_core);
471  else
472  fprintf (stderr, "No program was specified to be run.\n");
473  }
474 
475  display_close (); /* close down the display coprocess */
476 
477  exit (0);
478  return 0;
479 }

Automatically generated by Doxygen 1.8.2 on Fri Aug 1 2014.