Guten Morgen,
erstmal hoffe ich, dass ich das richtige Forum erwischt habe, ansonsten
tuts mir leid. Mit der Suchfunktion habe ich auch nicht wirklich was
gefunden.
Meine Ausgangslage:
Ich benutze z.z. den LPC2103 und den CARM Compiler von Keil, dessen
support wohl eingestellt wird ( jedenfalls hab ich es so verstanden ).
Nun muss die ganze Sch**** RealViewCompiler-tauglich gemacht werden,
eigentlich gar kein Problem...
Mein Problem:
Nested Interrupts, mit dem CARM Compiler war es schön möglich auf alle
Register via Inline Assembler zu zugreifen, ist aber im RealView nicht
mehr möglich. Nun hab ich div. Lösungsansätze ( Link Register über
Variablen oder Register sichern )probiert, aber am Ende bin ich mitm
Debugger immer in der AbortException gelandet.
Dass man die ganzen Register ( eigentlich nur das Link sichern muss )
ist mir klar, aber mein Sicherungsmechanismus über statische Variablen (
Stackpointer wird zerschossen bei Operating Mode-Wechsel ) scheint auch
nicht die Lösung zu bringen.
Hat irgendwer eine Idee, wo der Fehler evtl. liegen könnte oder gar
einen Lösungsansatz ?
mfg Wolfgang
Irgendwo kommt mir das alles bekannt vor, noch vom eigenen Umstieg nach
RealView...
Bei Assembler-Inlining unter RealView mit Vollzugriff auf alle Register
hilft nur noch die Einbeziehung des Embedded Assemblers. Näheres dazu
kann man der RealView Compilerbeschreibung (µVision Help oder Books
Window) entnehmen. Mit C-Sourcefiles kommt man unter RealView da nicht
mehr weiter, jedenfalls nicht ich. Man muß die
Inline-Assembler-Sequenzen zu Funktionen umbauen und in einer Datei mit
Endung ".s" unterbringen (so wie auch z.B. Startup.s oder SWI.s). Hier
wird der Zugriff auf Register, insbesondere SP, LR und PC, nicht mehr
blockiert. Du bist im Grunde nur wenig mehr als 3 ARM-Instructions von
der Lösung entfernt, und deine Idee, Sicherung der Returnadresse, ist
das A und O.
Darum poste ich mal eine vollständige Lösung als Anhang (Nested_IRQ.s),
direkt zum Einbinden ins µVision-Projekt. Sie basiert auf den Makros aus
den Hitex-Examples.
Die Funktionen brauchen jetzt 4 Byte mehr IRQ-Stack pro Schachtelung
(wegen eines zusätzlich benötigten und gesicherten Arbeitsregisters) und
etwas mehr Laufzeit (wegen des zusätzlichen Rücksprung-Handlings) als
die Makros aus den Hitex-Examples, das ist unter Umständen zu
berücksichtigen.
Die Funktionen sind auf einem Keil MCB2100 Eval-Board mit LPC2129
getestet. Trotzdem: Verwendung auf eigene Gefahr!
Ein Vorschlag zur weiteren Verbesserung ist jederzeit willkommen.
Gruß
Dietmar
Dann sag ich erstmal vielen Dank.
Ich werde es heute mal ausgiebig testen. Aber was mir auf dem ersten
Blick auffällt:
STMFD SP!, {R0} ; stelle ein Register zur Verfügung
MOV R0, LR ; sichere darin die Returnadresse
hiermit sicherst du doch eigentlich die Rücksprungadresse deines
Funktionsaufrufs ? Entweder hab ich den Sinn vom LinkRegister noch nicht
so ganz kapiert oder mir ist der Mechanismus beim ARM7 / Realview
Compiler nicht geheuer.
>STMFD SP!, {R0} ; stelle ein Register zur Verfügung>MOV R0, LR ; sichere darin die Returnadresse>hiermit sicherst du doch eigentlich die Rücksprungadresse deines>Funktionsaufrufs ?
So ist es!
>Entweder hab ich den Sinn vom LinkRegister noch nicht>so ganz kapiert
Das Problem ist hier ein ganz spezielles, da in der Funktion ein
Modewechsel statt findet. Da funktioniert das Link-Register nicht mehr
wie gewohnt, es wechselt mit der Modeumschaltung, LR_sys ist also nicht
gleich LR_irq. Deshalb muß die Returnadresse anderswie erhalten bleiben,
und wenn eben in einem anderen Register, welches nicht vom Modewechsel
abhängig ist, meinetwegen R0.
Jedenfalls benötigt man ein freies Register, entweder um die
Returnadresse direkt zu retten oder um nach der Modeumschaltung noch an
den IRQ-Stack heranzukommen, wenn man z.B. LR und R0 vorher dort
gesichert hat.
Mit dem benötigten Register (von mir gewählt: R0) bin ich noch nicht
ganz im Klaren, wo und inwieweit dessen ursprünglicher Wert erhalten
werden muß. Darauf, daß der Interrupt R0 compilerseitig sichert, kann
man nicht vertrauen, das ist stark vom Interruptcode selbst und vom
Compiler abhängig. Zur Zeit, wird R0 nur über die Nesting-Ebene hinweg
gesichert. Es ist möglich, daß der Compiler eine im Interrupt benötigte
Variable in R0 anlegt und über den gesamten Interruptverlauf hinweg
erhalten bleiben muß. Da könnte es kritisch werden, wenn die Variable
vor und hinter den Nesting-Umschaltungen benötigt wird. Sinnvollerweise
setzt man die beiden Funktionsaufrufe daher am besten ziemlich an den
Anfang und das Ende des Interruptcodes.
Ich arbeite noch daran, die beiden Funktionen dahin gehend zu
optimieren. Aber schneller, kürzer, und mit weniger Stackverbrauch, wird
die Sache dadurch sicher nicht mehr!
Danke nochmals :)
Ja das mit dem Modewechsel und verschiedenen Register war mir schon
klar, ich hatte ja das ganze schon mit dem CARM Compiler fertig und wäre
schon lang durch gewesen, aber leider musste ich feststellen, dass der
Support für diesen Compiler eingestellt wurde....
Und weil ich in einem Manual gelesen hatte, dass man eben das
Linkregister sichern muss, also das Linkregister_irq war ich irgendwie
auf der Schiene, dass hier kein Funktioncall kommen kann/darf, da ja
sonst mein Lr_Irq zerschossen wird..
Daher war mein erster Ansatz über:
register UINT_32 Lr_Reg __asm("r14"); ...
Leider konnte man beim IENABLE nur lesenden darauf zugreifen, frag mich
warum... alles andere wurde im Disassembly zu NOP oder ein kopieren von
r14 auf r14 ( sinnig.. )