mikrocontroller.net

Forum: Projekte & Code AVR Simulator mit grafischer Benutzeroberfläche für Linux


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: R. M. (Gast)
Datum:
Angehängte Dateien:

Bewertung
6 lesenswert
nicht lesenswert
Hallo an die große Runde!

Das Projekt, welches ich vorstellen möchte, ist aus einem Spieltrieb 
heraus entstanden, der dem ähnelt, den ich seinerzeit bei den ersten 
Schritten mit dem AVR-Studio entwickelt habe. Leider funktioniert dies 
aber unter WINE nicht so zuverlässig, wie ich es mir wünschen würde. Hin 
und wieder brauche ich aber doch eine kleine Hilfestellung, um einen 
Knoten im Kopf zu lösen..
Da ich vor vielen Jahren mal einen MCS-51-Simulator in Turbo-Pascal 
geschrieben hatte, wollte ich mal wissen, ob da noch was geht.
Dieses kleine Programm simuliert auch (erstmal) nur die CPU, vielleicht 
kommt später noch etwas Peripherie dazu.
Nichts professionelles, nur für den kleinen Spieltrieb zwischendurch.
mfG

Autor: Rene S. (Firma: BfEHS) (rschube)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für deinen Beitrag!

Ich hab das mal kurz angetestet und es sieht auf den ersten Blick sehr 
gut aus.

Noch ein bisschen Besserwisserei ;-) Es ist GNU-Linux.

Autor: Mw E. (Firma: fritzler-avr.de) (fritzler)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Das sieht gut aus.
Ist denn eine GDB Anbindung geplant?
Dann kann man noch besser debuggen ;)
Nen GDB Server coden is auch garnicht mal so schwer.

Autor: R. M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mw E. schrieb:
> Ist denn eine GDB Anbindung geplant?

Nein, der Simulator ist intern, und ob man die Sichten auf die Periperie 
über die GDB-Schnittstelle abbilden könnte, bin ich mir auch nicht 
sicher.

Das müsste ja dann gegebenenfalls der GDB-Server für die Hardware 
leisten.
Für die reine CPU gibt es den Simulator mit GDB-Schnittstelle ja auch 
schon. Und der simulavr zeigt das Wichtigste seines Innenlebens, 
(zusätzlich) über seine Konsole an.
Hab mal DDD als grafisches Frontend für den GDB auf simulavr getestet,
https://www.mikrocontroller.net/articles/AVR-Simulation#SimulAVR
da würde ich, vom Abstraktionsniveau, auf absehbare Zeit nicht hinkommen 
- wäre auch unsinnig, der ist ja ausgereift. Dort hatte ich lediglich 
die Stoppuhr, und die Unterstützung für die niedrigen Assembler 
vermisst. Vielleicht hab ich mich auch nur zu dumm angestellt.
In Hardwaredebugger habe ich bisher keine Zeit/ kein Geld investiert, da 
ich mir einbilde, das Funktionsprinzip des HW-Debuggings mit AVR ist, 
das auf den Haltepunkt eine BREAK-Anweisung geschrieben wird, die dann 
in den Debug-Modus führt. Sprich: es wird ständig auf den Flash 
rumgeschrieben, das wollte ich eigentlich vermeiden. Vielleicht fehlt 
mir dazu aber auch nur die Erfahrung. Kann mich erinnern, irgendwo bei 
Atmel gelesen zu haben, das man die Steine, die man für HW-Debugging 
genutzt hat, nicht mehr "scharf" einsetzen sollte.
Aber für so einen, ausschließlich in SW realisiertern Simulator sind 
auch die Einstiegshürden niedriger. Und den Simulator im Studio4 fand 
ich, wie bereits geschrieben, richtig gut. Seit dem Umstieg auf 
GNU/Linux (Danke Rene!), hab ich aber meine Arbeitsweise in mancher 
Hinsicht umgebaut. So hat mir die Sache, wenn auch der Nutzeffekt gering 
ist, trotzdem was gebracht. Zummindest kenne ich jetzt den Befehlssatz 
etwas besser als vorher. ;-)
mfG

Autor: R. M. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Mit der tabellarischen Darstellung des RAM und Flash hat es schneller 
geklappt, als erwartet. Da sich die Aktualisierungsgeschwindigkeit 
dadurch deutlich erhöht hat, und gleich noch Möglichkeit dazu gekommen 
ist, diese Speicher manuell zu modifizieren, schiebe ich mal ein Update 
nach.
Ein Hinweis zum RAM: der geht ja eigentlich erst ab 0x60 los. Auf den 
unteren Adressen findet man die Register (0 bis 31) und den I/O-Bereich 
(0x20 bis 0x5f), den man damit auch in der Hand hat. Dies analog zu den 
Zugriffsmöglichkeiten der LD und ST-Befehle.
Der schon mit eingebaute EEPROM-Bereich hat zur Zeit noch keine 
Funktion, die kommt später.
An der Anleitung hat sich nichts geändert, dazu siehe erster Beitrag.
mfG

Autor: Mw E. (Firma: fritzler-avr.de) (fritzler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hatte bei der GDB Schnittstelle auch eher an den Spieltrieb 
appeliert.
Danach weis man ziemlich sicher wie das funktioniert.

Die Periperie Register sind Memory mapped und der GDB kann Speicher 
auslesen, das geht also.
Die GDB Schnittstelle war auch eher als Zusatz gemeint, der Simulator 
bleibt wie er ist. Kann aber zusätzlich per GDB Debugbefehle entgegen 
nehmen.
Der Witz ist ja, dass der DDD dann mit deinem Simulator laufen würde, 
wenn du einen GDB Server einbaust ;)
DDD trommelt auf dem GDB rum, dieser trommelt auf deinem Simulator rum 
-> Profit!

Eine BREAK Anweisung in den Flash zu schreiben ist dann ein 
Softwarebreakpoint und so macht der GDB das auch. Ist sogar noch 
schlimemr als du denkst, denn der GDB löscht nach jedem STEP alle 
Breakpoints und legt die vor einem neuen STEP wieder an.
... Es könnte ja die Verbindung abbrechen und das Target mit wilden 
Breakpoints rumlaufen.
Man merkt eben, dass GDB eher von Mainframes kommt zum Userprozesse 
debuggen.

Ich hab ja auch schonmal nen Simulator geschrieben, aber für MIPS1.
Mit GDB Schnittstelle.
Da hätt man auch den QEMU nutzen könne, aber die Periperie war etwas 
spezieller.

Autor: R. M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mw E. schrieb:
> Ist sogar noch
> schlimemr als du denkst, denn der GDB löscht nach jedem STEP alle
> Breakpoints und legt die vor einem neuen STEP wieder an.

Das hatte ich mir schon so gedacht, macht ja eigentlich fast jedes 
Monitorprogramm so. Solange das Programm im RAM steht, tut das ja auch 
überhaupt nicht weh - aber diese Diskussion hatten wir hier ja schon 
öfter.
Fürchte blos, wenn ich zu viele Baustellen aufmache, dann verzettele ich 
mich. Meine nächsten Ziele sind, erstmal die Ansicht der wichtigsten 
Hardware auf der GUI abzubilden, dabei werde ich versuchen, die dafür 
erforderlichen Informationen weiterhin aus den <typ>def.inc Dateien zu 
beziehen. Dann kommt die Funktion der nicht statischen (Ports) Hardware 
dran: EEPROM, FLASH-Selbstprogrammierung, Timer (einschließlich 
Interrupts). Kann allerdings den Zeitrahmen dafür noch nicht annähernd 
abschätzen.
Wer sich mal den Quellcode angeschaut hat, wird bemerkt haben, das ich 
schon eine relativ klare Trennung zwischen dem Simulator und der GUI 
gezogen habe man könnte die Teile bei Bedarf auch auseinanderziehen. 
Vorher müssen sie aber erstmal beide fehlerfrei funktionieren.

mfG

Autor: R. M. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Inzwischen habe ich die Benutzeroberfläche stark überarbeitet.
Die Peripherie hat jetzt eine, nach Funktionsgruppen geordnete 
Baumansicht bekommen. Das bedingte allerdings, das ich von den "rohen" 
Includedateien abgehen musste und neue Definitionsdateien erstellen 
musste (iodefs). In der Anleitung dazu, bei Bedarf, mehr Details.
mfG

Autor: R. M. (Gast)
Datum:
Angehängte Dateien:

Bewertung
1 lesenswert
nicht lesenswert
Mittlerweile kann das Programm auch die "elf"-Objektdateien, welche 
avr-gcc 4.9.2 erzeugt, einlesen und die Quelltext-Zeileninformationen 
aus den debug-daten verarbeiten. Das avr-gcc_sample ist das Testprojekt, 
welches mir zum Evaluieren dient. Es besteht aus einem "C"-Hauptteil und 
2 Assemblermodulen. Die Verfolgung des "C"-Quelltextes funktioniert 
schon ganz gut (Der GCC packt die Info nach dem dwarf-Standard, der ganz 
gut dokumentiert ist), in den Assemblerteilen hakt die Verfolgung des 
Quelltextes noch stellenweise, dort gibt es noch was zu tun (hier werden 
die Quelltextzeilen in einer Weise kodiert, die weder bei elf, noch bei 
dwarf, noch bei stab wiederzuerkennen ist, aber das Prinzip erscheint 
auch so verständlich, daher schon die Grundfunktion da.

Wer damit das erste Mal ein in "C" geschriebenes Programm simuliert, 
bitte nicht wundern:
Bevor die erste Zeile der "main"-Funktion zu sehen ist, kommen erstmal 
einige Initialisierungen (Stackpointer, globale Variablen werden 
genullt), also nicht ungeduldig werden! Wenn man erstmal die 
Startadresse von main gesehen hat, kann man ja einen Haltepunkt dorthin 
setzen und beim nächsten Versuch mit "run" bis dort durchlaufen lassen.

Wenn das rund läuft, dann schau ich mal, ob ich das 
gdb-Netzwerkprotokoll finde, eventuell schaffe ich es doch noch, an 
einen Hardwaredebugger anzudocken - als erstes Opfer könnte ja der 
simulavr dienen.
Alternativ könnte ich versuchen, den avr-gdb über die 
Kommandozeilenschnittstelle "fernzubedienen", den Zeitrahmen dafür kann 
ich aber noch nicht abschätzen.
mfG

Autor: R. M. (Gast)
Datum:
Angehängte Dateien:

Bewertung
1 lesenswert
nicht lesenswert
Ganz kleines Update:
Beim Einlesen der "elf"-Datei, wird jetzt auch die Symboltabelle 
(zummindest für den Codebereich) mit eingelesen, die Disassemblerausgabe 
wird damit beschriftet. Als Nebeneffekt, kann man jetzt auch in die 
Eingabefelder für PC und Breakpoint einen Funktionsnamen eingeben, damit 
entfällt z.B. auch die Suche nach der Adresse von "main". Mit Symbolen 
für den Datenbereich tu ich mich noch etwas schwer, zumal der GCC 
ohnehin versucht, so Viel wie möglich in den Registern zu halten. Hier 
sollte man sich mal die Disassemblerausgabe anschauen, wo die Daten 
abgelegt werden.
mfG

Autor: Michael B. (mb_)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Das ist ein recht interessantes Projekt.

Vor vielen Jahren habe ich auch mal einen AVR emulator angefangen, der 
grundsätzlich auch funktioniert. Die Emulation ist recht schnell, weil 
in der CPU Optimierungen wie Lazy-Flags verwendet werden. (Das ist, wenn 
die CPU-Flags werden erst berechnet, wenn sie benötigt werden und nicht 
bei jeder Instruktion).

Irgendwann habe ich dann aber das Interesse verloren.
Vielleicht ist der Code dennoch nützlich für dich.
Ich habe ihn mal hier hochgeladen:
https://bues.ch/cgit/avremu.git/

Autor: Mw E. (Firma: fritzler-avr.de) (fritzler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie ich sehe gehts vorran und nun willste doch was mit dem GDB machen ;)
Auch wenns die andere Richtung ist.

Über TCP quatscht der GDB genauso wie über die Serielle Schnittstelle.
Schnödes ASCII nach altem Protokoll.
Es gibt zwar nen Binary Protokoll, aber das hab ich auch nicht 
implementiert.
Hier gibts Infos zur PingPong Kommunikation:
http://www.embecosm.com/appnotes/ean4/embecosm-howto-rsp-server-ean4-issue-2.html
Hier kannste gucken welche Befehle es gibt und was diese bewirken:
https://sourceware.org/gdb/onlinedocs/gdb/Remote-Protocol.html#Remote-Protocol

Viele Debugger haben eine Option "jump to main", dann landet man dort 
immer ohne init durchklicken oder manuell nen FUnktionsbreakpoint zu 
setzen.
Nur so als Option für Faule.

Falls du willst kann ich dir ja mal von meinem MIPS Sim den GDB Teil 
zukommen lassen.

Autor: R. M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael B. schrieb:
> Vielleicht ist der Code dennoch nützlich für dich.
> Ich habe ihn mal hier hochgeladen:
> https://bues.ch/cgit/avremu.git/

Hallo Michael,
Danke schon mal, für den Einblick, sieht etwas professioneller aus, als 
mein Stückwerk, ist aber anscheinend auf ähnlichem Stand: CPU wird 
emuliert, Periperie noch nicht, hab aber nur mal kurz überflogen, werd 
mir aber noch mal mehr Zeit nehmen.

Mw E. schrieb:
> Viele Debugger haben eine Option "jump to main", dann landet man dort
> immer ohne init durchklicken oder manuell nen FUnktionsbreakpoint zu
> setzen.
> Nur so als Option für Faule.

Das ist auch eine Sache, die wenig Aufwand in der Umsetzung machen 
dürfte.
Mal sehen, vielleicht komme ich noch dieses WE dazu.
Die GDB-Sachen setzen doch etwas mehr Lesen und Verstehen voraus, da 
kann ich noch nichts versprechen.
mfG

Autor: Uwe S. (steinm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

habe es mal unter Linux probiert und gleich bei der ersten elf-Datei ein 
segm fault bekommen, weil in elf.c:159 ein Speicherbereich freigeben 
wurde (free(stabstr);), der wohl zuvor nicht allociert wurde.

Wenn man als PC einen nicht existierenden Symbolnamen eingibt, dann 
kommt es auch zum Absturz. Diesmal in
refresh () at avrsim.cpp:120
 bei dem sprintf()

  Uwe

Autor: R. M. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hat etwas länger gedauert als geplant, hatte am Wochenende noch eine 
andere Baustelle und wollte auch vorher noch die, durch Uwe gemeldeten 
Fehler (Danke für den aussagekräftigen Bericht) korrigieren.
- Laden von "ELF"s sollte jetzt auch funktionieren, wenn keine 
"stabstr"-Tabelle drin ist;
- bei Eingabe ungültiger Symbolnamen / nicht als HEX lesbarer Werte in 
PC und Haltepunkt, kommt Fehlermeldung in Statuszeile, alter Wert wird 
nicht verändert;
- "goto main" ist auf der neuen Schaltfläche "m()";
mfG

Autor: Uwe S. (steinm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe es nochmal ausprobiert. Die beschriebenen Abstürze sind weg, aber 
war es vorher nicht so, dass man bei der Eingabe eines Symbolnamens 
(oder auch eines hex-Werts) als PC im Disassembler an die entsprechende 
Stelle gesprungen ist? Man gibt also z.B. 'main<CR>' ein und sieht im 
Disassembler-Fenster dann den Assembler-Code. Egal was ich eingebe, es 
wird immer ab Adresse 0x0000 disassembliert.

Noch eine blöde Frage. Was muss ich den machen, um den Quellcode zu 
sehen?

Autor: R. M. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Uwe S. schrieb:
> Habe es nochmal ausprobiert. Die beschriebenen Abstürze sind weg, aber
> war es vorher nicht so, dass man bei der Eingabe eines Symbolnamens
> (oder auch eines hex-Werts) als PC im Disassembler an die entsprechende
> Stelle gesprungen ist?

Autsch - Rückgabewert auf Gültigkeit geprüft, dann aber doch eine 0 in 
den PC geschrieben, so geht es natürlich nicht - ist jetzt korrigiert 
(aber ohne linux-binary, hab hier gerade nur Windows zur verfügung).

> Man gibt also z.B. 'main<CR>' ein und sieht im
> Disassembler-Fenster dann den Assembler-Code. Egal was ich eingebe, es
> wird immer ab Adresse 0x0000 disassembliert.

sollte jetzt funktionieren, sollte man allerdings nur machen, wenn man 
nicht beabsichtigt, den Code auch auszuführen, weil damit die 
Initialisierungen (SP und so weiter) übersprungen werden. Dafür ist die 
neue Funktion "go to main" besser, damit wird die reguläre 
Initialisierung abgearbeitet, bis der PC auf "main" steht.

> Noch eine blöde Frage. Was muss ich den machen, um den Quellcode zu
> sehen?

Das Quellcodefenster wird mit "View->Source" ein/ausgeblendet, ob dort 
auch wirklich etwas angezeigt wird, hängt von den Debugging-Infos in der 
ELF-Datei ab, und ob sich die Quelldatei im gleichen Verzeichnis (oder 
im "Include-Path") befindet.

mfG

Autor: Uwe S. (steinm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Korrektur. Jetzt läuft es deutlich besser. Bei der letzten 
Fassung hatte ich auch sporadisch Abstürze, wenn die Emulation lief. Die 
sind jetzt weg.

Wie springe man denn im Disassembler an die Stelle im Code, an die auch 
"go to main" springt, ohne gleich die Emulation zu starten. Um einfach 
mal zu schauen, was der Compiler produziert hat.

Den Quellcode sehe ich auch, aber nur die Assembler-Teile meines 
Programms. Könnte man auch den C-Code passend anzeigen?

Autor: R. M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Uwe S. schrieb:
> Wie springe man denn im Disassembler an die Stelle im Code, an die auch
> "go to main" springt, ohne gleich die Emulation zu starten. Um einfach
> mal zu schauen, was der Compiler produziert hat.

Wie gesagt, um nur die Disassemblerausgabe anzuschauen, kannst Du in den 
PC eine Adresse oder einen Symbolnamen eingeben. Musst nur im 
Hintergrund behalten, das der restliche Prozessor dann nicht im Zustand 
ist, dort einfach "weiterzuarbeiten". Musst dann Funktionsaufrufe, 
Rücksprünge selbst im Hinterkopf behalten.
Wenn es um Disassemblierung eines ganzen Programmes geht, könnte ich 
noch mit einbauen, gibt aber auch z.B. schon fertige Lösungen für.
Risiko bei so etwas, sind immer Datenstrukturen im Flash, die den 
Disassembler durcheinander bringen.
Daher disassembliere ich auch immer nur die als Nächstes auszuführenden 
Befehle.
mfG

Autor: Ingo W. (uebrig)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
In Beitrag "Schiebebefehl ATmega8 - mov Rd,Rr" ist ein 
Fehler im Befehl "mov Rd,Rs" festgestellt worden (Quelle und Ziel in der 
Simulation vertauscht). Im Anhang, die Korrektur.

Autor: Andreas N. (nabi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Ingo,

vielen Dank für die super schnelle Reaktion.

Danke.

Autor: Kaj G. (Firma: RUB) (bloody)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Ingo,

Ich wollte den Simulator mal testen, und habe mir die Linuxversion
aus diesem Beitrag:
Beitrag "Re: AVR Simulator mit grafischer Benutzeroberfläche für Linux"
runtergeladen. Direkt beim starten stuertzt das
Programm mit einem SIGSEGV ab.

Was ich an Informationen geben kann:
Warnung beim Compilieren:
avrsim.cpp: In function 'MyTable* cr_tab(int, int, int, int, Fl_Double_Window**, int, int, const char*)':
avrsim.cpp:397:1: warning: no return statement in function returning non-void [-Wreturn-type]
 }
 ^

Das ist nicht gut, da die Funktion 3x aufgerufen wird:
ram_tab = cr_tab(20,20,380,400,&ram_win,DT_RAM,20,"RAM");
eeprom_tab = cr_tab(40,40,380,400,&eeprom_win,DT_EEPROM,20,"EEPROM");
flash_tab = (60,60,640,400,&flash_win,DT_FLASH,40,"FLASH");
MyTable *cr_tab(int x, int y, int w, int h, Fl_Double_Window **win, int kind,int col_width,const char *name){
  MyTable *r;
  *win=new Fl_Double_Window(x,y,w,h,name);
  r=new MyTable(0,0,w,h,kind,col_width);
  (*win)->end();
  (*win)->resizable(r);
  (*win)->show();
  (*win)->hide();
}
Wenn du hier noch ein 'return r;' einfuegst, funktioniert es. :)

Interessanterweise ist dieser Bug schon seit der Version vom 27.02.2017 
drin.
Beitrag "AVR Simulator mit grafischer Benutzeroberfläche für Linux"


Gruesse

Autor: Ingo W. (uebrig)
Datum:
Angehängte Dateien:

Bewertung
1 lesenswert
nicht lesenswert
Hallo Kaj,
danke für den Hinweis!
Peinlich, das mir dies bisher nicht aufgefallen ist, theoretisch hätte 
es garnicht funktionieren dürfen, den Compiler habe ich immer über das 
"fltk-config"-bash script aufgerufen, der hat mir keine Warnung 
geworfen.
Die (ausschliesslich) geänderte "avrsim.cpp" hab ich nochmal einzeln 
angehängt, dann brauchen die Linux-Nutzer nicht das ganze Quellarchiv 
runterladen.

Autor: Kaj G. (Firma: RUB) (bloody)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ingo W. schrieb:
> Hallo Kaj,
> danke für den Hinweis!
Gerne :)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.