diff --git a/simavr/sim/avr/avr_mcu_section.h b/simavr/sim/avr/avr_mcu_section.h index 3deae7bac..e3f1c5fad 100644 --- a/simavr/sim/avr/avr_mcu_section.h +++ b/simavr/sim/avr/avr_mcu_section.h @@ -62,6 +62,8 @@ enum { AVR_MMCU_TAG_VCD_TRACE, AVR_MMCU_TAG_VCD_PORTPIN, AVR_MMCU_TAG_VCD_IRQ, + AVR_MMCU_TAG_VCD_SRAM_8, + AVR_MMCU_TAG_VCD_SRAM_16, AVR_MMCU_TAG_PORT_EXTERNAL_PULL, }; @@ -149,6 +151,16 @@ struct avr_mmcu_vcd_trace_t { .len = sizeof(struct avr_mmcu_vcd_trace_t) - 2,\ .name = _name +#define AVR_MCU_VCD_SRAM_8(_name) \ + .tag = AVR_MMCU_TAG_VCD_SRAM_8, \ + .len = sizeof(struct avr_mmcu_vcd_trace_t) - 2,\ + .name = _name + +#define AVR_MCU_VCD_SRAM_16(_name) \ + .tag = AVR_MMCU_TAG_VCD_SRAM_16, \ + .len = sizeof(struct avr_mmcu_vcd_trace_t) - 2,\ + .name = _name + /*! * Specifies the name and wanted period (in usec) for a VCD file * this is not mandatory for the VCD output to work, if this tag diff --git a/simavr/sim/avr_adc.c b/simavr/sim/avr_adc.c index 6adf1f267..425d5d333 100644 --- a/simavr/sim/avr_adc.c +++ b/simavr/sim/avr_adc.c @@ -31,17 +31,16 @@ avr_adc_int_raise( { avr_adc_t * p = (avr_adc_t *)param; if (avr_regbit_get(avr, p->aden)) { + if (!p->read_status) { + /* Update I/O registers. */ + avr_core_watch_write(avr, p->r_adcl, p->result & 0xff); + avr_core_watch_write(avr, p->r_adch, p->result >> 8); + } // if the interrupts are not used, still raised the UDRE and TXC flag avr_raise_interrupt(avr, &p->adc); avr_regbit_clear(avr, p->adsc); if( p->adts_mode == avr_adts_free_running ) avr_raise_irq(p->io.irq + ADC_IRQ_IN_TRIGGER, 1); - if (!p->read_status) { - /* Update I/O registers. */ - - avr->data[p->r_adcl] = p->result & 0xff; - avr->data[p->r_adch] = p->result >> 8; - } } return 0; } diff --git a/simavr/sim/run_avr.c b/simavr/sim/run_avr.c index 1f914fdb1..60cd42c68 100644 --- a/simavr/sim/run_avr.c +++ b/simavr/sim/run_avr.c @@ -55,7 +55,8 @@ display_usage( " [-ti ] Add traces for IRQ vector \n" " [--input|-i ] A VCD file to use as input signals\n" " [--output|-o ] A VCD file to save the traced signals\n" - " [--add-trace|-at ]\n" + " [--add-trace|-at ] or \n" + " ]\n" " Add signal to be included in VCD output\n" " [-ff <.hex file>] Load next .hex file as flash\n" " [-ee <.hex file>] Load next .hex file as eeprom\n" @@ -174,9 +175,11 @@ main( &trace.addr, &trace.mask ); - if (n_args != 4) { + + if ((n_args != 4) && + ((n_args != 3) || (strcmp(trace.kind, "sram8") && strcmp(trace.kind, "sram16")))) { --pi; - fprintf(stderr, "%s: format for %s is name=kind@addr/mask.\n", argv[0], argv[pi]); + fprintf(stderr, "%s: format for %s is name=kind@addr.\n", argv[0], argv[pi]); exit(1); } @@ -186,6 +189,10 @@ main( f.trace[f.tracecount].kind = AVR_MMCU_TAG_VCD_IRQ; } else if (!strcmp(trace.kind, "trace")) { f.trace[f.tracecount].kind = AVR_MMCU_TAG_VCD_TRACE; + } else if (!strcmp(trace.kind, "sram8")) { + f.trace[f.tracecount].kind = AVR_MMCU_TAG_VCD_SRAM_8; + } else if (!strcmp(trace.kind, "sram16")) { + f.trace[f.tracecount].kind = AVR_MMCU_TAG_VCD_SRAM_16; } else { fprintf( stderr, @@ -204,6 +211,8 @@ main( f.trace[f.tracecount].kind == AVR_MMCU_TAG_VCD_PORTPIN ? "portpin" : f.trace[f.tracecount].kind == AVR_MMCU_TAG_VCD_IRQ ? "irq" : f.trace[f.tracecount].kind == AVR_MMCU_TAG_VCD_TRACE ? "trace" + : f.trace[f.tracecount].kind == AVR_MMCU_TAG_VCD_SRAM_8 ? "sram8" + : f.trace[f.tracecount].kind == AVR_MMCU_TAG_VCD_SRAM_16 ? "sram16" : "unknown", f.trace[f.tracecount].addr, f.trace[f.tracecount].mask, diff --git a/simavr/sim/sim_avr.h b/simavr/sim/sim_avr.h index 71c3f4f6a..2bfa1a011 100644 --- a/simavr/sim/sim_avr.h +++ b/simavr/sim/sim_avr.h @@ -310,6 +310,15 @@ typedef struct avr_t { } io[4]; } io_shared_io[4]; + // SRAM tracepoint + #define SRAM_TRACEPOINT_SIZE 16 + int sram_tracepoint_count; + struct { + struct avr_irq_t * irq; + int width; + uint16_t addr; + } sram_tracepoint[SRAM_TRACEPOINT_SIZE]; + // flash memory (initialized to 0xff, and code loaded into it) uint8_t * flash; // this is the general purpose registers, IO registers, and SRAM diff --git a/simavr/sim/sim_core.c b/simavr/sim/sim_core.c index 4f21c1ee7..d0a0d42d9 100644 --- a/simavr/sim/sim_core.c +++ b/simavr/sim/sim_core.c @@ -185,6 +185,28 @@ static inline void _call_register_irqs(avr_t * avr, uint16_t addr) } } +void _call_sram_irqs(avr_t *avr, uint16_t addr) { + for(int tracepoint=0; tracepoint < avr->sram_tracepoint_count; tracepoint++) { + + if (avr->sram_tracepoint[tracepoint].width == 16) { + // 16 bits trace (LSB/addr or MSB/addr+1 may be accessed) + if (avr->sram_tracepoint[tracepoint].addr == addr) { + uint16_t v = (avr->data[addr+1] << 8) | avr->data[addr]; // LSB + avr_raise_irq(avr->sram_tracepoint[tracepoint].irq, v); + } else if (avr->sram_tracepoint[tracepoint].addr == addr - 1) { + uint16_t v = (avr->data[addr] << 8) | avr->data[addr-1]; // MSB + avr_raise_irq(avr->sram_tracepoint[tracepoint].irq, v); + } + } else { + // 8 bits trace + if (avr->sram_tracepoint[tracepoint].addr == addr) { + uint8_t v = avr->data[addr]; + avr_raise_irq(avr->sram_tracepoint[tracepoint].irq, v); + } + } + } +} + void avr_core_watch_write(avr_t *avr, uint16_t addr, uint8_t v) { if (addr > avr->ramend) { @@ -220,6 +242,7 @@ void avr_core_watch_write(avr_t *avr, uint16_t addr, uint8_t v) avr->data[addr] = v; _call_register_irqs(avr, addr); + _call_sram_irqs(avr, addr); } uint8_t avr_core_watch_read(avr_t *avr, uint16_t addr) @@ -269,6 +292,8 @@ static inline void _avr_set_r(avr_t * avr, uint16_t r, uint8_t v) avr_raise_irq(avr->io[io].irq + i, (v >> i) & 1); } } + // _call_register_irqs(avr, r); // else section above could then be removed ? + _call_sram_irqs(avr, r); // Only for io region } else avr->data[r] = v; } diff --git a/simavr/sim/sim_elf.c b/simavr/sim/sim_elf.c index 22e5ce424..3b16db0bf 100644 --- a/simavr/sim/sim_elf.c +++ b/simavr/sim/sim_elf.c @@ -205,7 +205,7 @@ avr_load_firmware( avr->vcd, firmware->traceperiod >= 1000 ? firmware->traceperiod : 1000); - AVR_LOG(avr, LOG_TRACE, "Creating VCD trace file '%s'\n", + AVR_LOG(avr, LOG_TRACE, "ELF: Creating VCD trace file '%s'\n", avr->vcd->filename); for (int ti = 0; ti < firmware->tracecount; ti++) { @@ -228,8 +228,32 @@ avr_load_firmware( &bit[firmware->trace[ti].addr], firmware->trace[ti].mask == 0xff ? 8 : 1, firmware->trace[ti].name); + } else if ( (firmware->trace[ti].kind == AVR_MMCU_TAG_VCD_SRAM_8) || + (firmware->trace[ti].kind == AVR_MMCU_TAG_VCD_SRAM_16) ) { + if ((firmware->trace[ti].addr <= 31) || (firmware->trace[ti].addr > avr->ramend)) { + AVR_LOG(avr, LOG_ERROR, "ELF: *** Invalid SRAM trace address (0x20 < 0x%04x < 0x%04x )\n", firmware->trace[ti].addr, avr->ramend); + } else if (avr->sram_tracepoint_count >= ARRAY_SIZE(avr->sram_tracepoint)) { + AVR_LOG(avr, LOG_ERROR, "ELF: *** Too many SRAM traces (limit = %d)\n", ARRAY_SIZE(avr->sram_tracepoint)); + } else { + char name[20]; + sprintf(name, "sram_tracepoint_%d", avr->sram_tracepoint_count); + const char *names[1] = {name}; + avr_irq_t *irq = avr_alloc_irq(&avr->irq_pool, 0, 1, names); + if (irq) { + AVR_LOG(avr, LOG_OUTPUT, "ELF: SRAM tracepoint added at '0x%04x' (%s, %d bits)\n", firmware->trace[ti].addr, firmware->trace[ti].name, firmware->trace[ti].kind == AVR_MMCU_TAG_VCD_SRAM_8 ? 8 : 16); + avr->sram_tracepoint[avr->sram_tracepoint_count].irq = irq; + avr->sram_tracepoint[avr->sram_tracepoint_count].width = firmware->trace[ti].kind == AVR_MMCU_TAG_VCD_SRAM_8 ? 8 : 16; + avr->sram_tracepoint[avr->sram_tracepoint_count].addr = firmware->trace[ti].addr; + avr_vcd_add_signal(avr->vcd, + irq, + avr->sram_tracepoint[avr->sram_tracepoint_count].width, + firmware->trace[ti].name[0] ? firmware->trace[ti].name : names[0] + ); + avr->sram_tracepoint_count++; + } + } } else if (firmware->trace[ti].mask == 0xff || - firmware->trace[ti].mask == 0) { + firmware->trace[ti].mask == 0) { // easy one avr_irq_t * all = avr_iomem_getirq(avr, firmware->trace[ti].addr, @@ -330,7 +354,9 @@ elf_parse_mmcu_section( } break; case AVR_MMCU_TAG_VCD_PORTPIN: case AVR_MMCU_TAG_VCD_IRQ: - case AVR_MMCU_TAG_VCD_TRACE: { + case AVR_MMCU_TAG_VCD_TRACE: + case AVR_MMCU_TAG_VCD_SRAM_8: + case AVR_MMCU_TAG_VCD_SRAM_16: { uint8_t mask = src[0]; uint16_t addr = src[1] | (src[2] << 8); char * name = (char*)src + 3; @@ -385,7 +411,7 @@ elf_copy_segment(int fd, Elf32_Phdr *php, uint8_t **dest) rv, php->p_filesz, php->p_vaddr, php->p_offset); return -1; } - AVR_LOG(NULL, LOG_DEBUG, "Loaded %d bytes at %x\n", + AVR_LOG(NULL, LOG_DEBUG, "ELF: Loaded %d bytes at %x\n", php->p_filesz, php->p_vaddr); return 0; }