From f97d1c890b4aa9b1db6da9af829b87acf6776076 Mon Sep 17 00:00:00 2001 From: Michel Pollet Date: Wed, 15 Feb 2017 19:19:17 +0000 Subject: [PATCH] mmcu: Added VCD_PORT_PIN support Allows specing VCD traces for PORT/PIN directly in the firmware using a MMCU macro. Also did a bit of housekeeping in sim_elf since I was there... Signed-off-by: Michel Pollet --- simavr/sim/avr/avr_mcu_section.h | 10 +++ simavr/sim/sim_elf.c | 107 ++++++++++++++++++++++--------- simavr/sim/sim_elf.h | 5 ++ 3 files changed, 90 insertions(+), 32 deletions(-) diff --git a/simavr/sim/avr/avr_mcu_section.h b/simavr/sim/avr/avr_mcu_section.h index dc690d8..e528955 100644 --- a/simavr/sim/avr/avr_mcu_section.h +++ b/simavr/sim/avr/avr_mcu_section.h @@ -60,6 +60,7 @@ enum { AVR_MMCU_TAG_VCD_FILENAME, AVR_MMCU_TAG_VCD_PERIOD, AVR_MMCU_TAG_VCD_TRACE, + AVR_MMCU_TAG_VCD_PORTPIN, AVR_MMCU_TAG_PORT_EXTERNAL_PULL, }; @@ -196,6 +197,15 @@ struct avr_mmcu_vcd_trace_t { (((unsigned long)((_port)&0xff) << 16) | \ ((unsigned long)((_mask)&0xff) << 8) | \ ((_val)&0xff))); +/*! + * Add this port/pin to the VCD file. The syntax uses the name of the + * port as a character, and not a pointer to a register. + * AVR_MCU_VCD_PORT_PIN('B', 5); + */ +#define AVR_MCU_VCD_PORT_PIN(_port, _pin) \ + AVR_MCU_LONG(AVR_MMCU_TAG_VCD_PORTPIN, \ + (((unsigned long)((_port)&0xff) << 8) | \ + ((_pin)&0xff))); /*! * This tag allows you to specify the voltages used by your board diff --git a/simavr/sim/sim_elf.c b/simavr/sim/sim_elf.c index a45fe0a..583011b 100644 --- a/simavr/sim/sim_elf.c +++ b/simavr/sim/sim_elf.c @@ -41,7 +41,10 @@ #define O_BINARY 0 #endif -void avr_load_firmware(avr_t * avr, elf_firmware_t * firmware) +void +avr_load_firmware( + avr_t * avr, + elf_firmware_t * firmware) { if (firmware->frequency) avr->frequency = firmware->frequency; @@ -70,10 +73,17 @@ void avr_load_firmware(avr_t * avr, elf_firmware_t * firmware) } #endif - avr_loadcode(avr, firmware->flash, firmware->flashsize, firmware->flashbase); - avr->codeend = firmware->flashsize + firmware->flashbase - firmware->datasize; + avr_loadcode(avr, firmware->flash, + firmware->flashsize, firmware->flashbase); + avr->codeend = firmware->flashsize + + firmware->flashbase - firmware->datasize; + if (firmware->eeprom && firmware->eesize) { - avr_eeprom_desc_t d = { .ee = firmware->eeprom, .offset = 0, .size = firmware->eesize }; + avr_eeprom_desc_t d = { + .ee = firmware->eeprom, + .offset = 0, + .size = firmware->eesize + }; avr_ioctl(avr, AVR_IOCTL_EEPROM_SET, &d); } if (firmware->fuse) @@ -81,23 +91,19 @@ void avr_load_firmware(avr_t * avr, elf_firmware_t * firmware) if (firmware->lockbits) avr->lockbits = firmware->lockbits[0]; // 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); - } + for (int i = 0; i < 8 && firmware->external_state[i].port; i++) { + 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); // rest is initialization of the VCD file - - if (firmware->tracecount == 0) + if (firmware->tracecount == 0 && firmware->traceportcount == 0) return; avr->vcd = malloc(sizeof(*avr->vcd)); memset(avr->vcd, 0, sizeof(*avr->vcd)); @@ -106,25 +112,42 @@ void avr_load_firmware(avr_t * avr, elf_firmware_t * firmware) avr->vcd, firmware->traceperiod >= 1000 ? firmware->traceperiod : 1000); - AVR_LOG(avr, LOG_TRACE, "Creating VCD trace file '%s'\n", avr->vcd->filename); + AVR_LOG(avr, LOG_TRACE, "Creating VCD trace file '%s'\n", + avr->vcd->filename); + + for (int ti = 0; ti < firmware->traceportcount; ti++) { + avr_irq_t * irq = avr_io_getirq(avr, + AVR_IOCTL_IOPORT_GETIRQ(firmware->traceport[ti].port), + firmware->traceport[ti].pin); + if (irq) { + char name[16]; + sprintf(name, "%c%d", firmware->traceport[ti].port, + firmware->traceport[ti].pin); + avr_vcd_add_signal(avr->vcd, irq, 1, name); + } + } + for (int ti = 0; ti < firmware->tracecount; ti++) { - if (firmware->trace[ti].mask == 0xff || firmware->trace[ti].mask == 0) { + if (firmware->trace[ti].mask == 0xff || + firmware->trace[ti].mask == 0) { // easy one avr_irq_t * all = avr_iomem_getirq(avr, firmware->trace[ti].addr, firmware->trace[ti].name, AVR_IOMEM_IRQ_ALL); if (!all) { - AVR_LOG(avr, LOG_ERROR, "ELF: %s: unable to attach trace to address %04x\n", + AVR_LOG(avr, LOG_ERROR, + "ELF: %s: unable to attach trace to address %04x\n", __FUNCTION__, firmware->trace[ti].addr); } else { - avr_vcd_add_signal(avr->vcd, all, 8, firmware->trace[ti].name); + avr_vcd_add_signal(avr->vcd, all, 8, + firmware->trace[ti].name); } } else { - int count = 0; - for (int bi = 0; bi < 8; bi++) - if (firmware->trace[ti].mask & (1 << bi)) - count++; + int count = __builtin_popcount(firmware->trace[ti].mask); + // for (int bi = 0; bi < 8; bi++) + // if (firmware->trace[ti].mask & (1 << bi)) + // count++; for (int bi = 0; bi < 8; bi++) if (firmware->trace[ti].mask & (1 << bi)) { avr_irq_t * bit = avr_iomem_getirq(avr, @@ -132,18 +155,21 @@ void avr_load_firmware(avr_t * avr, elf_firmware_t * firmware) firmware->trace[ti].name, bi); if (!bit) { - AVR_LOG(avr, LOG_ERROR, "ELF: %s: unable to attach trace to address %04x\n", + AVR_LOG(avr, LOG_ERROR, + "ELF: %s: unable to attach trace to address %04x\n", __FUNCTION__, firmware->trace[ti].addr); break; } if (count == 1) { - 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; } 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); } } } @@ -153,13 +179,19 @@ void avr_load_firmware(avr_t * avr, elf_firmware_t * firmware) avr_vcd_start(avr->vcd); } -static void elf_parse_mmcu_section(elf_firmware_t * firmware, uint8_t * src, uint32_t size) +static void +elf_parse_mmcu_section( + elf_firmware_t * firmware, + uint8_t * src, + uint32_t size) { +// hdump(".mmcu", src, size); while (size) { uint8_t tag = *src++; uint8_t ts = *src++; int next = size > 2 + ts ? 2 + ts : size; - // printf("elf_parse_mmcu_section %d, %d / %d\n", tag, ts, size); + // printf("elf_parse_mmcu_section %2d, size %2d / remains %3d\n", + // tag, ts, size); switch (tag) { case AVR_MMCU_TAG_FREQUENCY: firmware->frequency = @@ -186,7 +218,8 @@ static void elf_parse_mmcu_section(elf_firmware_t * firmware, uint8_t * src, uin 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", + 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); @@ -197,13 +230,23 @@ static void elf_parse_mmcu_section(elf_firmware_t * firmware, uint8_t * src, uin uint8_t mask = src[0]; uint16_t addr = src[1] | (src[2] << 8); char * name = (char*)src + 3; - AVR_LOG(NULL, LOG_TRACE, "AVR_MMCU_TAG_VCD_TRACE %04x:%02x - %s\n", addr, mask, name); + 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, sizeof(firmware->trace[firmware->tracecount].name)); firmware->tracecount++; } break; + case AVR_MMCU_TAG_VCD_PORTPIN: { + firmware->traceport[firmware->traceportcount].pin = src[0]; + firmware->traceport[firmware->traceportcount].port = src[1]; + printf("trace PORT %c pin %d\n", + firmware->traceport[firmware->traceportcount].port, + firmware->traceport[firmware->traceportcount].pin); + firmware->traceportcount++; + } break; case AVR_MMCU_TAG_VCD_FILENAME: { strcpy(firmware->tracename, (char*)src); } break; diff --git a/simavr/sim/sim_elf.h b/simavr/sim/sim_elf.h index 9d6bc71..997b8d7 100644 --- a/simavr/sim/sim_elf.h +++ b/simavr/sim/sim_elf.h @@ -53,6 +53,11 @@ typedef struct elf_firmware_t { uint16_t addr; char name[64]; } trace[32]; + int traceportcount; + struct { + char port; + int8_t pin; + } traceport[16]; struct { char port; -- 2.39.5