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
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
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
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
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
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
}
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
Je nach Controller und Compiler kann es erforderlich sein, ein
Interrupt-Flag nach dessen Abarbeitung händisch zu löschen. Vielleicht
müsste das noch rein.
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
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
Warum eigentlich NAKEDFUNC/ISR_ENTRY statt des dafür vorgesehenen
__attribute__((interrupt("IRQ")))? Letzteres hatte zwar früher einen
Bug, sollte heute aber ok sein.
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?
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?
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!
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.
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
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.
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
>Mit Pin-Umschaltung wird auch lediglich der>aller erste Interrupt angestoßen?!
Der Interrupt wird durch den Timer ausgelöst, und die Interrupt-Routine
(bei Dir "Ereignisfunktion") toggelt die LED.
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.