www.mikrocontroller.net

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


Autor: Manuel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Manuel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Norgan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Assemblercode des Compilers ausgeben lassen. Ansehen.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ganz davon abgesehen ließe sich das Ganze komplett so umschreiben:
TIMER ISR(){
   passiveChannelScan();
}


void passiveChannelScan(){
   static BOOL scanning;
   if (scanning) {
      return;
   }
   scanning = TRUE;


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

   scanning = FALSE;
}

Autor: Manuel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Manuel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Norgan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

volatile BOOL scanning;

TIMER ISR(){
   if (!scanning){
      passiveChannelScan(); // #1
   }
}

Datei bolek.c

extern volatile BOOL scanning;

void passiveChannelScan(){
   scanning = TRUE;
   // ..... (dauert oft länger als der Timer)
   scanning = FALSE;
}

...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!

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Manuel wrote:

> Was soll da gegen static spechen?

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

Autor: Manuel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Manuel (Gast)
Datum:

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

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ supachris:

>Ich arbeite..

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


**duck und weg**

Autor: Kopfkratzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

// DEKLARATION
// Namen bekanntmachen. KEINEN Platz anlegen 
// und NICHT initialisieren
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

// DEFINITION
// Platz anlegen und ggf. initialisieren, wenn Wert <> 0
int meine_globale_variable = 42;


Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.