Hallo
Ich habe zur zeit folgendes Problem mit einem AT91SAM7X256.
Ein externer Interrupt wird jede ms ausgelöst und in der ISR werden ein
paar Berechnungen durchgeführt. Grundsätzlich funktioniert das, aber
unter bestimmten Umständen tritt irgendein Problem auf, das bewirkt,
dass meine ISR nicht mehr aufgerufen wird - der Controler selber läuft
einwandfrei weiter. Nach ein paar Tests habe ich herausgefunden, dass es
offenbar mit der Abarbeitungszeit der ISR zu tun hat. Kommentiere ich
hierin Code aus, oder vergrößere das Intervall, in dem der Interrupt
feuert, dann funktioniert wieder alles wie es soll.
Ich kann das Problem jetzt also umgehen, indem ich den Interrupt nur
alle 2 ms statt jede ms feuere und die ISR selber etwas aufräume, sodass
sie schneller abgearbeitet werden kann, aber das ist etwas
unbefriedigend für mich, weil ich nicht genau verstehe, was hier schief
läuft.
Kann mir jemand von euch erklären, wie dieses Problem zu Stande kommt
oder ob ich vielleicht irgendwo einen Fehler gemacht habe?
Das Ganze läuft übrigens unter FreeRTOS.
Ist doch ganz klar: Deine Interrupts passieren schneller, als sie
abgearbeitet werden können. Das kann doch nicht funktionieren. Also
Berechnungen aus der ISR verlagern und in der ISR beispielsweise nur ein
Flag setzen.
AIC_EOICR wird ganz am Ende geschrieben und das nur mit deaktivierten
Interrupts. Kann sein, dass das alles gegeben ist, aber ich würde
erwarten, dass das der eigentliche Interrupt-Handler (ARM7 hat ja nur
einen, plus einen fürs FIQ) macht.
Also, ich weiß nicht wie das mit FreeRTOS aussieht, dazu noch in
Kombination mit der Atmel at91lib (? sieht mir zumindest von den
Definitionen so aus), aber das EOICR im Handler scheint mir suspekt.
Nico Sch. schrieb:> Ist doch ganz klar: Deine Interrupts passieren schneller, als sie> abgearbeitet werden können. Das kann doch nicht funktionieren.
Nach meinem Verständnis führt das aber "nur" dazu, das zwischendurch
Interrupts verloren gehen und nicht, dass ich gar keinen mehr
mitbekomme. Oder liege ich hier schon falsch?
Wie gesagt kann ich das Problem ja bereits umgehen, aber ich möchte
gerne genau verstehen, warum es auftritt, um dann entscheiden zu können,
ob meine "Lösung" wirklich eine ist, oder ob eine andere nicht
vernünftiger wäre.
> The nIRQ line can be asserted only if an interrupt condition occurs on an> interrupt source with a higher priority. If an interrupt condition happens (or> is pending) during the interrupt treatment in progress, it is delayed until the> software indicates to the AIC the end of the current service by writing the> AIC_EOICR (End of Interrupt Command Register). The write of AIC_EOICR is the> exit point of the interrupt handling.
Wenn ich am Ende der ISR nicht in AIC_EOICR schreibe, dann wird die ISR
nur ein einziges mal aufgerufen. Das ist also leider keine Lösung :/
Das habe ich so auch in Beispielen zu FreeRTOS gesehen.
Teakep schrieb:> Wenn ich am Ende der ISR nicht in AIC_EOICR schreibe, dann wird die ISR> nur ein einziges mal aufgerufen. Das ist also leider keine Lösung :/> Das habe ich so auch in Beispielen zu FreeRTOS gesehen.
Ich kenne die Implementierung von FreeRTOS nicht, deshalb war mein
Verdacht, dass EOICR zweimal geschrieben wird. Denn wegen des einzigen
normalen Interrupts, den die ARMs ausser Cortex-M bieten, läuft ja alles
über einen einzigen System-Interrupt-Handler, der dann wiederum je nach
aufgetretenem externen Interrupt den eigentlichen Handler aufruft.
Normalerweise macht dann dieser System-Handler den ganzen Zyklus: Lesen
AIC_IVR, Reaktivieren Interrupts, Aufruf des eigentlichen Handlers,
Deaktivieren Interrupts, Schreiben AIC_EOICR.
Wenn das in FreeRTOS anders läuft, auch gut. Nur müssen die Interrupts
definitiv deaktiviert sein bevor EOICR geschrieben wird und innerhalb
des restlichen Handlers nicht wieder reaktiviert werden.