run_avr: Add -v argument to raise verbosity level
[simavr] / simavr / sim / run_avr.c
index 4560033..e18f1cd 100644 (file)
@@ -1,7 +1,7 @@
 /*
        run_avr.c
 
-       Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
+       Copyright 2008, 2010 Michel Pollet <buserror@gmail.com>
 
        This file is part of simavr.
 
 
 #include <stdlib.h>
 #include <stdio.h>
-#include <getopt.h>
+#include <libgen.h>
 #include <string.h>
+#include <signal.h>
 #include "sim_avr.h"
 #include "sim_elf.h"
 #include "sim_core.h"
 #include "sim_gdb.h"
-#include "avr_eeprom.h"
-#include "avr_uart.h"
+#include "sim_hex.h"
 
-void hdump(const char *w, uint8_t *b, size_t l)
+#include "sim_core_decl.h"
+
+void display_usage(char * app)
 {
-       uint32_t i;
-       if (l < 16) {
-               printf("%s: ",w);
-               for (i = 0; i < l; i++) printf("%02x",b[i]);
-       } else {
-               printf("%s:\n",w);
-               for (i = 0; i < l; i++) {
-                       if (!(i & 0x1f)) printf("    ");
-                       printf("%02x",b[i]);
-                       if ((i & 0x1f) == 0x1f) {
-                               printf(" ");
-                               printf("\n");
-                       }
-               }
+       printf("Usage: %s [-t] [-g] [-v] [-m <device>] [-f <frequency>] firmware\n", app);
+       printf("       -t: Run full scale decoder trace\n"
+                  "       -g: Listen for gdb connection on port 1234\n"
+                  "       -ff: Load next .hex file as flash\n"
+                  "       -ee: Load next .hex file as eeprom\n"
+                  "       -v: Raise verbosity level (can be passed more than once)\n"
+                  "   Supported AVR cores:\n");
+       for (int i = 0; avr_kind[i]; i++) {
+               printf("       ");
+               for (int ti = 0; ti < 4 && avr_kind[i]->names[ti]; ti++)
+                       printf("%s ", avr_kind[i]->names[ti]);
+               printf("\n");
        }
-       printf("\n");
+       exit(1);
 }
 
+avr_t * avr = NULL;
 
-void display_usage()
+void
+sig_int(
+               int sign)
 {
-       printf("usage: simavr [-t] [-g] [-m <device>] [-f <frequency>] firmware\n");
-       printf("       -t: run full scale decoder trace\n");
-       printf("       -g: listen for gdb connection on port 1234\n");
-       exit(1);
+       printf("signal caught, simavr terminating\n");
+       if (avr)
+               avr_terminate(avr);
+       exit(0);
 }
 
 int main(int argc, char *argv[])
 {
-       elf_firmware_t f;
+       elf_firmware_t f = {{0}};
        long f_cpu = 0;
        int trace = 0;
        int gdb = 0;
+       int log = 1;
        char name[16] = "";
-       int option_count;
-       int option_index = 0;
-
-       struct option long_options[] = {
-               {"help", no_argument, 0, 'h'},
-               {"mcu", required_argument, 0, 'm'},
-               {"freq", required_argument, 0, 'f'},
-               {"trace", no_argument, 0, 't'},
-               {"gdb", no_argument, 0, 'g'},
-               {0, 0, 0, 0}
-       };
+       uint32_t loadBase = AVR_SEGMENT_OFFSET_FLASH;
+       int trace_vectors[8] = {0};
+       int trace_vectors_count = 0;
 
        if (argc == 1)
-               display_usage();
-
-       while ((option_count = getopt_long(argc, argv, "tghm:f:", long_options, &option_index)) != -1) {
-               switch (option_count) {
-                       case 'h':
-                               display_usage();
-                               break;
-                       case 'm':
-                               strcpy(name, optarg);
-                               break;
-                       case 'f':
-                               f_cpu = atoi(optarg);
-                               break;
-                       case 't':
-                               trace++;
-                               break;
-                       case 'g':
-                               gdb++;
-                               break;
+               display_usage(basename(argv[0]));
+
+       for (int pi = 1; pi < argc; pi++) {
+               if (!strcmp(argv[pi], "-h") || !strcmp(argv[pi], "-help")) {
+                       display_usage(basename(argv[0]));
+               } else if (!strcmp(argv[pi], "-m") || !strcmp(argv[pi], "-mcu")) {
+                       if (pi < argc-1)
+                               strcpy(name, argv[++pi]);
+                       else
+                               display_usage(basename(argv[0]));
+               } else if (!strcmp(argv[pi], "-f") || !strcmp(argv[pi], "-freq")) {
+                       if (pi < argc-1)
+                               f_cpu = atoi(argv[++pi]);
+                       else
+                               display_usage(basename(argv[0]));
+               } else if (!strcmp(argv[pi], "-t") || !strcmp(argv[pi], "-trace")) {
+                       trace++;
+               } else if (!strcmp(argv[pi], "-ti")) {
+                       if (pi < argc-1)
+                               trace_vectors[trace_vectors_count++] = atoi(argv[++pi]);
+               } else if (!strcmp(argv[pi], "-g") || !strcmp(argv[pi], "-gdb")) {
+                       gdb++;
+               } else if (!strcmp(argv[pi], "-v")) {
+                       log++;
+               } else if (!strcmp(argv[pi], "-ee")) {
+                       loadBase = AVR_SEGMENT_OFFSET_EEPROM;
+               } else if (!strcmp(argv[pi], "-ff")) {
+                       loadBase = AVR_SEGMENT_OFFSET_FLASH;                    
+               } else if (argv[pi][0] != '-') {
+                       char * filename = argv[pi];
+                       char * suffix = strrchr(filename, '.');
+                       if (suffix && !strcasecmp(suffix, ".hex")) {
+                               if (!name[0] || !f_cpu) {
+                                       fprintf(stderr, "%s: -mcu and -freq are mandatory to load .hex files\n", argv[0]);
+                                       exit(1);
+                               }
+                               ihex_chunk_p chunk = NULL;
+                               int cnt = read_ihex_chunks(filename, &chunk);
+                               if (cnt <= 0) {
+                                       fprintf(stderr, "%s: Unable to load IHEX file %s\n", 
+                                               argv[0], argv[pi]);
+                                       exit(1);
+                               }
+                               printf("Loaded %d section of ihex\n", cnt);
+                               for (int ci = 0; ci < cnt; ci++) {
+                                       if (chunk[ci].baseaddr < (1*1024*1024)) {
+                                               f.flash = chunk[ci].data;
+                                               f.flashsize = chunk[ci].size;
+                                               f.flashbase = chunk[ci].baseaddr;
+                                               printf("Load HEX flash %08x, %d\n", f.flashbase, f.flashsize);
+                                       } else if (chunk[ci].baseaddr >= AVR_SEGMENT_OFFSET_EEPROM ||
+                                                       chunk[ci].baseaddr + loadBase >= AVR_SEGMENT_OFFSET_EEPROM) {
+                                               // eeprom!
+                                               f.eeprom = chunk[ci].data;
+                                               f.eesize = chunk[ci].size;
+                                               printf("Load HEX eeprom %08x, %d\n", chunk[ci].baseaddr, f.eesize);
+                                       }
+                               }
+                       } else {
+                               if (elf_read_firmware(filename, &f) == -1) {
+                                       fprintf(stderr, "%s: Unable to load firmware from file %s\n",
+                                                       argv[0], filename);
+                                       exit(1);
+                               }
+                       }
                }
        }
 
-       elf_read_firmware(argv[argc-1], &f);
-
        if (strlen(name))
-               strcpy(f.mmcu.name, name);
+               strcpy(f.mmcu, name);
        if (f_cpu)
-               f.mmcu.f_cpu = f_cpu;
-
-       printf("firmware %s f=%d mmcu=%s\n", argv[argc-1], (int)f.mmcu.f_cpu, f.mmcu.name);
+               f.frequency = f_cpu;
 
-       avr_t * avr = avr_make_mcu_by_name(f.mmcu.name);
+       avr = avr_make_mcu_by_name(f.mmcu);
        if (!avr) {
-               fprintf(stderr, "%s: AVR '%s' now known\n", argv[0], f.mmcu.name);
+               fprintf(stderr, "%s: AVR '%s' not known\n", argv[0], f.mmcu);
                exit(1);
        }
        avr_init(avr);
-       avr->frequency = f.mmcu.f_cpu;
-       avr->codeline = f.codeline;
-       avr_loadcode(avr, f.flash, f.flashsize, 0);
-       avr->codeend = f.flashsize - f.datasize;
-       if (f.eeprom && f.eesize) {
-               avr_eeprom_desc_t d = { .ee = f.eeprom, .offset = 0, .size = f.eesize };
-               avr_ioctl(avr, AVR_IOCTL_EEPROM_SET, &d);
+       avr_load_firmware(avr, &f);
+       if (f.flashbase) {
+               printf("Attempted to load a bootloader at %04x\n", f.flashbase);
+               avr->pc = f.flashbase;
        }
+       avr->log = (log > LOG_TRACE ? LOG_TRACE : log);
        avr->trace = trace;
+       for (int ti = 0; ti < trace_vectors_count; ti++)
+               if (avr->interrupts.vector[trace_vectors[ti]])
+                       avr->interrupts.vector[trace_vectors[ti]]->trace = 1;
 
-       // try to enable "local echo" on the first uart, for testing purposes
-       {
-               avr_irq_t * src = avr_io_getirq(avr, AVR_IOCTL_UART_GETIRQ('0'), UART_IRQ_OUTPUT);
-               avr_irq_t * dst = avr_io_getirq(avr, AVR_IOCTL_UART_GETIRQ('0'), UART_IRQ_INPUT);
-               printf("%s:%s activating uart local echo IRQ src %p dst %p\n", __FILE__, __FUNCTION__, src, dst);
-               if (src && dst)
-                       avr_connect_irq(avr, src, dst);
-       }
-
+       // even if not setup at startup, activate gdb if crashing
+       avr->gdb_port = 1234;
        if (gdb) {
                avr->state = cpu_Stopped;
                avr_gdb_init(avr);
        }
 
-//     for (long long i = 0; i < 8000000*10; i++)
-//     for (long long i = 0; i < 80000; i++)
-       for (;;)
-               avr_run(avr);
+       signal(SIGINT, sig_int);
+       signal(SIGTERM, sig_int);
+
+       for (;;) {
+               int state = avr_run(avr);
+               if ( state == cpu_Done || state == cpu_Crashed)
+                       break;
+       }
        
+       avr_terminate(avr);
 }