Ich habe in einem anderen Beitrag hier (Beitrag "Funktion Reifendruckanlerngerät EL-50448; OEC-T5; Welches Bauelement ist das?") zu einem RDSK-Trigger Gerät Fragen zum darauf befindlichen PIC Mikrocontroller. Das RDSK-Thema ist aber vermutlich zu speziell, daher frage ich hier nochmal allgemein.
Herzstück hier ist ein PIC12F508I auf dem Board. Den habe ich runtergelötet und mit einem Flash-Programmer ausgelesen.
Laut Datenblatt hat dieser PIC einen Flash-Speicher von 512 words, also 1024 Bytes (0x400) und 25 Bytes RAM. Das BIN und HEX davon habe ich ins ZIP eingefügt. Ebenso ein Disassembly (mit PICDisasm erzeugt).
Wenn jetzt hier keine speziellen Protections greifen, dann dürfte das wirklich der komplette Code sein.
Vom Board her konnte ich ermitteln das folgende IO-Pins belegt sind:
- OSC1/OSC2 gehen direkt zu einem 4MHz Oszillator.
- GP0 konnte ich noch nicht ermitteln, wüsste auch grad nicht wozu es gut sein sollte da das Gerät nicht mehr Funktionen hat.
- GP1 geht über einen Transistor auf ein LCR, bestehend aus Antenne, Kondensator und Widerstand, nach Masse. Hierüber wird gesendet (125 kHz LF-Band)
- GP2 geht über einen 220 Ohm auf die Kathode einer grünen LED, welche den Sendebetrieb anzeigt (flackert beim drücken von T1)
- GP3 kommt über einen 4,7k von einem Taster T1 welcher auf (+) gelegt ist, er erzeugt also eine steigende Flanke.
Nun versuche ich aus der Software schlau zu werden und da könnte ich was Hilfe gebrauchen da ich mich mit den PICs überhaupt nicht auskenne.
Das FSR-Register sollte hier wohl keine Rolle spielen, da der 12F508 nur eine Speicherbank hat? Der Reset-Vector ist immer 0x0000, hier startet die Softwareausführung also. Auf Adresse 0x1FF soll beim 12F508 ein MOVLW Kommando mit dem Wert für die interne Oszillator-Kalibration liegen. Dieser liegt in meinem Dump jedoch auf 0x3FF und hat den Wert 0x2A.
Die Register liegen im RAM (Register File Map). Ich habe mit dann einen PIC-Simulator runtergeladen (https://gputils.sourceforge.io/) und versucht das alles nachzuvollziehen und hier ergeben sich die ersten Fragen:
Der erste Befehl ist laut Datenblatt die letzte Speicheradresse der ersten Page, dort wird das einzige Register "W" mit dem Wert 0x2A geladen. Danach geht der Programm-Counter automatisch auf 0x0000 und fängt an dort den Code auszuführen. Gleich die erste Anweisung ist ein NOP (warum nur?). Zunächst wird dann das OSCCAL-Register mit dem Wert aus W aus 0x2A beladen. Das kann ich im Simulator gut nachvollziehen.
Dann überspringt der Code einige Stellen die eher nach Daten als nach Programmcode aussehen um an Postion 0x0014 weiter zu machen. Dort ruft er eine Subroutine auf (LADR_0x0016) aus der er irgendwann mit einem return zurückkehren wird um dann anschließend an die Adresse LADR_0x0148 zu springen. Ab dieser Adresse stehen aber nur noch NOPs im Programmcode. Die führt er bis zuende aus um dann vermutlich wieder auf 0x0000 zu gehen und das Programm von vorn zu starten?
Der Code ab 0x0016 sieht aus wie eine Initialisierung der GPIOs. Hier wird das GPIO-Register (RAM Adresse 0x06) zunächst auf 0b00000100 eingestellt, was zur Folge hat das GP2 auf HIGH geht. Dadurch ist die grüne LED erstmal aus. Das nachfolgende MOVLW 0x08 und TRIS GPIO setzt wohl den GP3 (Taster-Eingang) auf Tri-State.
Nun wird der zuvor in W geladene Wert 0b01001111 mit dem "OPTION" Befehl in das gleichnamige Register geschrieben. Das bedeutet:
- setze den Prescaler des WDT auf 1:128
- setzte Wakeup auf Pin-Änderung von GP0, GP1 oder GP3 (hier sitzt der Taster)
Laut Datenblatt liest der Chip nach dem RESET das Configuration Word von der Speicheradresse 0x3FF. Hier steht im Dump ein 0b00001100 was soviel bedeutet wie "Use GP3 as input", "Use LP oscillator (200 kHz)", "Copy Protection OFF" und "Watchdog-Timer enabled". Das bedeutet das nach 18 ms nach dem POR der Watchdog auslöst. Ein solcher Auslöser ist immer ein RESET, es gibt also keine speziellen Watchdog-Vectoren/Code.
Soweit glaube ich noch mit zu kommen... aber jetzt geht es mit dieser ominösen Schleife los:
1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
Was genau macht dieser Code? Und sehe ich das richtig das nach der Schleife ein einfacher Return "RETLW 0x00" steht welcher die Subroutine und damit dann das Programm faktisch beendet? Das kann es ja nicht gewesen sein. Wie wird der code danach ausgeführt?
















