run_avr: Add -v argument to raise verbosity level
[simavr] / simavr / sim / run_avr.c
1 /*
2         run_avr.c
3
4         Copyright 2008, 2010 Michel Pollet <buserror@gmail.com>
5
6         This file is part of simavr.
7
8         simavr is free software: you can redistribute it and/or modify
9         it under the terms of the GNU General Public License as published by
10         the Free Software Foundation, either version 3 of the License, or
11         (at your option) any later version.
12
13         simavr is distributed in the hope that it will be useful,
14         but WITHOUT ANY WARRANTY; without even the implied warranty of
15         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16         GNU General Public License for more details.
17
18         You should have received a copy of the GNU General Public License
19         along with simavr.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <libgen.h>
25 #include <string.h>
26 #include <signal.h>
27 #include "sim_avr.h"
28 #include "sim_elf.h"
29 #include "sim_core.h"
30 #include "sim_gdb.h"
31 #include "sim_hex.h"
32
33 #include "sim_core_decl.h"
34
35 void display_usage(char * app)
36 {
37         printf("Usage: %s [-t] [-g] [-v] [-m <device>] [-f <frequency>] firmware\n", app);
38         printf("       -t: Run full scale decoder trace\n"
39                    "       -g: Listen for gdb connection on port 1234\n"
40                    "       -ff: Load next .hex file as flash\n"
41                    "       -ee: Load next .hex file as eeprom\n"
42                    "       -v: Raise verbosity level (can be passed more than once)\n"
43                    "   Supported AVR cores:\n");
44         for (int i = 0; avr_kind[i]; i++) {
45                 printf("       ");
46                 for (int ti = 0; ti < 4 && avr_kind[i]->names[ti]; ti++)
47                         printf("%s ", avr_kind[i]->names[ti]);
48                 printf("\n");
49         }
50         exit(1);
51 }
52
53 avr_t * avr = NULL;
54
55 void
56 sig_int(
57                 int sign)
58 {
59         printf("signal caught, simavr terminating\n");
60         if (avr)
61                 avr_terminate(avr);
62         exit(0);
63 }
64
65 int main(int argc, char *argv[])
66 {
67         elf_firmware_t f = {{0}};
68         long f_cpu = 0;
69         int trace = 0;
70         int gdb = 0;
71         int log = 1;
72         char name[16] = "";
73         uint32_t loadBase = AVR_SEGMENT_OFFSET_FLASH;
74         int trace_vectors[8] = {0};
75         int trace_vectors_count = 0;
76
77         if (argc == 1)
78                 display_usage(basename(argv[0]));
79
80         for (int pi = 1; pi < argc; pi++) {
81                 if (!strcmp(argv[pi], "-h") || !strcmp(argv[pi], "-help")) {
82                         display_usage(basename(argv[0]));
83                 } else if (!strcmp(argv[pi], "-m") || !strcmp(argv[pi], "-mcu")) {
84                         if (pi < argc-1)
85                                 strcpy(name, argv[++pi]);
86                         else
87                                 display_usage(basename(argv[0]));
88                 } else if (!strcmp(argv[pi], "-f") || !strcmp(argv[pi], "-freq")) {
89                         if (pi < argc-1)
90                                 f_cpu = atoi(argv[++pi]);
91                         else
92                                 display_usage(basename(argv[0]));
93                 } else if (!strcmp(argv[pi], "-t") || !strcmp(argv[pi], "-trace")) {
94                         trace++;
95                 } else if (!strcmp(argv[pi], "-ti")) {
96                         if (pi < argc-1)
97                                 trace_vectors[trace_vectors_count++] = atoi(argv[++pi]);
98                 } else if (!strcmp(argv[pi], "-g") || !strcmp(argv[pi], "-gdb")) {
99                         gdb++;
100                 } else if (!strcmp(argv[pi], "-v")) {
101                         log++;
102                 } else if (!strcmp(argv[pi], "-ee")) {
103                         loadBase = AVR_SEGMENT_OFFSET_EEPROM;
104                 } else if (!strcmp(argv[pi], "-ff")) {
105                         loadBase = AVR_SEGMENT_OFFSET_FLASH;                    
106                 } else if (argv[pi][0] != '-') {
107                         char * filename = argv[pi];
108                         char * suffix = strrchr(filename, '.');
109                         if (suffix && !strcasecmp(suffix, ".hex")) {
110                                 if (!name[0] || !f_cpu) {
111                                         fprintf(stderr, "%s: -mcu and -freq are mandatory to load .hex files\n", argv[0]);
112                                         exit(1);
113                                 }
114                                 ihex_chunk_p chunk = NULL;
115                                 int cnt = read_ihex_chunks(filename, &chunk);
116                                 if (cnt <= 0) {
117                                         fprintf(stderr, "%s: Unable to load IHEX file %s\n", 
118                                                 argv[0], argv[pi]);
119                                         exit(1);
120                                 }
121                                 printf("Loaded %d section of ihex\n", cnt);
122                                 for (int ci = 0; ci < cnt; ci++) {
123                                         if (chunk[ci].baseaddr < (1*1024*1024)) {
124                                                 f.flash = chunk[ci].data;
125                                                 f.flashsize = chunk[ci].size;
126                                                 f.flashbase = chunk[ci].baseaddr;
127                                                 printf("Load HEX flash %08x, %d\n", f.flashbase, f.flashsize);
128                                         } else if (chunk[ci].baseaddr >= AVR_SEGMENT_OFFSET_EEPROM ||
129                                                         chunk[ci].baseaddr + loadBase >= AVR_SEGMENT_OFFSET_EEPROM) {
130                                                 // eeprom!
131                                                 f.eeprom = chunk[ci].data;
132                                                 f.eesize = chunk[ci].size;
133                                                 printf("Load HEX eeprom %08x, %d\n", chunk[ci].baseaddr, f.eesize);
134                                         }
135                                 }
136                         } else {
137                                 if (elf_read_firmware(filename, &f) == -1) {
138                                         fprintf(stderr, "%s: Unable to load firmware from file %s\n",
139                                                         argv[0], filename);
140                                         exit(1);
141                                 }
142                         }
143                 }
144         }
145
146         if (strlen(name))
147                 strcpy(f.mmcu, name);
148         if (f_cpu)
149                 f.frequency = f_cpu;
150
151         avr = avr_make_mcu_by_name(f.mmcu);
152         if (!avr) {
153                 fprintf(stderr, "%s: AVR '%s' not known\n", argv[0], f.mmcu);
154                 exit(1);
155         }
156         avr_init(avr);
157         avr_load_firmware(avr, &f);
158         if (f.flashbase) {
159                 printf("Attempted to load a bootloader at %04x\n", f.flashbase);
160                 avr->pc = f.flashbase;
161         }
162         avr->log = (log > LOG_TRACE ? LOG_TRACE : log);
163         avr->trace = trace;
164         for (int ti = 0; ti < trace_vectors_count; ti++)
165                 if (avr->interrupts.vector[trace_vectors[ti]])
166                         avr->interrupts.vector[trace_vectors[ti]]->trace = 1;
167
168         // even if not setup at startup, activate gdb if crashing
169         avr->gdb_port = 1234;
170         if (gdb) {
171                 avr->state = cpu_Stopped;
172                 avr_gdb_init(avr);
173         }
174
175         signal(SIGINT, sig_int);
176         signal(SIGTERM, sig_int);
177
178         for (;;) {
179                 int state = avr_run(avr);
180                 if ( state == cpu_Done || state == cpu_Crashed)
181                         break;
182         }
183         
184         avr_terminate(avr);
185 }