Commit 58130f067d478535e6146e79d84d36b13b8b8f73
receivedSun, 1. Oct 2023, 08:43:17 (by user sx)
Sun, 1 Oct 2023 06:43:17 +0000 (08:43 +0200)
authorManfred Steiner <sx@htl-kaindorf.at>
Sun, 1 Oct 2023 06:43:13 +0000 (08:43 +0200)
committerManfred Steiner <sx@htl-kaindorf.at>
Sun, 1 Oct 2023 06:43:13 +0000 (08:43 +0200)
8 files changed:
README.md
examples/simuc/Makefile
examples/simuc/README.md
examples/simuc/src/main.cpp
examples/simuc/src/sim/sim.cpp
examples/simuc/src/sim/sim.h
examples/simuc/src/simavr/simavr.cpp
examples/simuc/src/simavr/simavr.h

index 265da2f89b2c4087bce8a3720ed70ed7af850547..bef3e1641217c6e6ee5c636bb6fbfb3e71e9a0ae 100644 (file)
--- 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)
index c8d1971407f7466d1f1a5edd775a741e97176115..f7cbcbf119e4ec58ff7ea2ed31ce8e72e066052a 100644 (file)
@@ -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
index 1453dd1ceb40591065c6e845ee103eb42dc03522..95dcfac551dbe72e6687eb37b4410a8140e4ecca 100644 (file)
@@ -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/).
index 575165b6223acce97d498b904bf3b6d45895b092..345a87214d7ec595fa2bd51b002681b29e679313 100644 (file)
@@ -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(&params);
     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
+}
index 4ba1da09719a0a673e0e283ed59fe521d125e80d..c1ec1e3d17bd814acc9ab2750eaf8274bf81060d 100644 (file)
@@ -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());
index d980f263030046c59039160e28d73b1bd595f2de..eb6199241a560aa283e2c142d16189f9b1169426 100644 (file)
@@ -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);
index f054e7c70353bfcfdb1310eed8836019e26d7198..b12befe4c97e069260ce2372e55523e28f26a506 100644 (file)
@@ -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;
index 0184f5b6a8d0bc9e2f5c34f49dbc34bb6a99527e..141084a7c02a09d760a447d5a1f6f2dff34167eb 100644 (file)
@@ -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