/*
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);
}