From 319779f020f9dc15902dadad8a9ebb059118dfa4 Mon Sep 17 00:00:00 2001 From: Manfred Steiner Date: Sun, 27 Nov 2022 18:52:17 +0100 Subject: [PATCH] simavr is now able to load multiple flash sections --- examples/simuc/.gitignore | 3 ++ examples/simuc/Makefile | 4 +- examples/simuc/src/simavr/simavr.cpp | 4 ++ simavr/.gitignore | 3 +- simavr/sim/sim_elf.c | 61 +++++++++++++++++++++++++--- 5 files changed, 66 insertions(+), 9 deletions(-) diff --git a/examples/simuc/.gitignore b/examples/simuc/.gitignore index d1ad022..5489810 100644 --- a/examples/simuc/.gitignore +++ b/examples/simuc/.gitignore @@ -1,4 +1,7 @@ dist/** build/** dpkg/**/*.deb +dpkg/**/usr/share/htl-simuc/simuc +dpkg/**/usr/share/htl-simuc/simavr +dpkg/**/DEBIAN/control **/*.vcd diff --git a/examples/simuc/Makefile b/examples/simuc/Makefile index 456d1d5..e06b0fe 100644 --- a/examples/simuc/Makefile +++ b/examples/simuc/Makefile @@ -15,9 +15,9 @@ CFLAGS = -Os -Wall X_CFLAGS = -Os -g -Wall -dist/simuc: build/main.o build/sim.o build/simavr.o build/error.o build/uart_pty.o +dist/simuc: build/main.o build/sim.o build/simavr.o build/error.o build/uart_pty.o ../../simavr/obj-$(shell gcc -dumpmachine)/libsimavr.a #g++ -o $@ -g -Wall -gdwarf-2 $^ -Wl,-rpath,$(CURDIR) -L$(CURDIR) -lsimavr -lpthread -lutil - g++ -o $@ -g -Wall -gdwarf-2 $^ ../../simavr/obj-$(shell gcc -dumpmachine)/libsimavr.a -lelf -lpthread -lutil + g++ -o $@ -g -Wall -gdwarf-2 $^ -lelf -lpthread -lutil #dist/libsim.so: build/sim.o build/simavr.o build/error.o build/uart_pty.o diff --git a/examples/simuc/src/simavr/simavr.cpp b/examples/simuc/src/simavr/simavr.cpp index ba63390..1945ad5 100644 --- a/examples/simuc/src/simavr/simavr.cpp +++ b/examples/simuc/src/simavr/simavr.cpp @@ -60,6 +60,10 @@ void SimAvr::load (struct StartParameters *params) { startParameters = params; firmware = (elf_firmware_t *) malloc(sizeof(elf_firmware_t)); std::string filename = std::string(params->filename); + if (params->mmcu != NULL) { + // elf_read_firmware needs mmcu to malloc proper flash size + strncpy(firmware->mmcu, params->mmcu, sizeof(firmware->mmcu)); + } if (firmware == NULL || elf_read_firmware(filename.c_str(), firmware) != 0) { throw std::logic_error(error(AT, "elf_read_firmware() from %s fails", filename.c_str())); } diff --git a/simavr/.gitignore b/simavr/.gitignore index 5587c97..3a85b15 100644 --- a/simavr/.gitignore +++ b/simavr/.gitignore @@ -1,3 +1,4 @@ sim_core_decl.h sim_core_config.h -.vscode/* \ No newline at end of file +.gdb_history +.vscode/* diff --git a/simavr/sim/sim_elf.c b/simavr/sim/sim_elf.c index df69b81..371b9db 100644 --- a/simavr/sim/sim_elf.c +++ b/simavr/sim/sim_elf.c @@ -291,7 +291,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, "Loaded %d bytes at 0x%04x\n", php->p_filesz, php->p_vaddr); return 0; } @@ -373,18 +373,42 @@ elf_read_firmware( continue; if (php->p_vaddr < 0x800000) { /* Explicit flash section. Load it. */ + if (firmware->flash == NULL) { + firmware->flashbase = 0; + firmware->flashsize = php->p_vaddr + php->p_filesz; + firmware->flash = malloc(firmware->flashsize); + memset(firmware->flash, 0xff, firmware->flashsize); + uint8_t *where = firmware->flash + php->p_vaddr; + elf_copy_segment(fd, php, &where); + + } else { + long gapSize = php->p_vaddr - firmware->flashsize; + if (gapSize < 0) { + AVR_LOG(NULL, LOG_ERROR, + "Overlapping flash sections!\n"); + return -1; + } else if (gapSize > 0) { + firmware->flash = realloc(firmware->flash,php->p_vaddr ); + uint8_t *where = firmware->flash + firmware->flashsize; + memset(where, 0xff, gapSize); + firmware->flashsize = php->p_vaddr; + } + firmware->flash = realloc(firmware->flash, + firmware->flashsize + php->p_filesz); + if (!firmware->flash) + return -1; + uint8_t *where = firmware->flash + firmware->flashsize; + elf_copy_segment(fd, php, &where); + firmware->flashsize += php->p_filesz; + } - if (elf_handle_segment(fd, php, &firmware->flash, "Flash")) - continue; - firmware->flashsize = php->p_filesz; - firmware->flashbase = php->p_vaddr; } else if (php->p_vaddr < 0x810000) { /* Data space. If there are initialised variables, treat * them as extra initialised flash. The C startup function * understands that and will copy them to RAM. */ - if (firmware->flash) { + if (firmware->flash != NULL) { uint8_t *where; firmware->flash = realloc(firmware->flash, @@ -393,6 +417,7 @@ elf_read_firmware( return -1; where = firmware->flash + firmware->flashsize; elf_copy_segment(fd, php, &where); + AVR_LOG(NULL, LOG_DEBUG, ".data section %d bytes copied to flash at 0x%04x\n", php->p_filesz, firmware->flashsize); firmware->flashsize += php->p_filesz; } else { /* If this ever happens, add a second pass. */ @@ -421,6 +446,27 @@ elf_read_firmware( } } + avr_t *avr = avr_make_mcu_by_name(firmware->mmcu); + if (avr != NULL) { + if (firmware->flash == NULL) { + AVR_LOG(NULL, LOG_ERROR, + "no flash!\n", + php->p_filesz, php->p_vaddr); + return -1; + } else { + long gapSize = avr->flashend + 1 - firmware->flashsize; + if (gapSize < 0) { + AVR_LOG(NULL, LOG_ERROR, + "flash size 0x%04x too large for selected mmcu device %s!\n", firmware->flashsize, firmware->mmcu); + return -1; + } else if (gapSize > 0) { + firmware->flash = realloc(firmware->flash, firmware->flashsize + gapSize); + uint8_t *where = firmware->flash + firmware->flashsize; + memset(where, 0xff, gapSize); + firmware->flashsize += gapSize; + } + } + } /* Scan the section table for .mmcu magic and symbols. */ while ((scn = elf_nextscn(elf, scn)) != NULL) { @@ -493,6 +539,9 @@ elf_read_firmware( } #endif // ELF_SYMBOLS } + if (firmware->flash != NULL) { + AVR_LOG(NULL, LOG_DEBUG, "end of flash initialization (size=0x%04x)\n", firmware->flashsize); + } elf_end(elf); close(fd); return 0; -- 2.39.5