1

Donnerstag, 23. Oktober 2008, 01:22

Tutorial: Programm "debuggen" mit dem MPSIM Simulator

Häufig läuft ein Programm nicht auf Anhieb, sondern enthält noch eine gewisse Anzahl Fehler. Nun kann man ein Programm schreiben, in BIN bzw. HEX-code übersetzen und in den Controller brennen, diesen in die Ziel-Hardware stecken und einschalten. Mit etwas Glück passiert etwas, das Rückschlüsse auf die Art des Fehlers zulässt, wenn aber einfach keine nachvollziehbare Funktion zu sehen ist (hier z.B.: falls die LED einfach nur aus bleibt), kann man so nur "geht" oder "geht nicht" diagnostizieren, und ggf. stundenlang über dem Quelltext brüten und spekulieren, wo der Fehler wohl liegen könnte.

Fehler in Computerprogrammen nennt man traditionell "Bug" (= "Käfer"), seitdem bei einem der ersten Computer, die noch mit Röhren und Relais aufgebaut waren, mal so ein Insekt einen Kurzschluß und damit eine seltsame Fehlfunktion ausgelöst hatte. Der Prozess zum Entfernen der "Bugs" aus dem System heißt daher "debugging", Hilfsmittel zum Aufspüren der Fehler nennt man "Debugger". Eines dieser Tools ist der Simulator "MPLAB SIM". Dieser hat den Vorteil, daß wir keine Hardware brauchen (nicht einmal den Prozessor, für den wir das Programm geschrieben haben) und er ist in der MPLAB IDE integriert. Daher werden wir mit diesem Tool arbeiten.

Weil man mit dem Debugger so schön die Arbeit des Prozessors genau beobachten kann, auch die internen Register, die einem beim "echten" Prozessor verborgen bleiben, ist das auch ein prima Tool zum Experimentieren und Lernen, wie der Prozessor arbeitet.

Um den Simulator kennenzulernen, verwenden wir eine etwas erweiterte Version des LED-Schalters aus dem Tutorial "Projekt erstellen". Der PIC hat dabei die Funktion, beim Betätigen eines Tasters (S1) eine LED einschzuschalten, beim Betätigen des anderen Tasters (S2) die LED auszuschalten (siehe Schaltbild).
»Ottili« hat folgendes Bild angehängt:
  • probe.gif

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Ottili« (23. Oktober 2008, 02:10)


2

Donnerstag, 23. Oktober 2008, 02:02

Tutorial: Programm "debuggen" mit MPSIM - das Demo-Programm

Hier ist das Source-File. Die Datei (simdemo.asm) kann in den bereits vorhandenen Ordner "Probe" entpackt werden. Statt ein neues Projekt anzulegen, kann auch einfach im Projekt "Versuch" die Datei "Probe.asm" durch "simdemo.asm ersetzt werden. Dazu im Projekt-Fenster auf die Datei klicken, mit der [Entf]-Taste entfernen, nun mit der rechten Maustaste auf das "Source Files"-Ordnersymbol klicken, "Add Files..." und die Datei "simdemo.asm" hinzufügen.
Durch einen Doppelklick auf "simdemo.asm" im Projekt-Fenster öffnet sich das Editor-Fenster mit dem Sourcetext.
Das Ausführen von "Project/make" (bzw. [F10]) sollte ohne Fehlermeldung mit "BUILD SUCCEEDED" im Output-Fenster durchlaufen.

Nun wählen wir das Debugger-Tool aus über "Debugger/Select Tool/MPLAB SIM".
Unter "Debugger/Settings" wird bei "Osc/Trace" noch die richtige Taktfrequenz des Prozessors eingestellt (hier: 4MHz). Das hat zwar keine unmittelbare Auswirkung auf die logische Abarbeitung des Programms, jedoch zeigt die Stoppuhr (Debugger/StopWatch) nur mit richtig eingestellter Taktrate die "echte" Zeit an.

Mit der Funktion "Debugger/Reset/Processor Reset" (= Funktionstaste [F6], alternativ: Klick auf das entsprechende Symbol in der "Debug"-Menüleiste) wird am virtuellen Prozessor ein Reset ausgelöst und das Programm damit auf Anfang gesetzt.
Nun kann das Programm Schritt für Schritt abgearbeitet werden: Durch wiederholtes Drücken von [F7] wird ein Befehl nach dem anderen simuliert. Dabei zeigt ein grüner Pfeil im Quelltext-Fenster immer auf den nächsten auszuführenden Befehl.
»Ottili« hat folgende Datei angehängt:
  • simdemo.zip (996 Byte - 17 mal heruntergeladen - zuletzt: 10. April 2014, 11:47)

3

Donnerstag, 23. Oktober 2008, 02:46

Tutorial: Programm "debuggen" mit MPSIM - Register beobachten

Ein durch den Programmtext wandernder, grüner Pfeil allein lässt noch nicht sehr tief in den Prozessor blicken. Um besser beobachten zu können, was der Prozessor macht, wird über "View/Special Function Registers" das Fenster mit den Registern geöffnet.

Die Variablen "counter" und "timer", die im RAM-Bereich des Prozessors angelegt worden sind, können über ein weiteres Fenster mit "View/File Registers" beobachtet werden. Da das hier ja nur zwei Speicherzellen sind, kann das Fenster stark verkleinert werden (an die entsprechende Stelle scrollen).

In welcher Form die Daten der Register oder Speicherzellen angezeigt werden, lässt sich anpassen, indem mit der rechten Maustaste auf die Spaltenüberschrift geklickt wird. Dann kann durch Häkchen vor den möglichen Darstellungsarten die gewünschte Darstellung aktiviert werden. Um den Status einzelner Bits gut sehen zu können, bietet sich die Binäre Darstellung an. Damit ist z.B. leicht beim Register GPIO der Zustand der LED (an/aus) unserer Beispiel-Schaltung am 3.Bit von rechts ablesbar.

ro.heg

RCLine User

Wohnort: Quickborn

  • Nachricht senden

4

Donnerstag, 23. Oktober 2008, 19:48

Hallo Thomas,
versuche mit unseren LED Programm debuggen nachzuvollziehen!
Ich komme so weit, bis die Abfrageschleife "S1" beginnt.
Irgendwie hast Du durch meine viele Fragerei am 18.10.08 den Faden
verloren. Ich drucke alles aus und sehe ein Fenster, wo ich GP0 Set low,
GP0 Set High usw. eingeben sollte.....und dann war Schluß!

Viele Grüße und ein Dank für Deine viele Mühe.

Rolf

5

Donnerstag, 23. Oktober 2008, 21:39

Hallo Rolf,

das Sim-Tutorial wird hier noch weitergehen! Damit es nicht im "Allgemeine Diskussion"-Teil zwischen diversen Diskussionsbeiträgen untergeht, habe ich diesen separaten Thread als Tutorial neu erstellt. Leider habe ich derzeit etwas wenig Zeit und komme oft erst sehr spät dazu, hier ein paar Beiträge zu verfassen....
Also, es geht schon noch weiter, aber dieser Tage leider etwas langsam!
Demnächst: Anlegen von Stimuli (verschiedene Arten), grafischen Darstellung der Signale im "Simulator Logic Analyzer" u.v.a.

Grüße,

Thomas

6

Samstag, 25. Oktober 2008, 00:56

Tutorial: Programm "debuggen" mit MPLAB SIM - Signale anlegen

Bis hierher haben wir gesehen, wie man im Simulator den Prozessor bei der Verarbeitung des Programms genau beobachten kann. Um Programme zu testen, brauchen wir aber auch die Möglichkeit, Eingangssignale, wie z.B. unsere Taster an den Pins GP0/GP1, an den simulierten Prozessor anzulegen. Ein virtuelles Eingangssignal für eine simulierte Schaltung nennt man "Stimulus".

So gehen wir vor:
Über "Debugger/Stimulus/New Workbook" das Fenster zur Eingabe der Daten öffnen. Für eine einfache, manuelle Eingabe nehmen wir den "Asynch"-Reiter, da die Eingabe von Pegeländerungen hier zu beliebigen Zeiten, eben "asynchron" zu irgend etwas anderem, erfolgen kann. Jetzt basteln wir uns ein paar einfach anklickbare Eingangs-Signalpegel:
Im ersten "Pin/SFR"-Feld wählen wir "GP0" aus, im "Action"-Feld rechts daneben "Set Low". Eine Zeile darunter wählen wir wieder "GP0", diesmal aber als Aktion "Set High".
Das gleiche machen wir in Zeile 3 und 4 mit GP1. Das Ergebnis ist das Stimulus-Fenster wie im Bild.
Durch Mausklick auf den jeweiligen "Fire"-Button links vor der Zeile können wir nun nach belieben 1-Pegel (High) oder 0-Pegel (Low) für die jeweiligen Pins anlegen. Da die Taster in unserer Testschaltung die Pins auf Masse (0V=Low) ziehen, die Pins sonst durch einen "Pull-Up"-Widerstand im Prozessor auf +5V (=High) gelegt werden, entspricht also "Fire" bei "Set Low"-Action dem Drücken, und bei "Set High" dem Loslassen des Tasters.
»Ottili« hat folgendes Bild angehängt:
  • stimulus.gif

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Ottili« (25. Oktober 2008, 03:09)


7

Samstag, 25. Oktober 2008, 03:02

Tutorial: Programm "debuggen" mit MPLAB SIM - Programm ausführen

Der Simulator MPLAB SIM simuliert nicht die Pull-Up Widerstände, die im Programm aktiviert werden, und erst recht würde der Simulator natürlich auch keine externen Pull-Up Widerstände berücksichtigen. Wenn das Programm also im Simulator gestartet wurde, und noch keine Stimuli aktiviert wurden, sind die Porteingänge erstmal alle auf Low-Pegel (logisch 0). Das entspricht nicht unserer "echten" Hardware, deshalb muß eine der ersten Aktionen nach dem Start des simulierten Programms das Anlegen von High-Pegel an die Portleitungen sein, was "Taster losgelassen" bei der Schaltung entspricht.

Um die Simulation auf Anfang zu setzen, drücken wir also die [F6] Taste (oder per Menü: Debugger/Reset/Prozessor Reset), dann klicken wir im "Stimulus"-Fenster auf "Fire" für "GP0 Set High" und "GP1 Set High". Nachdem mit F7 durch die ersten Befehle gesteppt wurde, sieht man, daß die Bits 0 und 1 vom Register GPIO nun "1"-Pegel zeigen ( Special Function Register dafür auch binär anzeigen lassen!).
Ein paar mal mehr [F7] gedrückt, und man sieht, wie das Programm beim Label "waits1" in einer Schleife hängt, in der auf Low-Pegel am GP0-Eingang (= Taste S1 gedrückt) gewartet wird. Also simuleren wir jetzt den gedrückten Taster (S1), indem auf "Fire" für "GP0 Set Low" geklickt wird. Jetzt können mit [F7] die nächsten Befehle durchgesteppt werden. Nach einigen weiteren Steps mit [F7] landen wir im Unterprogramm "delay", in einer Warteschleife. Die kann man zwar auch weiter mit [F7] durchssteppen und dabei im Fenster "File Registers" beobachten, wie "timer" heruntergezählt wird, aber das wird schnell langweilig. Es wären auch ungefähr 200 [F7]-Tastendrücke, bis man aus der Warteschleife kommt! Wie kann man das jetzt abkürzen?
Zum Beispiel so: mit der rechten(!) Maustaste auf den nächsten Befehl hinter der langweiligen Schleife klicken (das ist hier der "return"-Befehl) und aus dem sich aufklappenden Menü den Punkt "Run to Curser" auswählen. Nun läuft das Programm am Stück bis zu diesem Programmschritt durch und hält erst dort wieder an. Dieser Befehl ("Run to Cursor") ist immer dann sehr nützlich, wenn man sich für eine bestimmte Programmstelle interessiert und die Programmteile davor nicht im Einzelschritt-Betrieb analysieren muß oder will. Wenn z.B. bei unserem Demo-Programm ein Fehler in dem Bereich vermutet würde, wo die LED nach Drücken von S2 ausgeschaltet wird, kommt man schnell zu der entsprechenden Stelle:
- Programm resetten [F6]
- Taster auf "losgelassen" setzen (Stimulus: GP0 und GP1 jeweils auf High abfeuern)
- Programmstelle im Quelltext suchen, die wir näher untersuchen wollen. Hier z.B. nach der Warteschleife "waits2" der Befehl "incf counter,F"
- mit rechter Maustaste auf den Befehl klicken, "Run to Cursor"
Das Programm läuft nun, aber im "Run"-Modus sieht man nichts davon - erst, wenn das Programm angehalten wird, werden die Fenster mit den Register-Daten aktualisiert! Die Stimulus-Eingaben funktionieren aber, und so simulieren wir das Ein- und Ausschalten der LED über die Taster:
- [>] GP0 Set Low (Taste 1 drücken)
- [>] GP0 Set High (Taster 1 wieder loslassen)
- [>] GP1 Set Low (Taste 2 drücken
Damit kommt das Programm zu der vorher definierten Stelle und hält an.
Kommt das Programm wider Erwarten nicht an dieser Stelle an, muß es durch "Debugger/Halt" (Taste [F5]) abgebrochen werden. Der grüne Pfeil erscheint dann vor der Programmzeile, in der das Programm angehalten wurde.

Eine andere Möglichkeit, um speziell aus Unterprogrammen oder Interrupt-Service Routinen schnell herauszukomen, ist der Befehl "Debugger/Step Out". Hier wird der ganze Rest des Unterprogramms abgearbeitet und das Programm stoppt im übergeordneten Programm nach der Stelle, wo das Unterprogramm oder der Interrupt aufgerufen wurde.
Wenn man das Hauptprogramm im Einzelschritt-Betrieb analysieren möchte, aber der Inhalt von einem Unterprogramm nicht durchgesteppt werden soll, kann "Step Over" (Funktionstaste [F8]) statt "Step Into" [F7] verwendet werden. Damit werden Unterprogramme wie ein Schritt abgearbeitet.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Ottili« (25. Oktober 2008, 03:08)


8

Sonntag, 26. Oktober 2008, 23:55

Tutorial: Programm "debuggen" mit MPLAB SIM - Stimulus automatisieren

Während des Entwicklungsprozesses werden die folgenden Schritte immer mehr oder weniger oft wiederholt, bis das Programm (vermeintlich) fehlerfrei ist:
- Quelltext verändern
- Programm assemblieren
- Programm testen, Fehler finden
- Queltext verändern
- usw...

Vermutlich wird man bei den wiederholten Testläufen im Simulator auch immer wieder die gleichen Stimuli anlegen wollen. Mit der bisher kennengelernten Methode (manuell über "Fire"-Buttons) ist das etwas mühsam und fehleranfällig. Deshalb programmieren wir nun die Eingangssignale entsprechend vor, damit wir das Testprogramm dann nur noch ablaufen lassen müssen.

Dazu klicken wir im "Stimulus" Fenster auf den Reiter "Pin/Register Actions". Mit einem Klick auf "Click here to add signals" werden nun die Signale GP0 und GP1 zu "Selected Signals" hinzugefügt (wie gehabt: Markieren und [Add]), dann [OK].
Nun sollte je eine Spalte für GP0 und GP1 vorhanden sein.
Bei "Time units" kann eine geeignete Zeiteinheit gewählt werden. Wir wählen hier mal die Einheit Millisekunden "ms". In der Spalte "Time" können nun beliebige Zeitwerte eingegeben werden, in der jeweiligen Zeile können für die einzelnen Signale Werte angegeben werden, die zum jeweiligen Zeitpunkt angenommen werden sollen.
Folgender Ablauf soll erreicht werden:
Am Anfang (T=0 ms) sind beide Taster losgelassen, also GP0/GP1 jeweils = 1.
Nach 1 ms wird S1 gedrückt -> GP0 = 0, nach einer weiteren ms (T=2ms) S1 loslassen (GP0=1). Bei T=5ms nach Programmstart soll S2 1 ms lang gedrückt werden.
Dann soll sich das Ganze wiederholen. Dazu wird ein Häkchen bei "Repeat" gesetzt und in das Feld "after:" z.B. eine 2 eingetragen. Das bedeutet, daß zwei Millisekunden nach der letzten Aktion aus der Liste der Vorgang wieder bei 0 ms anfängt.

Das Stimulus-Fenster sollte dann so aussehen:
»Ottili« hat folgendes Bild angehängt:
  • stimulus.gif

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Ottili« (26. Oktober 2008, 23:58)


9

Montag, 27. Oktober 2008, 01:06

Tutorial: Programm "debuggen" mit MPLAB SIM - Breakpoints und Stoppuhr

So, nun können wir das Programm wieder zurücksetzen [F6] und z.B. mit dem bereits bekannten "Run to Cursor" bis zu beliebigen Stellen laufen lassen, von dort wieder im Einzelschritt [F7] oder [F8] oder mit "Run to Cursor" usw., und dabei die Auswirkungen auf Ports und Register beobachten. Die Funktion "Run" [F9] macht hier nur im Zusammenhang mit Breakpoints wirklich Sinn, da das Programm sonst nur abläuft, ohne Auswirkungen auf dem Bildschirm zu zeigen.
Also probieren wir jetzt mal Breakpoints! Ein Breakpoint ist so ähnlich, wie "Run to Cursor", allerdings bleibt die markierte Stelle bestehen und es können gleich mehrere Stellen im Programm als Breakpoints gekennzeichnet werden. Immer, wenn das Programm auf einen aktiven Breakpoint trifft, hält es dort an und es können Daten/Ports/Register inspiziert werden.
Ein Breakpoint kann sehr einfach über Doppelklick auf den gewünschten Befehl im Quelltext gesetzt werden. Nochmal Doppelklick löscht den Breakpoint wieder. Hier möchten wir z.B. das Programm immer anhalten, wenn die LED ein- oder ausgeschaltet wird. Also: Doppelklick auf den Befehl "bsf GPIO,2" (nach Label "ledoff") und Doppelklick auf "bcf GPIO,2" ein paar Zeilen darunter. Es erscheint jeweils ein rotes "B" vor der Zeile.
Für die Beobachtung der abgelaufenen Programmzeit öffnen wir die Stoppuhr:
Menü "Debugger/Stopwatch". Damit diese die "richtige" Zeit anzeigt, muß die korrekte Taktfrequenz des Prozessors eingestellt sein (hier: 4MHz, ggf. über "Debugger/Settings" ändern!).
So, nun also wieder Reset[F6], dann das Programm mit "Run" [F9] starten. Nach wenigen Microsekunden hält das Programm beim ersten Breakpoint an. Jetzt wieder mit [F9] weiter laufen lassen. Die Warteschleife "waits1" wird ausgeführt, bis der Stimulus nach 1ms zuschlägt und einen gedrückten Taster S1 simuliert. Dadurch kommt der Prozessor aus der Schleife und landet beim zweiten Breakpoint. Wieder [F9] und das Spiel geht weiter, bis der simulierte Tastendruck (S2) bei 5ms stattfindet.

Mit der Stoppuhr können auch leicht Laufzeiten von einzelnen Programmteilen ermittelt werden. Beispiel: es soll die Laufzeit des Unterprogramms "delay" ermittelt werden. Dazu mit "Run to Cursor" auf den Befehl "call delay", bis der grüne Pfeil auf dieser Zeile steht (das Programm hält auch bei "Run to Cursor" auf den Breakpoints!), dann im Stopwatch-Fenster auf [Zero] klicken und das Unterprogramm durch [F8] oder "Run to Cursor" auf den nächsten Befehl ausführen. Bei Time steht nun die Laufzeit.

10

Montag, 27. Oktober 2008, 01:54

RE: Tutorial: Programm "debuggen" mit MPLAB SIM - Logic Analyser

Zum Abschluß dieses Simulator-Tutorials schauen wir uns noch eine Möglichkeit zur grafischen Darstellung der Signale an:
Über "View/Simulator Logic Analyzer" öffnen wir das Fenster, mit dem [Channels]-Button werden die darzustellenden Signale gewählt. Hier sind es: GP0, GP1 (für die Taster) und GP2 (für den LED-Ausgang).
Nun lassen wir unser Programm mit den oben vorprogrammierten Stimuli für 10-15 Millisekunden ablaufen (Mit den Breakpoints einfach ein paar mal auf [F9] drücken).
Im Ergebnis sieht man die Logikpegel der ausgewählten Signale über der Zeit (in Maschinenzyklen=Taktfrequenz/4).

Soweit mal die Vorstellung der wichtigsten Funktionen des Simulators beim Austesten der Programme. Viel Spass bei eigenen Experimenten!

Viele Grüße,

Thomas