Hallo! Gibt es einen "schönen" Befehl, um eine Interrupt-SR von Hand aufzurufen. Ich nutze avr-libc. Vielen Dank
Klasse! In der ersten Antwort werde ich gleich mit "Unsinn" beschimpft! Aber gut. Ich möchte die Funktionalität, die normalerweise von einem Interrupt ausgelöst wird, bei Programmstart einmalig von Hand aufrufen, damit alles in einem definierten Zustand ist. Ja, ich könnte alles in eine Funktion packen, die ich dann immer von der ISR als auch einmalig von der main() aus aufrufe. Das macht mein Programm aber unnötig langsam, denn bei jedem Interrupt habe ich einen unnötigen Funktionsaufruf und Rücksprung. Also möchte ich einmalig die ISR von Hand aufrufen (von mir aus auch, indem ich das Interrupt-Bit setze).
Wenn Du das Datenblatt des AVR's Deiner Wahl lesen würdest, wüsstest Du daß man die Interrupt Flags nur löschen, aber nicht setzen kann. Was man machen kann, ist z.B. einen Timer so zu setzen, daß er sofort überläuft und damit einen OVF Int auslöst, oder man kann einen ext. Int auslösen, indem man den Intpin als Ausgang definiert und entsprechend toggelt.
um welche architektur handelt es sich denn? es ist mithilfe von inline-asembler sicher möglich, das schön dreckig beim programmstart durchzuführen.
Bei 8051 Derivaten kannst du die Interrupts durch setzen von bits in SFR-Registern erzwingen. Ich meine das wäre das TCON Register bei 88h gewesen.
Hi mh123, Du baust eine ISR die nichts anderes macht als eine andere Funktion auzurufen, in der der eigentlich Code drin ist. Diese Funktion kannst Du dann direkt aus main aufrufen. Gruß Patrick ISR(void) -> Aufruf aus Vektortabelle { MyIsr(); } void MyIsr(void) { } void main(void) { MyIsr(); ... }
@ Patrick Der Thread-Eröffner schrieb: >Ja, ich könnte alles in eine Funktion packen, die ich dann immer von der >ISR als auch einmalig von der main() aus aufrufe. Das macht mein >Programm aber unnötig langsam, denn bei jedem Interrupt habe ich einen >unnötigen Funktionsaufruf und Rücksprung.
Dass das mit Assembler war mir klar. Deshalb habe ich nach einem schönen C-Befehl gefragt. Ich schrieb, dass ich avr-libc benutze. Es ist ein AVR. Ich schrieb, dass ich avr-libc benutze. Und ich dachte, dass die avr-libc nur für AVRs geht. Das mit der Extra-Funktion wusste ich auch schon. Das habe ich weiter oben schon beschrieben. Leider ist es weder ein externer Pin noch ein Timer. Da muss ich wohl doch einen der vielen möglichen Umwege nehmen. Da bin ich ein bisschen enttäuscht von avr-libc. Bin der sicherlich nicht der erste, der so eine Funktion gut gebrauchen kann.
Na wenn du noch genug Flash hast, musst du die Funktion zweimal schreiben, in der ISR und in der normalen Funktion. Michael
>Da muss ich wohl doch einen der vielen möglichen Umwege nehmen. Da bin >ich ein bisschen enttäuscht von avr-libc. Bin der sicherlich nicht der >erste, der so eine Funktion gut gebrauchen kann. Das sollte Dir eher ein Hinweis darauf sein, das es Gründe gibt, warum dies nicht implementiert wurde. Im Grunde ist das nur notwendig, wenn Du absolut notwendig Programmspeicherplatz sparen musst. Ansonsten kanns Du eine C-Makro verwendenn. Der Code taucht dann nur einmal in Deinem Text auf. Du kannst das Makro dann in der ISR einsetzten und ein andermal in eine Funktion einfügen.
Es geht doch! Ganz einfach sogar. Einfach den Interruptnamen als Funktionszeiger aufrufen. Also z. B. ADC_vect(); (Ich dachte zwar, ich hätte es schon erfolglos ausprobiert, aber da hatte ich mich wohl vertan.) @naja: Und, was wären diese Gründe Deiner Meinung nach? ;-)
Man kann doch eine ISR per Vector auf ne andere springen lassen. Der Overhead müsste überschaubar sein (ohne mich tiefer mit beschäftigt zu haben) Bsp. ISR(PCINT0_vect) { ... // Code to handle the event. } ISR(PCINT1_vect, ISR_ALIASOF(PCINT0_vect)); Quelle: avr-libc-user-manual.pdf Also irgend nen ungenutzten Timer etc. auslösen lassen...
Natuerlich kann man einen Interrupt von Hand aufrufen. Man braucht ja nur das passende Flag zu setzen. Um zB den timer0 Overflow Interrupt aufzurufen, braucht man das TOV0 im TIFR zu setzen
Hi, geht prinzipiell bei der AVR Architektur nicht. Es ist z.B. nicht möglich ein Flag in einem Interruptregister zu setzen, da laut Datenblatt ein Schreiben einer 1 das Flag löscht. Die einzige Möglichkeit wäre Deine Interruptroutine an den gewünschten Interruptvektor und an den SPM-Interrupt zu binden (wird meist in der Applikation nicht benötigt), dann kannst Du einmalig zur Initialisierung den SPM-Interrupt freigeben und danach gleich wieder sperren. Dadurch wird sofort Deine Interruptroutine einmal augeführt. Von dem Funktionsaufruf aus der Interruptroutine kann ich nur abraten (es sei denn es ist eine inline/static Funktion im gleichen File), da sonst der Compiler einen vollen Interruptframe erzeugt, was die Ausführungszeit unnötigerweise erhöht. Gruss
Hallo zusammen, ich würde es mit etwas Inline-Assembler über einen indirekten Aufruf versuchen: asm volatile ( "mov r30,0xHH\n\t" //High-Adresse des Interruptvektors (meistens 0) "mov r31,0xLL\n\t" //Low-Adresse des Interruptvektors "icall\n\t"::); //Indirekter Aufruf der ISR 0xHH und 0xLL bitte mit den richtigen Hex-Werte ersetzen. Die Methode funkt aber nur bis 64kWords/128kBytes Codegrösse. Die Adressen der Interruptvektoren findet man im AVR Datenblatt im Kapitel Interrupts. Würde mich über eine Anwort freuen ob es funktioniert.
mh123, Du solltest nur das klitzekleine Detail beachten, daß der Compiler für das Ende einer ISR ein RETI erzeugt, während bei einer normalen Funktion ein RET steht. Nicht daß Du Dich über merkwürdiges Verhalten wunderst :D
reti schaltet interrupts generell ein, also verwende ein cli gleich nach dem return (falls nötig!)!
>reti schaltet interrupts generell ein, also verwende ein cli > gleich nach dem return (falls nötig!) Genau das meinte ich, wollte aber dem TE das Erfolgserlebnis lassen, selbst draufgekommen zu sein, mennnooo... Alles wieder verraten ;-) Wobei ich mir nicht sicher wäre, wenn zu diesem Zeitpunkt ein Interruptflag bereits gesetzt ist, ob dort nicht wieder sofort in die nächste ISR gesprungen, oder ob eben dieses CLI abgearbeitet würde.
>Wobei ich mir nicht sicher wäre, wenn zu diesem Zeitpunkt ein >Interruptflag bereits gesetzt ist, ob dort nicht wieder sofort in die >nächste ISR gesprungen, oder ob eben dieses CLI abgearbeitet würde. Ein Befehl vom Hauptprogramm wird dann noch abgearbeitet. In dem Fall das CLI.
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.