Forum: Mikrocontroller und Digitale Elektronik 8051, Ringbuffer in Assembler


von Magnus (Gast)


Lesenswert?

Hallo *,

ich arbeite mit einem Philips 8051 basieredem Controller (Genauer 
P89LPC921) und muss in diesem einen Ringbuffer realisieren. (Die 
eigentliche Aufgabe des Controllers besteht darin, 2 Byte Daten von I²C 
auszuwerten und eine Tastaturausgabe (PS/2-Protokoll) zu erzeugen.)

Nun habe ich im Netz schon nach Lösungsansätzen gesucht und habe mich 
für diesen entschieden:

http://www.embeddedrelated.com/groups/piclist/show/2273.php
(2. Beitrag)

Zum Testen habe ich dann mein Programm so gestaltet, dass ich den 
Ringbuffer händisch fülle (2 Bytes) und dabei den Counter (ebenfalls 
händisch) hochzähle. Das Befüllen soll später über einen Interrupt 
erfolgen. (sollte kein Problem sein)

Jedenfalls, nach der manuellen Vorbereitung werte ich den Counter aus, 
und wenn 2 oder mehr Bytes neu in den Puffer gelegt wurden, so sollen 
diese Daten über das PS/2 Protokoll verschickt werden.

Dabei wird der Counter dann wieder dekrementiert.

Nun habe ich das Programm einmal in den Chip gebrannt und nachdem ich 
das Delay verkürzen wollte, lies sich der Controller nicht mehr 
beschreiben.
Leider verfügt er nur über einen ISP-Modus und nicht über MISO/MOSI 
Leitungen. D.h. wenn ich den ISP Code überschreibe wird der Controller 
unbrauchbar.

Ich weiß, ich habe bei diesem "Ringbuffer" noch keine Abfrage drin, ob 
der Buffer nicht grade seine Grenze erreicht hat.
Das aber auch nur, weil ich R0 bei jedem Scheifendurchgang neu mit der 
Startadresse des Ringbuffers fülle (oder zumindest denke das zu tun) und 
ich damit dachte ein überlaufen auszuschließen.


Ist der Quellcode den soweit korrekt, oder gibt es einen Fehler, den ich 
einfach nicht sehe und der mir dann irgendwie den ISP-Code überschrieben 
haben könnte?


Ich danke vielmals für Tips und Hilfestellungen!!!

von Magnus (Gast)


Angehängte Dateien:

Lesenswert?

Irgendwie hat das mit dem Dateianhang grade nicht geklappt. Neuer 
Versuch

von Magnus (Gast)


Lesenswert?

Ich vergaß zu erwähnen, dass vor der Mainloop natürlich die HEAD und 
TAIL Variablen initialisiert werden:


mov HEAD, #RING_BUF
mov TAIL, #RING_BUF
mov COUNTER, #0


MainLoop:
...

von Peter D. (peda)


Lesenswert?

Magnus wrote:

> Nun habe ich das Programm einmal in den Chip gebrannt und nachdem ich
> das Delay verkürzen wollte, lies sich der Controller nicht mehr
> beschreiben.

Ja, man kann sich bei den LPC sehr leicht aussperren.
Die haben ja keinen PSEN, wie die 40-Pinner mit dem man den 
Bootloaderstart erzwingen kann.

Man muß also bevor man sich aussperrt eine Backdoor installieren:

http://www.8052.com/users/erikm/NoTouch932.phtml


Peter

von Matthias (Gast)


Lesenswert?

>Leider verfügt er nur über einen ISP-Modus und nicht über MISO/MOSI
>Leitungen. D.h. wenn ich den ISP Code überschreibe wird der Controller
>unbrauchbar.

Benutzt Du FlashMagic zum programmieren? Und welchen Adapter?

Die LPC900 sind zwar sehr schnell, haben aber beim programmieren ihre 
Tücken, kann ich bestätigen. Der Bootloadercode der ISP-Typen (ab 
LPC920) liegt standardmäßig in den obersten Teil des FLASH. Bei 
FlashMagic gibt es unter Optionen "Protect ISP Code", dies sollte immer 
aktiviert werden und verhindert das versehendliche Löschen. Oder man 
bindet gleich die Bootloader-Quelle mit ein und brennt so jedesmal den 
ISP-Code mit.
Möglicherweise hast Du aber auch den Vector zum starten des Bootloaders 
umprogrammiert!

In der Anlage sind die Quellen des LPC9xx Bootloaders enthalten und ein 
Bsp. wie man sie einbindet.

Ist der ISP Bootloader erstmal gelöscht, hilft nur noch die 
Programmierung per ICP. Dies kann man auch mit einen 2. ISP-fähigen LPC 
per ICP-Brigde erfolgen, oder mit einen anderen Programmiergerät. Man 
kann dann auch den Bootloader wieder draufprogrammieren, wird sich bei 
den geringen Preis aber kaum lohnen.

>Ja, man kann sich bei den LPC sehr leicht aussperren.
>Die haben ja keinen PSEN, wie die 40-Pinner mit dem man den
>Bootloaderstart erzwingen kann.

Der Bootloader der LPC9 wird über 3 kurze Impuls am RST-PIN kurz nach 
dem  Einschalten von VDD gestartet. Geht eigentlich problemlos. Das 
genaue Timing steht im Datenblatt.
Hast Recht, bei den Atmel-Typen mit Bootloader kann man sich nicht ganz 
so leicht aussperren, da der ISP Code in einem separaten Bereich liegt.

von Matthias (Gast)


Angehängte Dateien:

Lesenswert?

Hier noch die Anlage, kam beim ersten mal nicht mit?

von R. W. (quakeman)


Lesenswert?

Magnus wrote:
> Leider verfügt er nur über einen ISP-Modus und nicht über MISO/MOSI
> Leitungen. D.h. wenn ich den ISP Code überschreibe wird der Controller
> unbrauchbar.
Das ist nicht ganz korrekt.
Der P89LPC921 verfügt über einen standard parallelen Programmiermodus 
sowie über ICP und ISP Programmiermöglichkeiten. Also selbst wenn du den 
Bootloader versehentlich per ISP überschrieben haben solltest, kannst du 
den Controller per ICP oder mit einem herkömmlichen Programmiergerät 
wieder beschreiben und auch den Bootloader wieder reinschreiben.

Magnus wrote:
> Ich weiß, ich habe bei diesem "Ringbuffer" noch keine Abfrage drin, ob
> der Buffer nicht grade seine Grenze erreicht hat.
> Das aber auch nur, weil ich R0 bei jedem Scheifendurchgang neu mit der
> Startadresse des Ringbuffers fülle (oder zumindest denke das zu tun) und
> ich damit dachte ein überlaufen auszuschließen.
Ein Ringbuffer hat keine "Grenze", da er die Daten ja im Kreis rotierend 
beinhaltet. Du kannst höchstens prüfen, ob du den Ringbuffer z.B. 
komplett ausgelesen hast oder ob er voll ist. In letzterem Fall würden 
neue Daten eben die ältesten Daten einfach wieder überschreiben.

von Magnus (Gast)


Angehängte Dateien:

Lesenswert?

Hallo!

Vielen Dank für eure Antworten.

Allgemein: Ich habe das Programm leicht modifiziert, da ich im 
Debugmodus festgestellt habe, dass mit der TAIL-Zeiger wegläuft, da 
dieser in der Endlosschleife nicht resettet wird (händisch).
Dann bin ich heute Morgen hingegangen und habe den Chip gegen einen 
anderen ersetzt (so eine kniffelarbeit o_O).
Dann habe ich zunächst ein Programm, von dem ich weiß, dass alles 
funktioniert (einfach eine I²C Master Applikation, die meinem Slave die 
Daten zuschiebt) eingebrannt (2 mal) und es gab keine Probleme beim 
"wieder bebrennen".

Naja und dann habe ich mein eigentliches SlaveProgramm wieder gebrannt 
und der Chip lies sich danach erneut NICHT brennen :(

Dabei sind beide Sourcen fast identisch, da ich den I²C Master selbst 
aufgesetzt habe.

Wenn ich mir die beiden Dateien in diff ansehe, sind die "großen" 
Verändergungen (also die neben den Kommentaren) lediglich folgende:


Beim I²C Master initialisiere ich lediglich einen Stack

1
;****************************************************************
2
; Stack Pointer einrichten 
3
;****************************************************************
4
5
STACK  SEGMENT IDATA    ;Stack wird im indirekten RAM-Bereich 
6
        RSEG STACK      ;eingerichtet
7
        DS   0AH       ;Reservierung von 10 Bytes fuer den Stack




Beim Slave kommt nach dieser Initialisierung noch die vom Buffer:
1
;****************************************************************
2
; Deklaration des Ringbuffers
3
;****************************************************************
4
INDIREKT_1 SEGMENT IDATA   
5
         RSEG INDIREKT_1
6
7
RING_BUF:  DS 20H  ; 32 Bytes fuer den Ringpuffer 
8
9
10
DIREKT_1 SEGMENT DATA   
11
         RSEG DIREKT_1
12
13
HEAD:    DS 1  ; HEAD, Zeiger auf letzten empfangenen Wert
14
          ;     im Ringbuffer
15
TAIL:    DS 1  ; TAIL, Zeiger auf letzten gesendeten Wert
16
          ;     im Ringbuffer
17
COUNTER:   DS 1  ; COUNTER, Zählervariable für den Buffer



Da ich mir unsicher war, welche RAM-Segmente/Adressen ich direkt nutzen 
kann, wollte ich es auf dem indirekten Wege machen, wo der Compiler 
bestimmt, an welcher Adresse der Stack oder der Buffer oder die 
Variablen angelegt werden.
(Hab beim debuggen auch heraus gefunden, wo sie dann liegen aber ich 
glaube, dass ist hier nicht wichtig, oder?)


Mach ich denn bei dieser Initialisierung irgendwas fatal falsch?


Die nächste Abweichung in beiden Programmen ist die Initialisierung der 
Ports und die MainLoop eben, die oben im ersten Anhang zu finden ist.
(Es wurde lediglich das Delay nun verkürzt und zum Beginn der MainLoop 
HEAD auf die Startadresse vom Buffer gesetzt. Im aktuellen Anhang ist 
aber die Main auch drin.)





So und nun zu den speziellen Antworten:

@peda:
Genau das ist einem Kollegen mit dem Chip mal passiert, deshalb hatte er 
mich beim Beginn der Arbeit drauf hingewiesen und mir seinen Source-Code 
als "Grundlage" zur Verfügung gestellt, in dem diese Abfrage 
durchgeführt wird. Ich habe sie dann einfach übernommen.
Ich hänge dir die Abfrage als Anhang dran.


@Matthias:
Ja, FlashMagic benutze ich. Der Adapter ist von einem Kollegen 
zusammengeschreinert speziell für diese Platine und der tut dumm vor 
sich hin ;)
Die Option "Protect ISP Code" hab ich in der "Security" immer 
eingestellt ;)
Das mit dem Vector wäre vllt noch eine Möglichkeit, obwohl ich nicht 
weiß, ob dass dan was mit dem Anlegen des Speicherbereichs für den 
Buffer zu tun hat. Im Anhang habe ich den ISP/Nicht-ISP 
Entscheidungscode und die aktuelle Hauptschleife drin. Wenn du es dir 
ansiehst, sieht du vielleicht auf Anhieb, was falsch ist, wobei ich 
denke es richtig gemacht zu haben.


@quakeman:
Vielen Dank: Wieder was gelernt. Das mit dem ICP ist mir irgendwie 
komplett entgangen.
Mit "Grenze" vom Ringbuffer meinte ich die letzte zu beschreibende 
Adresse, bevor der Zeiger wieder an die Anfangsadresse springt.




Ich werde nun mich wieder ans löten begeben und mal sehen, ob es vllt 
besser ist die Datensegmente am Anfang irgendwie anders zu 
initialisieren.
Ich habe keine Ahnung, welche Zusammenhänge da sein könnten. Aber er 
will sich halt einfach nicht programmieren lassen :(...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.