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
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.
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
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
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.
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...
> 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.
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.
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
volatileBOOLscanning;
2
3
TIMERISR(){
4
if(!scanning){
5
passiveChannelScan();// #1
6
}
7
}
Datei bolek.c
1
externvolatileBOOLscanning;
2
3
voidpassiveChannelScan(){
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!
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...
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.
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.
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.
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
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
externintmeine_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