From: Manfred Steiner Date: Sun, 1 Oct 2023 06:43:13 +0000 (+0200) Subject: simuc V0.0.6 (merge with sx-2023-09-30/5a85848) X-Git-Url: https://git.htl-mechatronik.at/public/?a=commitdiff_plain;h=58130f067d478535e6146e79d84d36b13b8b8f73;p=sx%2Fsimavr.git simuc V0.0.6 (merge with sx-2023-09-30/5a85848) --- diff --git a/README.md b/README.md index 265da2f..bef3e16 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # simavr -This repository is mirrored from [https://github.com/buserror/simavr.git](https://github.com/buserror/simavr.git), commit 7003af0 (Mon Jul 18 10:29:17 2022) +This repository is forked from [https://github.com/buserror/simavr.git](https://github.com/buserror/simavr.git), commit 7003af0 (Mon Jul 18 10:29:17 2022) * **simuc**: see [examples/](examples/simuc/README.md) * Original `README.md`: see [README-simavr.md](README-simavr.md) diff --git a/examples/simuc/Makefile b/examples/simuc/Makefile index c8d1971..f7cbcbf 100644 --- a/examples/simuc/Makefile +++ b/examples/simuc/Makefile @@ -51,12 +51,12 @@ ifeq ($(ARCH), arm-linux-gnueabihf) DEBARCH="armhf" endif -DEBVERSION := 0.0.5~1 +DEBBASE := dpkg DEBNAME := dpkg/htl-simuc_version_arch DEBSRC := dpkg/htl-simuc_version_arch DEBARCH := $(shell dpkg --print-architecture) -DEB := $(DEBNAME:%version=%$(DEBVERSION),%arch=%$(DEBARCH).deb) +DEB := $(DEBBASE:%version=%$(DEBVERSION),%arch=%$(DEBARCH).deb) LIBC_NAME := libc6 LIBC_VERSION := $(shell dpkg --list | grep ${LIBC_NAME}:${DEBARCH} | tr -s ' ' | cut -d" " -f 3 | cut -d"-" -f 1) LIBCXX_NAME := libstdc++6 @@ -67,7 +67,6 @@ LIBELF_VERSION := $(shell dpkg --list | grep ${LIBELF_NAME}:${DEBARCH} | tr -s ' deb: dpkg $(DEBSRC)/DEBIAN/control $(DEBSRC)/usr/share/doc/htl-simuc/readme @dpkg-deb -Z xz --root-owner-group --build $(DEBSRC) ${DEB} - @mv $(DEBSRC)/*.deb dpkg/ @chmod 644 dpkg/*.deb .PHONY: $(DEBSRC)/DEBIAN/control $(DEBSRC)/usr/share/doc/htl-simuc/readme diff --git a/examples/simuc/README.md b/examples/simuc/README.md index 1453dd1..95dcfac 100644 --- a/examples/simuc/README.md +++ b/examples/simuc/README.md @@ -2,30 +2,65 @@ **simuc** is used to simulate a megaAvr microcontroller. -If the cpu is stopped by command or `avr-gdb`, some information is printed on standard output: +The git repository for this program can be found on the git repository [https://git.htl-mechatronik.at/public/?p=sx/simavr.git;a=home](https://git.htl-mechatronik.at/public/?p=sx/simavr.git;a=home). +The software `simuc` itself is located in the subfolder [examples/simuc](https://git.htl-mechatronik.at/public/?p=sx/simavr.git;a=tree;f=examples/simuc;hb=HEAD) + +---------------------------------------------------- + +## Installation + +If the Debian/Ubuntu htl package is included the software is already installed. + +In any other case "ready to use" debian packages are located on [http://www.htl-mechatronik.at/ubuntu-new/pool/partner/](http://www.htl-mechatronik.at/ubuntu-new/pool/partner/) and can be installed after download with `apt install ...`. + +The package is available for 4 supported architectures: + +* **[amd64](http://www.htl-mechatronik.at/ubuntu-new/pool/partner/htl-simuc_0.0.6~1_amd64.deb)** Linux (Debian, Ubuntu, ...) PC 64 bit +* **[i386](http://www.htl-mechatronik.at/ubuntu-new/pool/partner/htl-simuc_0.0.6~1_arm64.deb)** Linux (Debian, Ubuntu, ...) PC 32 bit +* **[arm64](http://www.htl-mechatronik.at/ubuntu-new/pool/partner/htl-simuc_0.0.6~1_arm64.deb)** ARM 64 Bit (Respberry Pi 3,4 ... with RaspbianOs 64 Bit) +* **[armhf](http://www.htl-mechatronik.at/ubuntu-new/pool/partner/htl-simuc_0.0.6~1_armhf.deb)** ARM 32 Bit (Raspberry Pi 2,3,4 ... with RaspbianOs 32 Bit) + +---------------------------------------------------- + +## Overview + +If the microcontroller CPU is stopped by command or `avr-gdb`, some information is printed on standard output: * Number of cycles and elapsed time * Status Flags * General Purpose registers r0..r31 * address registers X, Y and Z * Stack pointer SP and stack content - -Commands available via standard input (keyboard): -* *Enter* print current cycles, elapsed time and LED status -* `interrupt`: stop cpu -* `continue`: continue cpu run -* `stack`: print complete stack content on standard output +* LED status for some type boards (Arduino, Sure Electronics, ...) + +**Commands** available via standard input (keyboard): +* ***Enter*** print current cycles, elapsed time and LED status +* `break` + *Enter*: + ... stop microcontroller CPU (breakpoint) +* `continue` + *Enter*: + ... continue microcontroller CPU +* `reset` + *Enter*: + ... simulate external reset (registers will be cleared, SRAM contents remain unchanged) +* `power` + *Enter*: + ... simulate power on reset (registers and SRAM will be cleared) +* `stack` + *Enter*: + ... print complete stack content on standard output + +It is sufficient to enter only as many characters of the command until the command is unique. +`b` for *break*, `c` for *continue*, `r` for *reset*, `p` for *power* and `s` for *stack* Microcontrollers UART interface(s) is/are connected to local devices and can be used with terminal programs (like `picocom`). -After start of `simuc` the program waits for an keyboard action to start simulation. So you are able to connect with avr-gdb before the simulation is executing some machine code. +After start of `simuc` the program waits for a command (via keyboard) to start simulation. So you are able to connect with *avr-gdb* before the simulation is executing some machine code. 1) start `simuc` with proper options and arguments 2) start new shell and execute `avr-gdb` 3) inside (gdb) connect to simuc with the gdb shell command `target remote :1234` 4) load symbols with gdb command `file ...` 5) optionally set source directory with `directory ...` -6) press enter in the shell of simuc -7) now debug avr program step by step with gdb commands `stepi`, `step`, `nexti`, `next` or continue execution with `continue` +6) press `b` and enter in the shell of simuc (break on first machine command) +7) now debug avr program step by step with gdb commands `stepi` (`si`), `step` (`s`), `nexti` (`ni`), `next` (`n`) or continue execution with `continue` (`c`) + +Don't forget to compile your program with the option **`-g`** (include gdb debugging information in elf-file)! ------------------------------------------------------------- @@ -35,7 +70,7 @@ After start of `simuc` the program waits for an keyboard action to start simulat ```sh $ sudo apt install gcc make gcc-avr avr-libc $ sudo apt install libelf-dev -$ sudo apt install freeglut3 freeglut3-dev +$ sudo apt install freeglut3-dev $ sudo apt install libncurses5 libncurses5-dev ``` @@ -45,6 +80,9 @@ $ sudo apt install libncurses5 libncurses5-dev user@host:~ $ git clone https://git.htl-mechatronik.at/public/sx/simavr.git ``` +The main branch is named `master-sx` because the branch `master` remains unchanged with the original simavr repository on [https://github.com/buserror/simavr](https://github.com/buserror/simavr) (commit [7003af0](https://github.com/buserror/simavr/commit/7003af0)). + + ### Make complete simavr ```sh @@ -66,7 +104,9 @@ Executable `simuc` available in folder `dist` ```sh user@host:~ $ cd ~/simavr/examples/simuc -user@host:~/simavr/examples/simuc $ make deb +user@host:~/simavr/examples/simuc $ export DEBVERSION="0.0.6~1"; make deb ``` Debian packet available in folder `dpkg` + +Find "ready to use" debian packages on [http://www.htl-mechatronik.at/ubuntu-new/pool/partner/](http://www.htl-mechatronik.at/ubuntu-new/pool/partner/). diff --git a/examples/simuc/src/main.cpp b/examples/simuc/src/main.cpp index 575165b..345a872 100644 --- a/examples/simuc/src/main.cpp +++ b/examples/simuc/src/main.cpp @@ -7,8 +7,12 @@ #include "sim/sim.h" #include "simavr/simavr.h" +void printVersion () { + printf("simuc V0.0.6 (%s,%s)\n", __DATE__, __TIME__); +} + void printHelp () { - printf("simuc V0.0.5 (%s,%s)\n", __DATE__, __TIME__); + printVersion(); printf("usage: simuc [options] elf-file [elf-file ...]\n\n"); printf(" available options (you can use file .simucinit instead):\n"); printf(" --port ... listining port for gdb (default 1234)\n"); @@ -190,22 +194,35 @@ int main (int argc, char **argv) { } if (params.filenames == NULL || params.filenames[0] == NULL) { + printVersion(); printf("ERROR: missing target elf file, use --help to show usage\n\n"); return 1; } - printf("--------------------------------------------------------------------\n"); + printf("----------------------------------------------------------------------\n"); init(¶ms); if (errno == 1) { return 1; } - printf("--------------------------------------------------------------------\n"); - printf("available commands: i (interrupt), c (continue), s (stack), r (reset), q (quit)\n"); - printf("--------------------------------------------------------------------\n"); + printf("----------------------------------------------------------------------\n"); + printf("available commands:\n"); + printf(" b (break), c (continue), s (stack), r (reset), p (power), q (quit)\n"); + printf("----------------------------------------------------------------------\n"); printf("init done - press key to start\n"); - getchar(); - printf("--------------------------------------------------------------------\n"); - start(); + char c = getchar(); + if (c != '\n') { + getchar(); // remove line feed from stdin + } + printf("----------------------------------------------------------------------\n"); + + switch (c) { + case 'b': start(CommandBreak, NULL); break; + case 's': start(CommandStack, NULL); break; + case 'r': start(CommandReset, NULL); break; + case 'p': start(CommandPower, NULL); break; + case 'q': return 0; + default: start(ReadyForNewCommand, NULL); break; + } // int cnt = 0; char *line = NULL; @@ -221,9 +238,9 @@ int main (int argc, char **argv) { // shutdown(); // break; // } - + if (getline(&line, &size, stdin) > 0) { - const char *commands[] = { "quit", "interrupt", "continue", "stack", "reset" }; + const char *commands[] = { "quit", "break", "continue", "stack", "reset", "power" }; try { int foundIndex = -1; int foundCnt = 0; @@ -246,7 +263,7 @@ int main (int argc, char **argv) { } } } - // printf("foundCnt=%d foundIndex=%d command=%s\n", foundCnt, foundIndex, foundIndex >= 0 ? commands[foundIndex] : ""); + printf("foundCnt=%d foundIndex=%d command=%s\n", foundCnt, foundIndex, foundIndex >= 0 ? commands[foundIndex] : ""); if (foundCnt == 1 || length == 0) { EnumSimAvrCommand cmd = (EnumSimAvrCommand)(foundCnt > 0 ? foundIndex + 2 : 1); setCommand(cmd, NULL); @@ -295,4 +312,4 @@ int main (int argc, char **argv) { usleep(10000); return 0; -} \ No newline at end of file +} diff --git a/examples/simuc/src/sim/sim.cpp b/examples/simuc/src/sim/sim.cpp index 4ba1da0..c1ec1e3 100644 --- a/examples/simuc/src/sim/sim.cpp +++ b/examples/simuc/src/sim/sim.cpp @@ -154,7 +154,7 @@ void init (struct StartParameters *param) { } simavr.load(param); - printf("--------------------------------------------------------------------\n"); + printf("----------------------------------------------------------------------\n"); simavr.setUartDumpEnabled(false); // simavr.registerIoWrite(PORTB, handleWritePortB); simavr.setUartPtyEnabled(0, true); @@ -199,9 +199,9 @@ void shutdown () { } } -void start () { +void start (EnumSimAvrCommand cmd, void *param) { try { - simavr.start(); + simavr.start(cmd, param); } catch (std::exception& e) { lastErrorMessage = "start() fails, caused by " + std::string(e.what()); diff --git a/examples/simuc/src/sim/sim.h b/examples/simuc/src/sim/sim.h index d980f26..eb61992 100644 --- a/examples/simuc/src/sim/sim.h +++ b/examples/simuc/src/sim/sim.h @@ -22,7 +22,7 @@ typedef enum { extern void init (struct StartParameters *param); extern void shutdown (); extern const char * lastError (); -extern void start (); +extern void start (EnumSimAvrCommand cmd, void *param); extern void stop (); extern void setCommand (EnumSimAvrCommand cmd, void *param); extern void addEvent (EnumSimEvent event); diff --git a/examples/simuc/src/simavr/simavr.cpp b/examples/simuc/src/simavr/simavr.cpp index f054e7c..b12befe 100644 --- a/examples/simuc/src/simavr/simavr.cpp +++ b/examples/simuc/src/simavr/simavr.cpp @@ -70,7 +70,7 @@ void SimAvr::load (struct StartParameters *params) { 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())); } - printf("--------------------------------------------------------------------\n"); + printf("----------------------------------------------------------------------\n"); } if (params->mmcu != NULL) { strncpy(firmware->mmcu, params->mmcu, sizeof(firmware->mmcu)); @@ -131,7 +131,7 @@ void SimAvr::load (struct StartParameters *params) { printf("EEPROM: "); if (firmware->eesize == 0) { - printf("not defined (no section .eeprom found)"); + printf("not defined (no section .eeprom found)\n"); } else { printf("%d bytes defined (", firmware->eesize); for (uint32_t i = 0; i < firmware->eesize; i++) { @@ -155,7 +155,7 @@ void SimAvr::load (struct StartParameters *params) { if (avr_init(avr) != 0) { throw std::logic_error(error(AT, "avr_init() fails")); } - + // now we can chang log level to desired value avr->log = params->log; printf("simavr log level: "); @@ -325,7 +325,7 @@ uint32_t SimAvr::getTargetFrequency () { } } -void SimAvr::start () { +void SimAvr::start (EnumSimAvrCommand cmd, void *param) { if (pthread_mutex_lock(&lock)) { throw std::logic_error(error(AT, "start() fails caused by mutex error")); } @@ -339,6 +339,7 @@ void SimAvr::start () { if (avr == NULL) { throw std::logic_error("avr not ready (check if load done)"); } + command = cmd; syncTime[0] = !syncTime[1]; avrRunThread = new std::thread(&SimAvr::avrRun, this); pthread_mutex_unlock(&lock); @@ -494,7 +495,7 @@ bool SimAvr::sprintfLedStatus (char *s, size_t size, bool onlyOnChange) { } if (!onlyOnChange || nextLedL != ledL) { ledL = nextLedL; - snprintf(s, size, "LED L = %c", ledL ? 'X' : '.'); + snprintf(s, size, "LED L = %c", ledL == 1 ? 'X' : '.'); rv = true; } break; @@ -519,7 +520,7 @@ bool SimAvr::sprintfLedStatus (char *s, size_t size, bool onlyOnChange) { if (!onlyOnChange || change) { int n = snprintf(s, size, "LED PA[3210] ="); for (int i = 3; i >= 0; i--) { - n += snprintf(s + n, size - n, " %c", led[i] ? 'X' : '.'); + n += snprintf(s + n, size - n, " %c", led[i] == 1 ? 'X' : '.'); } rv = true; } @@ -535,7 +536,7 @@ bool SimAvr::sprintfLedStatus (char *s, size_t size, bool onlyOnChange) { } if (!onlyOnChange || nextLed != led) { led = nextLed; - snprintf(s, size, "LED1 (PB0) = %c", led ? 'X' : '.'); + snprintf(s, size, "LED1 (PB0) = %c", led == 1 ? 'X' : '.'); rv = true; } break; @@ -546,6 +547,23 @@ bool SimAvr::sprintfLedStatus (char *s, size_t size, bool onlyOnChange) { return rv; } +void SimAvr::reset (ResetType type) { + avr_reset(avr); + + switch (type) { + case powerOn: avr_regbit_set(avr, avr->reset_flags.porf); break; + case external: avr_regbit_set(avr, avr->reset_flags.extrf); break; + case brownout: avr_regbit_set(avr, avr->reset_flags.borf); break; + case watchdog: avr_regbit_set(avr, avr->reset_flags.wdrf); break; + } + + // bugfix, also clear r0..r31, and set SP to 0 + for (int i = 0; i < 0x20; i++) { + avr->data[i] = 0; + } + _avr_sp_set(avr, 0); +} + void SimAvr::avrRun () { long cnt = 0; @@ -730,7 +748,7 @@ void SimAvr::avrRun () { printf(" %s\n", s); break; } - case CommandInterrupt: { + case CommandBreak: { if (avr->state == cpu_Running) { avr->state = cpu_Stopped; } @@ -767,10 +785,19 @@ void SimAvr::avrRun () { } case CommandReset: { - avr_reset(avr); - printf("RESET done -> PC=0x%04x, use command 'continue' to start!\n", avr->pc); - avr->state = cpu_Stopped; - break; + reset(external); + printf("\n\n----------------------------------------------------------------\n"); + printf("RESET done (registers set to init value, SRAM remains unchanged)\n"); + command = CommandBreak; + continue; + } + + case CommandPower: { + reset(powerOn); + printf("\n\n-----------------------------------------------\n"); + printf("Power-On done (SRAM cleared and power-on reset)\n"); + command = CommandBreak; + continue; } default: break; diff --git a/examples/simuc/src/simavr/simavr.h b/examples/simuc/src/simavr/simavr.h index 0184f5b..141084a 100644 --- a/examples/simuc/src/simavr/simavr.h +++ b/examples/simuc/src/simavr/simavr.h @@ -58,10 +58,11 @@ typedef enum { ReadyForNewCommand = 0, CommandStatus, CommandQuit, - CommandInterrupt, + CommandBreak, CommandContinue, CommandStack, - CommandReset + CommandReset, + CommandPower } EnumSimAvrCommand; struct SimAvrStatus { @@ -80,6 +81,7 @@ struct SimAvrEvent { class SimAvr; typedef void (*avrsim_io_write_callback_t)(avr_t *avr, avr_io_addr_t addr, uint8_t value, SimAvr *simavr); +typedef enum { powerOn = 1, external = 2, brownout = 4, watchdog = 8 } ResetType; class SimAvr { @@ -91,10 +93,10 @@ public: struct SimAvrEvent waitForEvent (); const char *eventText (EnumSimAvrEvent event); -public: +public: void load (struct StartParameters *params); void shutdown (); - void start (); + void start (EnumSimAvrCommand cmd, void *param); void stop (); void addEvent (int event); void setUartDumpEnabled (bool enabled); @@ -127,6 +129,7 @@ private: uint64_t timeMicrosOnSyncStart = 0; Semaphore eventCount; uart_pty_t *uartPty[2] = { NULL, NULL }; + void reset (ResetType type); void printCyclesAndElapsedTime (); bool sprintfLedStatus (char *s, size_t size, bool onlyOnChange); }; @@ -134,4 +137,4 @@ private: -#endif // SIMAVR_H \ No newline at end of file +#endif // SIMAVR_H