Forum: Compiler & IDEs Interrupt und volatile - ich versteh's nicht.


von Manuel (Gast)


Lesenswert?

Hallo,

ich programmiere eine MSP430 und habe nun das Problem, dass ich in einer 
Interruptroutine eine andere Funktion aufrufe - dort aber ein VOLATILE 
flag setze, damit sie nicht nochmal beim nächsten Interrupt aufgerufen 
wird.
Soweit sollte das ja gehen. Nur der Zustand des Flags in der ISR und in 
der Funktion unterscheiden sich! Trotz VOLATILE... ich versteh's nicht 
:-(

Gruß

Manuel

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Codebeispiel?

Sind weitere Interrupts gesperrt, wenn die Folgefunktion läuft? Wenn 
weitere Interrupts kommen können, ändern die vielleicht das Flag. 
Volatile besagt zunächst mal nur, dass flag stets "frisch" zu holen ist 
und nicht vom Compiler in Registern vorgehalten werden darf. Für eine 
interruptfeste Programmierung bei reentranten Funktionen reicht das noch 
nicht.

von Manuel (Gast)


Lesenswert?

Hallo,

der Code ist ein bisschen lang zum posten - sieht aber so aus:

volatile BOOL scanning;


TIMER ISR(){

   if (!scanning){
      passiveChannelScan();
   }
}


void passiveChannelScan(){
   scanning = TRUE;


   ..... (dauert oft länger als der Timer)

   scanning = FALSE;
}

Wie gesagt, ich habe mir eine Ausgabe erzeugt, wenn scanning auf FALSE 
gesetzt wird - passiert nie - aber in der ISR ist es auch nie TRUE...

Gruß

Manuel

von Norgan (Gast)


Lesenswert?

Assemblercode des Compilers ausgeben lassen. Ansehen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ganz davon abgesehen ließe sich das Ganze komplett so umschreiben:
1
TIMER ISR(){
2
   passiveChannelScan();
3
}
4
5
6
void passiveChannelScan(){
7
   static BOOL scanning;
8
   if (scanning) {
9
      return;
10
   }
11
   scanning = TRUE;
12
13
14
   //..... (dauert oft länger als der Timer)
15
16
   scanning = FALSE;
17
}

von Manuel (Gast)


Lesenswert?

Hallo Jörg,

mit dem static funktioniert's dann - aber ich versteh nicht warum... Es 
sollte doch mit volatile auf das selbe rauslaufen...
Warum geht eigentlich "extern static" foo nicht?

Gruß

Manuel

von Stefan B. (stefan) Benutzerseite


Lesenswert?

extern static widerspricht ziemlich dem Konzept eines static.

Deine Frage lässt aber auf eine mögliche Problemursache im OP 
schliessen: Hast du vielleicht die ISR und die Funktion in getrennten 
Modulen/Quelldateien?

Dann könnte es sein, dass in beiden Dateien unbeabsichtigterweise 
unterschiedliche Variablen scanning angelegt sind z.B. durch ein 
fehlendes oder unglückliches extern.

von Manuel (Gast)


Lesenswert?

extern bedeutet doch nur, dass die variable in einer anderen .c datei 
definiert ist. Was soll da gegen static spechen?
Versteh ich nicht. Scanning gibts bei mir nur einmal (und ich greife 
auch nicht von anderen Funktionen darauf zu)... aber wenn ich's als 
extern volatile definier, dann gibts Probleme...

Immernoch am rätseln...

von Norgan (Gast)


Lesenswert?

> mit dem static funktioniert's dann - aber ich versteh nicht warum.

Assemblercode des Compilers ausgeben lassen. Ansehen.

Huch, sagte ich das nicht schon mal? Na ja, ist halt einfacher andere 
Leute mit den eigenen Problemen zu betrauen, statt mal in den eigenen 
Code zu sehen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Manuel wrote:
> extern bedeutet doch nur, dass die variable in einer anderen .c datei
> definiert ist. Was soll da gegen static spechen?

Dass `static' auf der obersten Dateiebene (auf der alle Variablen
immer mit statischem Speicherplatz angelegt werden) eben etwas
anderes bedeutet als statische Speicherzuordnung: es bedeutet, dass
die dergestalt deklarierten Variablen privat für diese Datei werden
(genauer: für diese Übersetzungseinheit).  Das beißt sich logischerweise
mit “extern”, das ja einen globalen Zugriff (über alle Übersetzungs-
einheiten hinweg) erreichen will.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Manuel wrote:
> extern bedeutet doch nur, dass die variable in einer anderen .c datei
> definiert ist. Was soll da gegen static spechen?
> Versteh ich nicht. Scanning gibts bei mir nur einmal (und ich greife
> auch nicht von anderen Funktionen darauf zu)... aber wenn ich's als
> extern volatile definier, dann gibts Probleme...
>
> Immernoch am rätseln...

Wenn  das heisst dein Projekt sieht so aus und bei der beschriebene 
Fehler tritt auf...

Datei lolek.c
1
volatile BOOL scanning;
2
3
TIMER ISR(){
4
   if (!scanning){
5
      passiveChannelScan(); // #1
6
   }
7
}

Datei bolek.c
1
extern volatile BOOL scanning;
2
3
void passiveChannelScan(){
4
   scanning = TRUE;
5
   // ..... (dauert oft länger als der Timer)
6
   scanning = FALSE;
7
}

...dann kann ich nur den Hinweis von Norgan unterstützen.

Vielleicht ist es auch nur ein Mistverständnis beim Debuggen bzw. beim 
Programmablaufverständnis. Oben hatte ich ja schon mal nach *gesperrten 
Interrupts* gefragt. BEim AVR wäre es beim obigen Code so, dass während 
der Abarbeitung von TIMER ISR (hat dort anderen Namen) und dem daraus 
aufgerufenen passiveChannelScan() weitere Interrupts gesperrt wären! 
Dann kann in TIMER ISR scanning nur den Wert FALSE haben!

von Andreas K. (a-k)


Lesenswert?

Manuel wrote:

> Was soll da gegen static spechen?

Weil das ungefähr so klingt wie "extern intern" oder "oben unten".

von Manuel (Gast)


Lesenswert?

Hallo,

das Problem scheint zu sein, dass falls ein 2. Interrupt auftritt und 
den 1. Interrupt unterbricht (beim msp430 timer geht das) kehrt der 1. 
nicht mehr zurück sondern beendet beide ISR. Weiß der Geier warum... 
Scheiß MSPs - ich will wieder ATMELs!

Manuel

@Andreas: Das ist kein Widerspruch - in vielen Programmiersprachen geht 
das. Warum unter gcc nicht, versteh ich immer noch nicht...

von Karl H. (kbuchegg)


Lesenswert?

Manuel wrote:
> Hallo,
>
> das Problem scheint zu sein, dass falls ein 2. Interrupt auftritt und
> den 1. Interrupt unterbricht (beim msp430 timer geht das) kehrt der 1.
> nicht mehr zurück sondern beendet beide ISR. Weiß der Geier warum...

Das klingt nicht sehr logisch. Wenn dem tatsächlich so ist, dann
ist irgend etwas gröber faul. Entweder in deinem Programm oder im
Compiler.

> @Andreas: Das ist kein Widerspruch - in vielen Programmiersprachen geht
> das. Warum unter gcc nicht, versteh ich immer noch nicht...

Sorry, aber das ist Unsinn.
Entweder eine Variable ist in ihrer Sichtbarkeit auf einen Bereich
eingeschränkt (und genau das macht das static) oder es ist global
sichtbar (und kann daher mittels extern von überallher referenziert
werden). Aber 'eingeschränkt sichtbar' und 'von überallher ansprechbar'
widersprechen sich nun mal.
'extern static' wäre in der Sprache der Pferdezüchter ein 'schwarzer
Schimmel'

Und das hat auch nichts mit gcc zu tun. Das ist in der Sprachdefinition
von C so festgelegt.

von Manuel (Gast)


Lesenswert?

OK - ich vergrab mich mal besser... sorry für die missverständnisse...

von Andreas K. (a-k)


Lesenswert?

Manuel wrote:

> @Andreas: Das ist kein Widerspruch - in vielen Programmiersprachen geht
> das. Warum unter gcc nicht, versteh ich immer noch nicht...

Die Verwirrung rührt vielleicht daher, dass "static" im Grunde zwei 
unterschiedliche Bedeutungen hat, je nachdem wo du es verwendest. 
Innerhalb einer Funktion ist es eine Speicherklasse, ausserhalb einer 
Funktion definiert es die Sichtbarkeit.

von Christian R. (supachris)


Lesenswert?

Manuel wrote:
> Hallo,
>
> das Problem scheint zu sein, dass falls ein 2. Interrupt auftritt und
> den 1. Interrupt unterbricht (beim msp430 timer geht das) kehrt der 1.
> nicht mehr zurück sondern beendet beide ISR. Weiß der Geier warum...
> Scheiß MSPs - ich will wieder ATMELs!

Unsinn. Die ISR wird nur unterbrochen, wenn du selbst explizit den GIE 
wieder frei gibst. Nennt sich dann verschachtelte Interrupts. 
Standardmäßig deaktiviert der Compiler aber das GIE beim Einsprung in 
die ISR. Siehe hier: http://mspgcc.sourceforge.net/manual/x580.html
Wenn deine Interrupts durcheinander kommen, liegt das am Programmierer.
Ich arbeite täglich mit dem MSP430 und verschachtelten Interrupts und da 
kehrt der immer in die zuletzt unterbrochene ISR zurück.

von Matthias L. (Gast)


Lesenswert?

@ supachris:

>Ich arbeite..

Ich denke, du bist am Institut?  ;-))


**duck und weg**

von Kopfkratzer (Gast)


Lesenswert?

Also ich lege grundsätzlich globale Variablen in Header Dateien an.
Lediglich lokale Laufvariablen, wie das geliebte i, i2, i3 usw. kommen 
direkt in Routinen.
Das ist doch mit der Sinn einer Headerdatei, oder ?
kopfkratz

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Kopfkratzer wrote:
> Also ich lege grundsätzlich globale Variablen in Header Dateien an.
> Lediglich lokale Laufvariablen, wie das geliebte i, i2, i3 usw. kommen
> direkt in Routinen.
> Das ist doch mit der Sinn einer Headerdatei, oder ?
> *kopfkratz*

Anlegen... Altes Thema
"Was ist der Unterschied zwischen Deklaration und Definition?"

Wenn du mit Anlegen eine Deklaration meinst, bist du auf dem 
richtigen Weg. Die globalen Variablen sollen über die Includedatei im 
ganzen Programm bekanntgemacht werden.

Typ. in einer *.h Datei
1
// DEKLARATION
2
// Namen bekanntmachen. KEINEN Platz anlegen 
3
// und NICHT initialisieren
4
extern int meine_globale_variable;

Wenn du mit Anlegen eine Definition meinst, bist du auf dem Holzweg. 
Die globalen Variablen sollen nur in einem Modul definiert werden, d.h. 
es soll nur einmal Platz dafür angelegt werden und sie sollen nur einmal 
für den Programmstart initialisiert werden.

Typ. in EINER *.C Datei
1
// DEFINITION
2
// Platz anlegen und ggf. initialisieren, wenn Wert <> 0
3
int meine_globale_variable = 42;

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.