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
Assemblercode des Compilers ausgeben lassen. Ansehen.
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 | }
|
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 | 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!
Manuel wrote:
> Was soll da gegen static spechen?
Weil das ungefähr so klingt wie "extern intern" oder "oben unten".
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.
OK - ich vergrab mich mal besser... sorry für die missverständnisse...
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.
@ supachris:
>Ich arbeite..
Ich denke, du bist am Institut? ;-))
**duck und weg**
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 | 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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.