Interrupts richtig einsetzen

Gast #462153
Lesenswert?

Schönen guten Morgen zusammen,

wollte meine Frage vom 20.12.2006 16:25 nochmal verkürzt formulieren. 
Würde gerne den ADC mit höchster Priorität durch den AIC "triggern", 
während "im Hintergrund" kontinuierlich Nebensächliche Programmschritte 
ablaufen. Häng irgendwie total fest. Was könnte ich denn Dummes 
vergessen haben oder falsch gemacht haben, bin leider blutiger Anfänger 
bzgl. µC? Welche grundsätzliche Ablauf ist bei Interrupts wichtig?

Vielen, vielen Dank auf jedenfall schon mal für eure Mühen,


euer Max
Angehängte Dateien:
#462178
Lesenswert?

Max wrote:

> bin leider blutiger Anfänger
> bzgl. µC?

Dann hätte ich nicht gleich mit nem 32Bit-Boliden mit tausendenden 
Seiten Datasheet, Usermanual, Core- und Peripheriebeschreibung 
angefangen.
Man wird sprichwörtlich erschlagen damit.
Und das Erlernen des effektiven Programmierens wird stark erschwert.


Allgemein sollte man erstmal den Core-Typ, das konkrete Derivat, den 
Compiler, die IDE nennen, denn Gedanken lesen ist anstrengend.


Ich weiß ja nicht, wie schnell der Interrupt ist, aber darin ne Divison 
auf ner CPU ohne Divisionsbefehl ist Ober-bäh.


Peter
Gast #462272
Lesenswert?

Sorry,

bei meinem ersten Eintrag hatte ich ein paar mehr Infos angefügt. Ist 
das Olimexboard SAM7-H64 mit dem AT91SAM7S64 von Atmel. Ich verwende den 
WinARM und Dev-C++ als Umgebung.
Leider MUSS ich mit dem 32bit-er arbeiten, ist ne Studienarbeit :-/ Hab 
mich schon intensiv mit dem Verhalten befasst, komm auch gut voran, nur 
eben mit diesem Interruptbereich bin ich mit meinem Latein seit en paar 
Tagen am Ende.

Die Modulo-Division wär nicht wirklich nötig, könnte ja einfach 
langsamer Interrupten und dann direkt die Fkt. aufrufen, oder?

Mit IRH_Entry und ...Exit kannst du mir nicht zufällig weiterhelfen?


VG Max
Gast #462362
Lesenswert?

Also generell kann ich wenig helfen (habe diesen uC nie benutzt)

aber:

(1) check mal deine Syntax - der Begriff "NACKEDFUNC" sollte bestimmt 
"NAKEDFUNC" heißen

(2) google mal nach "at91sam7 examples interrupt download". Gleich der 
erste Eintrag ist super

(3) In solchen Fällen erstmal Interrupts weglassen, dann das Ganze mit 
Polling zum laufen bringen, dann mit Polling aber gesetzter 
"Signal-/Statusvariable" im Interrupt und dann mit komplettem Interrupt

/ hoffe geholfen zu haben
Gast #462418
Lesenswert?

Danke schon mal für die Antworten,

wie funktioniert denn das Polling einer Fkt. genau?

... dann mit Polling aber gesetzter "Signal-/Statusvariable" im 
Interrupt?

was ist damit denn genau gemeint?


VG Max
Gast #462458
Lesenswert?

du setzt im interrupt nur eine variable, die dann anzeigt, daß ein 
interrupt aufgetreten ist (z.b. ereignis = 1) wobei die variable global 
und volatile ist

z.b.: volatile uint8_t ereignis;

in der hauptschleife wartest du dann, und reagierst, sobald sich die 
variable ändert:

while(1)
{
  while(ereignis != 1);   // warte auf ereignis == 1
  ereignis = 0;           // variable zurücksetzen

  meine_aktion();         // nun das tun, was später der INT macht
}
Gast #462510
Lesenswert?

Hab das Bsp. jetzt mal nachgebaut und in meinen Programmablauf 
integriert. Leider stehe ich nach wie vor vor dem gleichen Problem. 
Sobald der Interrupt aktiviert wird, geht gar nichts mehr, sprich ich 
käme gar nicht in die oben vorgeschlagene while(1)-Schleife :-/

Hab jetzt den ganzen Nachmittag auch mit dem Interrupt-Beispiel von 
dieser Seite gespielt, dieses ist zwar anders aufgebaut ( Triggert 
mittels TC ), aber immer noch das gleiche Problem. Die auskommentierte 
Zeile hab ich in der main-Schleife unmittelbar vor meiner 
while(1)-Schleife eingefügt.

Hab mal meine aktuelle Version angefügt?!


Mit bitte um weitere Ratschläge,

Max
Angehängte Dateien:
Gast #462797
Lesenswert?

Hallo zusammen,
hallo Philipp,

herzlichen Dank für die Nachrichten. Die main () hab ich schon 
integriert, aber nicht dem Code.txt beigefügt. Hab aber jetzt auch das 
noch mit angefügt (Neuer-Code.txt), da lösche ich doch das 
Interrupt-flag "ereignis" händisch, oder?

Kann es auch ein Timing- oder Taktproblem sein? Mein Problem ist, dass 
der ARM WEDER die Interruptroutine NOCH die main-Schleife weiter 
ausführt, sondern schlichtweg hängen bleibt, bzw. nur noch interruptet?!

Ich hoffe auf weitere gute Ideen von euch,


VG euer Max
Angehängte Dateien:
Gast #462852
Lesenswert?

Habs jetzt zum Ausschluss von Fehlern/Defekten der Hardware auf ein 
Eval-Board gespielt. da läufts komplett gleich ab.

Das Verhalten ist folgendes:

Die Main-Schleife läuft an, zunächst Initialisierungen etc. (LED1 
blinkt!). Dann kommt unmittelbar vor der while(1)-Schleife noch der 
AIC-Enable. Die Interruptfkt. wird genau ein Mal angestossen (LED2 
blinkt genau ein Mal!!!).
Dannach würde in der while(1)-Schleife die LED1 blinken, das passiert 
allerdings nicht mehr.

Warum stößt der Interrupt nur EIN MAL die Fkt. an und hängt dannach 
alles andere auf??????

Ich hoffe sehnlichst auf einen heißen Tipp ;-)

VG Max
Gast #462857
Lesenswert?

Hab mit den Fkt. ISR_ENTRY und ISR_EXIT auch schon herumprobiert. Das 
einzige, was sich verändert, ist dass er jetzt nicht mal mehr bis an die 
Stelle LED2 kommt, solange ISR_ENTRY() davor steht ???

Was ist denn genau mit __attribute__((interrupt("IRQ"))) gemeint?
Gast #462867
Lesenswert?

Aber das ändert doch eigentlich nichts an dem prinzipiellen Problem, 
dass er nur einmal in die durch den Interrupt aufgerufene Fkt. geht und 
in dieser lediglich den ersten Befehl (LED2 Ein-Aus) abarbeitet, obwohl 
nachfolgend lediglich dieser Befehl wiederholt wird?
Gast #462888
Lesenswert?

Und an welcher Stelle werden genau die Register gesichert? Ist doch noch 
im Bereich der AIC-Initialisierung, oder? Mich wundert, dass die Fkt. 
nicht mal zu Ende gearbeitet wird, die der Interrupt aufruft.
Zumindest müsste dass aber doch bei jedem neuen Interrupt bis zu der 
Stelle ständig wiederholt laufen?!

Verhalten:
LED1 blinkt 4 mal ( Inits OK?! ), danach nur EIN EINZIGES MAL KURZ LED2 
( Interrupt kommt nur einmal und hängt dann? )

Das momentane Code-Bsp. hab ich nochmal angefügt!
Gast #462898
Lesenswert?

Um mal Peter zu zitieren: "Dann hätte ich nicht gleich mit nem 
32Bit-Boliden mit tausendenden Seiten Datasheet, Usermanual, Core- und 
Peripheriebeschreibung angefangen."

Dir fehlen elementare Grundlagen der Interrupt-Programmierung, 
entsprechend betreibst du dabei Blindflug.

Es ist sehr hilfreich, wenn man mal Interrupts in Assembler programmiert 
hat. Dann erschliesst sich einem der Sinn von dem ganzen Zirkus mit 
__attribute__((interrupt("IRQ"))), __attribute__((naked)), ISR_ENTRY() 
usw nämlich erst so richtig. Nur sollte man damit nicht grad beim ARMs 
beginnen.

Eine Interrupt-Routine muss alle benutzten Register vor Verwendung 
sichern. Entweder indem die Routine als solche gekennzeichnet wird 
__attribute__((interrupt("IRQ"))) oder indem man dem Compiler sagt, dass 
man alles selber macht __attribute__((naked)) aka NAKEDFUNC und das dann 
mit ISR_ENTRY/EXIT auch an der richtigen Stelle macht. Sehr hilfreich 
kann es dabei sein, den entstehenden Assembler-Code zu verstehen.
Gast #462901
Lesenswert?

Danke dennoch für deine Antworten,

leider werde ich vom ARM nicht loskommen, ist nun mal ne vorgegebene 
Studienarbeit. Mit Assembler hatte ich in der Tat noch nie etwas zu tun. 
Gibt es da gerade im Hinblick auf Interrupts Bsp., über die man sich 
langsam herantasten kann?

Brauch ja ne vernünftige Beschäftigung während den Feiertagen ;-)

Frohes Fest,

Max
Gast #462945
Lesenswert?

mal ein hinweis:

wie oft feuert denn dein timer interrupt pro sekunde ?

deine ereignisfunktion/int-handler ist ja voller warteschleifen... das 
sollte man in einer interruptfunktion unbedingt vermeiden

mach es lieber so, daß der interrupt alle paar hundert ms feuert, und du 
in der ereignisfunktion/int-handler nur den pin umschaltest

also in etwa so ein verhalten:

  - int kommt: led aus
  - int kommt: led an
  - int kommt: led aus

usw.
Gast #462964
Lesenswert?

Danke für die Antwort,

die Delays sind lediglich aufgrund meiner 1000 Versuche, das Ding zum 
Laufen zu bringen, hinzugekommen ;-) Die Brauch ich später auch nicht. 
Der TC wird mit MCK/1024 betrieben ( MCK ~ 48MHz ), dieser hat einen 
16bit Counter. Immer bei Inkrementierung sollte der interrupten. Da komm 
ich auf so ca. 1,4 sec.

Mit Pin-Umschaltung wird auch lediglich der aller erste Interrupt 
angestoßen?!

VG Max
Gast #462980
Lesenswert?

ach übrigens:

viele übersehen wichtige Parameter des Timers, da diese oftmals mehrere 
Funktionen zur Verfügung stellen.

Deshalb ist es immer sinnvoll in solchen Fällen das Kapitel über den 
Timer im Datenblatt nochmal durchzugehen:

Wichtige Stichpunkte: Überlaufverhalten, Interrupt-Maske etc.

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