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!!!
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:
...
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
>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.
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.
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
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 :(...