/*
avr_mcu_section.h
- Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
+ Copyright 2008-2013 Michel Pollet <buserror@gmail.com>
This file is part of simavr.
AVR_MMCU_TAG_SIMAVR_COMMAND,
AVR_MMCU_TAG_SIMAVR_CONSOLE,
AVR_MMCU_TAG_VCD_FILENAME,
- AVR_MMCU_TAG_VCD_PERIOD,
+ AVR_MMCU_TAG_VCD_PERIOD,
AVR_MMCU_TAG_VCD_TRACE,
+ AVR_MMCU_TAG_PORT_EXTERNAL_PULL,
};
enum {
struct avr_mmcu_long_t {
uint8_t tag;
uint8_t len;
- uint32_t val;
+ uint32_t val;
} __attribute__((__packed__));
struct avr_mmcu_string_t {
uint8_t tag;
uint8_t len;
- char string[];
+ char string[];
} __attribute__((__packed__));
struct avr_mmcu_addr_t {
uint8_t len;
uint8_t mask;
void * what;
- char name[];
+ char name[];
} __attribute__((__packed__));
#define AVR_MCU_STRING(_tag, _str) \
.len = sizeof(void *),\
.what = (void*)_register, \
}
+/*!
+ * Allows the firmware to hint simavr as to wether there are external
+ * pullups/down on PORT pins. It helps if the firmware uses "open drain"
+ * pins by toggling the DDR pins to switch between an output state and
+ * a "default" state.
+ * The value passed here will be output on the PORT IRQ when the DDR
+ * pin is set to input again
+ */
+#define AVR_MCU_EXTERNAL_PORT_PULL(_port, _mask, _val) \
+ AVR_MCU_LONG(AVR_MMCU_TAG_PORT_EXTERNAL_PULL, \
+ (((unsigned long)(_port) << 16) | \
+ ((unsigned long)(_mask) << 8) | \
+ (_val)));
/*!
* This tag allows you to specify the voltages used by your board
#include "sim_elf.h"
#include "sim_vcd_file.h"
#include "avr_eeprom.h"
+#include "avr_ioport.h"
#ifndef O_BINARY
#define O_BINARY 0
for (int i = 0; i < firmware->symbolcount; i++)
if (!(firmware->symbol[i]->addr >> 20)) // code address
- avr->trace_data->codeline[firmware->symbol[i]->addr >> 1] =
+ avr->trace_data->codeline[firmware->symbol[i]->addr >> 1] =
firmware->symbol[i];
// "spread" the pointers for known symbols forward
avr_symbol_t * last = NULL;
avr_eeprom_desc_t d = { .ee = firmware->eeprom, .offset = 0, .size = firmware->eesize };
avr_ioctl(avr, AVR_IOCTL_EEPROM_SET, &d);
}
-
+ // load the default pull up/down values for ports
+ for (int i = 0; i < 8; i++)
+ if (firmware->external_state[i].port == 0)
+ break;
+ else {
+ avr_ioport_external_t e = {
+ .name = firmware->external_state[i].port,
+ .mask = firmware->external_state[i].mask,
+ .value = firmware->external_state[i].value,
+ };
+ avr_ioctl(avr, AVR_IOCTL_IOPORT_SET_EXTERNAL(e.name), &e);
+ }
avr_set_command_register(avr, firmware->command_register_addr);
avr_set_console_register(avr, firmware->console_register_addr);
return;
avr->vcd = malloc(sizeof(*avr->vcd));
memset(avr->vcd, 0, sizeof(*avr->vcd));
- avr_vcd_init(avr,
+ avr_vcd_init(avr,
firmware->tracename[0] ? firmware->tracename: "gtkwave_trace.vcd",
avr->vcd,
firmware->traceperiod >= 1000 ? firmware->traceperiod : 1000);
-
+
AVR_LOG(avr, LOG_TRACE, "Creating VCD trace file '%s'\n", avr->vcd->filename);
for (int ti = 0; ti < firmware->tracecount; ti++) {
if (firmware->trace[ti].mask == 0xff || firmware->trace[ti].mask == 0) {
__FUNCTION__, firmware->trace[ti].addr);
break;
}
-
+
if (count == 1) {
avr_vcd_add_signal(avr->vcd, bit, 1, firmware->trace[ti].name);
break;
}
char comp[128];
sprintf(comp, "%s.%d", firmware->trace[ti].name, bi);
- avr_vcd_add_signal(avr->vcd, bit, 1, firmware->trace[ti].name);
+ avr_vcd_add_signal(avr->vcd, bit, 1, firmware->trace[ti].name);
}
}
}
break;
case AVR_MMCU_TAG_NAME:
strcpy(firmware->mmcu, (char*)src);
- break;
+ break;
case AVR_MMCU_TAG_VCC:
firmware->vcc =
src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
firmware->aref =
src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
break;
+ case AVR_MMCU_TAG_PORT_EXTERNAL_PULL: {
+ for (int i = 0; i < 8; i++)
+ if (!firmware->external_state[i].port) {
+ firmware->external_state[i].port = src[2];
+ firmware->external_state[i].mask = src[1];
+ firmware->external_state[i].value = src[0];
+ AVR_LOG(NULL, LOG_TRACE, "AVR_MMCU_TAG_PORT_EXTERNAL_PULL[%d] %c:%02x:%02x\n",
+ i, firmware->external_state[i].port,
+ firmware->external_state[i].mask,
+ firmware->external_state[i].value);
+ break;
+ }
+ } break;
case AVR_MMCU_TAG_VCD_TRACE: {
uint8_t mask = src[0];
uint16_t addr = src[1] | (src[2] << 8);
AVR_LOG(NULL, LOG_TRACE, "AVR_MMCU_TAG_VCD_TRACE %04x:%02x - %s\n", addr, mask, name);
firmware->trace[firmware->tracecount].mask = mask;
firmware->trace[firmware->tracecount].addr = addr;
- strncpy(firmware->trace[firmware->tracecount].name, name,
+ strncpy(firmware->trace[firmware->tracecount].name, name,
sizeof(firmware->trace[firmware->tracecount].name));
firmware->tracecount++;
} break;
return -1;
}
- Elf_Data *data_data = NULL,
+ Elf_Data *data_data = NULL,
*data_text = NULL,
*data_ee = NULL; /* Data Descriptor */
gelf_getsym(edata, i, &sym);
// print out the value and size
- if (ELF32_ST_BIND(sym.st_info) == STB_GLOBAL ||
- ELF32_ST_TYPE(sym.st_info) == STT_FUNC ||
+ if (ELF32_ST_BIND(sym.st_info) == STB_GLOBAL ||
+ ELF32_ST_TYPE(sym.st_info) == STT_FUNC ||
ELF32_ST_TYPE(sym.st_info) == STT_OBJECT) {
const char * name = elf_strptr(elf, shdr.sh_link, sym.st_name);
s->addr = sym.st_value;
if (!(firmware->symbolcount % 8))
firmware->symbol = realloc(
- firmware->symbol,
+ firmware->symbol,
(firmware->symbolcount + 8) * sizeof(firmware->symbol[0]));
-
+
// insert new element, keep the array sorted
int insert = -1;
for (int si = 0; si < firmware->symbolcount && insert == -1; si++)
if (insert == -1)
insert = firmware->symbolcount;
else
- memmove(firmware->symbol + insert + 1,
+ memmove(firmware->symbol + insert + 1,
firmware->symbol + insert,
(firmware->symbolcount - insert) * sizeof(firmware->symbol[0]));
- firmware->symbol[insert] = s;
+ firmware->symbol[insert] = s;
firmware->symbolcount++;
}
}
(data_text ? data_text->d_size : 0) +
(data_data ? data_data->d_size : 0);
firmware->flash = malloc(firmware->flashsize);
-
+
// using unsigned int for output, since there is no AVR with 4GB
if (data_text) {
// hdump("code", data_text->d_buf, data_text->d_size);