void Messdaten_RISING()
{
const int AL = 50; // Arraylänge
static unsigned long Data_RISING[AL];
static unsigned int Index = 0;
Data_RISING[Index] = micros();
Index++;
Allerdings ist damit nichts volatiles geschütztes mehr im Spiel. Nun möchte ich wissen
a) ist das ein Problem?
b) wird die Funktion im ISR wegoptimiert, da nicht volatile?
c) ist der Funktionsaufruf aus der ISR heraus immer noch während die Interrupts abgeschalten sind?
Sollte eigentlich so sein. Der ISR Vector ist doch erst fertig wenn er vom Funktionsaufruf wieder zum ISR Vector zurückgekehrt ist. Damit wäre laut meiner Überlegung ein Atomic Block hier nicht nötwending. Oder?
Natürlich müssen deine statischen Variablem volatile deklariert werden.
Ob statisch+lokal oder global... voll egal... Einzig die Sichtbarkeit ist anders.
Natürlich wird das Interruptflag erst am Ende ISR wieder frei geschaltet.
Es sei denn, du legst selber Hand an.
Dann musst du allerdings deine ISR, und deine Funktion, wiedereintrittsfähig gestalten.
aha verstehe, ist nur ein anderer Betrachtungswinkel und die Variablen stehen woanders.
Also alle Variablen die mit einer ISR auch nur im entferntesten in Berührung kommen müssen volatile sein?
Das mit dem Flag mache ich mir gleich zu nutze und verzichte in dem Fall auf ein extra atomic.
Vielen Dank.
Die Funktion selbst kann man nicht gleich als ganzes volatile definieren? Mal ganz doof gefragt.
Was du zeigst, ist die ISR (Interrupt Service Routine), der ISR Vector (ein Tabelleneintrag) ist immer gleich lang.
Korrekte Bezeichnungen sind wichtig!
Meine Ausführungen beziehen sich nur auf die Schnipsel die du da präsentierst.
Deine statischen Variablen sind ausserhalb der ISR nicht sichtbar, brauchen also kein volatile.
Da die Variablen aber ausserhalb der ISR nicht sichtbar sind, kannst du sie auch weglassen.
a) ausser dem oben genannten Problem: nein
b) nein (aber du würdest den Unterschied ja nur im Timing sehen können)
c) ja
ja war blöd mit dem falschen Namen, aber ihr denkt ja mit.
Jetzt widerspricht sich leider deine Aussage mit der von combie wegen dem volatile. In meinen Augen.
Anders formuliert. Wenn alle Variablen in der ISR Routine innerhalb dieser bleiben, was in dem Fall auch die Funktion betrifft, weil da nichts globales im Spiel ist, dann kann man volatile weglassen. Schadet aber auch nicht volatile zu verwenden. Würde nur den Compiler an eventuellen Optimierungen hindern.
Man muß das gedanklich betrachten als stände die Funktion in der ISR Routine.
Soweit richtig?
Sobald eine globale Variable in die ISR Routine kommt, dann müssen alle volatile gemacht werden. Ebenso wie combie schreibt. Soweit richtig?
Alle von der ISR und dem nicht-ISR Kode benutzten Variablen müssen volatile sein,
Variablen von mehr als einen Byte müssen im nicht-ISR Kode bei abgeschalteten Interrupts gelesen oder geschrieben werden.
ich glaube ich habs verstanden. Das mit dem "benutzte Variablen in ISR Code und außerhalb müssen volatile sein" mache ich schon länger. Ich war mir mit den lokalen in der ISR Routine nicht im klaren. Aber klar, ist ja lokal. Wir belassen es mal dabei. Alles weitere würde wieder mehr verwirren.
du willst mich jetzt auf den Arm nehmen.
Oder soll ich das aus meiner Sicht wirklich nochmal erklären, zum Test?
Dann möchte ich anschließend ein Zeugnis.
Variante 2. Warum denke ich das es volatile sein muß? Ich denke das deshalb, weil die Variablen im Funktionsaufruf() jederzeit durch die ISR Routine unerwartet verändert werden können. Die loop könnte mit dem Funktionsaufruf arbeiten und plötzlich schlägt die Interrruot Routine zu und verändert extra nochmal. Okay, dass steht so nicht da.
Nochmal. Variante 2 so wie sie oben steht, muß kein volatile rein. Weil es nur von der ISR Routine genutzt wird.
#include <util/atomic.h> // für cli() und sei() mit SREG Sicherung
#include <avr/interrupt.h>
void setup() {
// set_ISR_Register();
}
void loop() {
} // end of loop
/* *** Funktionen *** */
ISR(INT4_vect) // ISR Service Routine
{
Funktionsaufruf();
}
void Funktionsaufruf()
{
int temp = 0;
// Code mit temp
}
wenn jetzt die loop auch noch mit dem Funktionsaufruf arbeiten soll, dann muß volatile rein.
#include <util/atomic.h> // für cli() und sei() mit SREG Sicherung
#include <avr/interrupt.h>
void setup() {
// set_ISR_Register();
}
void loop() {
Funktionsaufruf();
} // end of loop
/* *** Funktionen *** */
ISR(INT4_vect) // ISR Service Routine
{
Funktionsaufruf();
}
void Funktionsaufruf()
{
volatile int temp = 0;
// Code mit temp
}
Nein. Funktionslokale Variablen müssen niemals volatile sein, da sie nach dem Funktionsaufruf nicht mehr existieren.
Auf Grund ihrer lokalen Definition können sie von der ISR nicht benutzt werden, die ISR kann sie einfach nicht sehen.
Alle von der ISR und dem nicht-ISR Kode gleichzeitig benutzten Variablen müssen volatile sein.
dass die ISR die lokalen Variablen der Funktion erstmal nicht sehen kann, leuchtet mir ja ein. Aber wenn die Funktion wie im letzten Bsp. von der ISR und von loop genutzt wird, dann greifen beide gleichzeitig darauf zu in meinen Augen. Wobei ... 'grübel' .... nur die Funktion selbst letztlich ihre lokale Variable verändern kann. Egal wer sie aufruft. Auch wieder wahr. Dann sind wir wieder auf Anfang. Dann müssen nur Variablen volatile sein, die global deklariert sind und in der ISR geändert werden. Wenn der letzte Satz absolut wahr ist, dann hatte ich eine sehr große Denkschleife.
Selbst wenn funktionsaufruf() sowohl in der ISR wie in loop verwendet wird, und also eventuell parallel mehrfach läuft und sich selbst überrholt, gibt es unterschiedliche lokale Variable, die ausser dem Namen temp nichts gemein haben. (Damit du was zum Grübeln hast)
Wenn funktionsaufruf() sowohl in der ISR wie in loop verwendet wird, solltest du übrigens gaaaanz genau wissen, was du da machst, insbesondere wenn diese Funktion mit gemeinsamen statischen oder globalen Variablen arbeitet.
Die Grundregel: "ISR so einfach wie möglich" ist schonmal nicht eingehalten
Dann müssen nur Variablen volatile sein, die global deklariert sind und in der ISR geändert werden. Wenn der letzte Satz absolut wahr ist, dann hatte ich eine sehr große Denkschleife.
Sieht wohl so aus.
"in der ISR" heisst natürlich eigentlich "in der ISR oder von dort aufgerufenen Unterfunktionen". Da scheinst du gedanklich fälschlich noch ein bisschen zu unterscheiden ?
erster Absatz:
die sind deshalb unterschiedlich, weil temp nicht statisch ist, wird mit jedem Funktionsaufruf neu erstellt. Wenn temp statisch wäre, wäre temp immer die gleiche.
zweiter Absatz:
ja, das ist gefährlich, ich denke ich weiß was ich tue. Ich möchte im Interrupt einen Zeitwert (millis/micros) in ein Array schreiben. Wenn das voll ist, sperre ich gezielt nur meine 2 Pin Interrupts, nicht global. Dann werte ich das Array in Ruhe aus, wenn fertig, setze ich die Pin Interrupts wieder scharf und das Spiel geht von vorn los. Das funktioniert auch schon. Muß das nur nochmal genauer verifizieren ob wirklich alles okay ist. Beide Arrays werden später noch miteinander zeitlich sortiert ausgegeben. Wird ein kleiner Datalogger, eine Art kleiner Logikanalyzer. Das zur näheren Erklärung.
ISR(INT4_vect) // ATmega2560
{
if (state_Logging == true) {
Data_RISING[Index_R] = micros();
Index_R++;
}
if (Index_R >= AL) {
dis_INT_ISR_Register(); // selbst disabled
state_Logging = false;
}
}
ISR(INT5_vect) // ATmega2560
{
if (state_Logging == true) {
Data_FALLING[Index_F] = micros();
Index_F++;
}
if (Index_F >= AL) {
dis_INT_ISR_Register(); // selbst disabled
state_Logging = false;
}
}
dritter Absatz:
Ich glaube direkt falsch ist meine Aussage nicht. Nur nicht vollständig mit deinem Argument. Das sind nun 2 verschiedene Dinge gewurden, meine ich. Ich formuliere neu.
Wenn man eine reine nackte Unterfunktion aus der ISR aufruft, dann müssen darin die lokalen Variablen nicht volatile sein. Sobald die ISR bei sich selbst eine Variable ändert die nach außen sichtbar ist, meistens dann global ist, dann muß diese volatile sein. Ob diese volatile Variable nun in einer anderen Funktion oder in der loop Verwendung findet spielt keine Rolle. Man sollte zusätzlich den atomaren Zugrif beachten.
Doc_Arduino:
Sobald die ISR bei sich selbst eine Variable ändert die nach außen sichtbar ist, meistens dann global ist, dann muß diese volatile sein.
Ob diese volatile Variable nun in einer anderen Funktion oder in der loop Verwendung findet spielt keine Rolle.
Nicht ganz.
Nur wenn sie von nicht-ISR Kode benutzt werden müssen sie volatile sein.
jetzt mal ehrlich. Habe ich das nicht genauso formuliert wie du meinst? Ich sehe keinen Unterschied mehr in der Formulierung. Ich wollte es nun wirklich allen recht machen.