Interrupt von Hand aufrufen

Gast #1400580
Lesenswert?

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).
Gast #1400590
Lesenswert?

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.
Gast #1400644
Lesenswert?

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.
Gast #1400652
Lesenswert?

>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.
Gast #1400684
Lesenswert?

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...
Gast #1400705
Lesenswert?

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
Gast #1400800
Lesenswert?

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.
Gast #1400902
Lesenswert?

>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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren