So noch einmal eine Frage zum Einbinden von Assembler-Funktionen in C-Programmen... Welche Register sollte mann in asm-Interrupt-Routinen verwenden? Und kann man falls nötig benötigte Register einfach pushen und popen? Ich suche jetzt schon bald den ganzen Tag nach dem Fehler in der Funktion im Anhang. Kann mir jemand mal auf die Sprünge helfen. Meine Orginalfunktion die ich in einem reinem Assembler-Programm benutze funktioniert super. Anscheinend habe ich bei der Umsetzun in eine C-taugliche Funktion irgendwo einen Bug drin. Ich bin da noch ziemlich neu auf dem Gebiet... Beschreibung: Die Interrupt Funktion decodiert die Positive-Flanke des Manchester-codierten Signals (Positive Flanke am Eingang).Es gibt auch noch das Gegenstück, eine Funktion die auf die negative Flanke reagiert.Eigentlich funktioniert das Programm, bis zu einen gewissen Zeitpunkt. Leider stimmt ab circa der neunten Flankenauswertung das Ergebnis nicht mehr. Im AVR-Studio debugge ich das Programm. Allerdings kommt da immer das richtige Ergebnis raus. Meine Vermutung ist ja, dass es irgendwann die globale Variable FlankeFlg zerlegt :-(.... Implementierung in C-Main: volatile extern void SIG_INTERRUPT (void); unsigned char FlankeFlg; void main (void) {......} Ich hab' die Assembler Dateien mit xxx.S eingebunden.... Danke schoen, bluemole PS:Hab' schon ziemlich viel rumprobiert, daher schaut die Funktion ein bisschen unkoordiniert aus.
Natürlich mußt Du in Deiner ISR alle Register retten, einschließlich
SREG. Du kannst ja nie wissen, wann der Interrupt zuschlägt.
Schreibe am besten eine ISR in C und sieh Dir den generierten
Assemblercode an, dann hast Du ein Gerippe.
So komplex wie Deine ISR ist, kannst Du sie vermutlich effektiver
gleich in C schreiben. Was ist denn der Grund für Assembler?
> volatile extern void SIG_INTERRUPT (void);
Wofür soll das denn gut sein?
Der Grund ist ziemlich einfach. Ich habe bisher nur in Assembler die
Atmels programmiert. Daher habe ich ziemlich viele Assembler-
Funktionen, die ich weiterhin benutzen will ohne sie erst aufwendig in
C zu übersetzen.
>volatile extern void SIG_INTERRUPT (void);
volatile
ich will nicht, dass der Compiler die Funktion SIG_INTERRUPT zu
aggressiv optimiert. Aber wie gesagt, ich hab' zu diesem Zeitpunkt
dann schon viel rumprobiert.
Ansonsten ist doch der Aufruf völlig normal, oder?
PS: Die Funktion läuft immer noch nicht ordentlich...
> Der Grund ist ziemlich einfach. Ich habe bisher nur in Assembler die > Atmels programmiert. Daher habe ich ziemlich viele Assembler- > Funktionen, die ich weiterhin benutzen will ohne sie erst aufwendig > in C zu übersetzen. Vermutlich wäre das komplette Neuschreiben in C in einem Zehntel der Zeit getan, die Du zum Debuggen der Assemblereinbindung brauchst. > ich will nicht, dass der Compiler die Funktion SIG_INTERRUPT zu > aggressiv optimiert. Du hast den Sinn von `volatile' überhaupt nicht verstanden. > Ansonsten ist doch der Aufruf völlig normal, oder? Sorry, erstens ist es kein Aufruf, sondern eine Deklaration, und zweitens fürchte ich, daß sie einfach nur völliger Unsinn ist (der aber zum Glück bloß ignoriert wird). > PS: Die Funktion läuft immer noch nicht ordentlich... Klar, wenn Du Dir nicht die Mühe machst, die benutzten Register zu retten, wird sie auch nicht richtig laufen können.
T'schuldigung für mein volatile Mist und meinem Interrupt Aufruf. Aber in der Not hat man die lustigsten Ideen Meine Interrupt-Funktio läuft :-). Ich hab'mir mal eine leere Interrupt-Funktion übersetzen lassen. Da wird eigentlich nur das Statusregister und die benutzten Register (r0 und r1) gepusht. Ok nach dem Schema hab' ich meine Funktio dann auch gebastelt. Funktionierte dann immer noch nicht. Erst als ich dann den Funktionsaufruf rcall serout (Anzeige des empfangenen Bits) eleminiert habe ging's. Komisch ist es, wenn der ein ganzer Datenstrom empfangen wurde gebe ich alle drei empfangenen Bytes testhalber auch aus der Interrupt-Funktion mittels rcall serout aus und es funktioniert einwandfrei... Irgendwie scheint da noch der Hund begraben. Daher noch eine Frage. Wie rufe ich aus einer Interruptroutine eine andere Assembler-Funktion auf. Mein Code Aufruf aus Assembler- Interrupt- Funktion: ldi r24,0xAA // r24 Übergabe register 0xAA Test Byte rcall serout Assembler-Code serout: #define temp r24 .... serout: sbis UCSRA,UDRE rjmp serout out UDR,temp ret .endfunc Danke... Ich rette nun das Statusr
>Wie rufe ich aus einer Interruptroutine eine andere >Assembler-Funktion auf. Ganz normal - so wie Du es machst ist es schon ok. Aber hast Du alle verwendeten Register von serout auch (auf dem Stack) gerettet? R24? ALLE Register, die innerhalb eines IR angefasst werden, müssen vorher auf dem Stack gesichert werden. Sonst bekommst Du (ev. nur ab und an) hässliche Fehler. Ist Dein Stack groß genug definiert? >serout: >sbis UCSRA,UDRE >rjmp serout Das ist innerhalb eines IR nicht besonders schön. Der IR wartet solange, bis der UART wieder frei ist. D.h. Du blockierst Dein System für mehrere ms, auch für andere IR. Stefan
Ja ich weiß, dass das mit der Wartezeit in serout nicht so toll ist. Aber zum Debuggen hat mir die Funktion schon oft sehr große Dienste geleistet. Hier scheint sie mir echt einen Strich durch die Rechnung gemacht zu haben. Das Register 24 rette ich schon am Anfang der Interrupt-Funktion. Also brauche ich es nicht ein zweites mal zu retten, oder doch? Ist die Funktion serout wirklich so langsam. Vielleicht entsteht ja wirklich irgendwie ein Laufzeitfehler. Also ein Bit kommt alle 1000us Sekunden an. Somit wird alle 1ms ein Byte '1' oder '0' zum veranschaulichen am PC ausgegeben. Das müsste doch die USART-Schnittstelle mit 9600kBaud locker schaffen. Wenn ich mich nicht irre. 9600kBaud == 9600 Bits pro Sekunde Das heißt maximal könnte ich alle...rechne 1/9600*Bit/s = 0.000104 s/Bit also pro 100us ein Bit verschicken... Moment ein Bit.... Ich verschicke ein Byte also 8* 100us = 800 us werden für ein Byte benötigt... Ok, kann knapp werden.....
Doppelt sichern musst Du R24 nicht, wenn die IR-fkt. das nicht erfordert. Vergiss Start/Stopbit nicht, unter 10 Bit geht (fast) nichts. Wie langsam serout ist, hängt rein von der Baudrate ab. Stefan
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.