Mure schrieb:> Welche Codeausführung ist schneller und warum?
Wie wäre es mit einfach ausprobieren?
Ich würde allerdings wetten, dass keine Variante irgendwie schneller
wäre, und die meisten (zumindest 1-4) sogar absolut identischen Code
erzeugen.
Mure schrieb:> Die jeweilige Funktion VarianteX, kann durch Interrupts mehrfach> aufgerufen werden. Des Wegen die Sperre.
Da hilft dir deine Sperre aber nicht wirklich. Was, wenn der Interrupt
zwischen dem "if" und dem "i = 1;" auftritt?
Peter II schrieb:> Variante 1 und Variante 2 machen verschiende dinge
Nö. "!i" und "i == 0" sind identisch.
Edit: Allerdings machen Variante 3 und 4 was anderes. Die sollten wohl
eher nach dem Muster wie 5 und 6 aufgebaut sein.
Mure schrieb:> Die jeweilige Funktion VarianteX, kann durch Interrupts mehrfach> aufgerufen werden. Des Wegen die Sperre.
Du hast in diesem Zusammenhang hoffentlich an einen Cache-Flush gedacht,
oder?
Stefan Ernst schrieb:> Was, wenn der Interrupt> zwischen dem "if" und dem "i = 1;" auftritt?
Äh. Gute Frage! - Nächste Frage! Wie löse ich das Problem?
Stefan Ernst schrieb:> Edit: Allerdings machen Variante 3 und 4 was anderes.
Nochmal Äh! - Richtig erkannt. Falsch von mir getippt!
void Variante3()
{
if(i != 1)
{
i = 1;
/* Code ausführen */
i = 0;
}
}
void Variante4()
{
if(i > 0)
{
return;
}
i = 1;
/* Code ausführen */
i = 0;
}
Doof schrieb:> Du hast in diesem Zusammenhang hoffentlich an einen Cache-Flush gedacht,> oder?
Ein was!? - Nö! Bin wohl doofer als du...
Stefan Ernst schrieb:>> Variante 1 und Variante 2 machen verschiende dinge>> Nö. "!i" und "i == 0" sind identisch.
Das stimmt schon, aber es trotzdem Varianten dabei, die nicht dasselbe
tun.
Beispiele:
> void Variante4()> {> if(i > 0)> {> i = 1;> /* Code ausführen */> i = 0;> }> }
hier wird bei i>0, also auch bei i==1 der Code ausgeführt,
und
> void Variante6()> {> if(i == 1)> {> return;> }>> i = 1;> /* Code ausführen */> i = 0;> }
hier kommt bei i==1 'return' und der Code wird nicht ausgeführt.
Es dürften alle gleich sein, so lange der Instruktionssatz
Vergleichsoperationen für Grösser-/Kleiner-/Gleich hat.
Achja: Deine Sperre ist keine gute Implementation für das Problem.
Einerseits kann, wie bereits gesagt wurde, der Interrupt genau in die
Änderung von i reinfunken. Klingt unwahscheinlich, wird in der Praxis
aber sicher passieren und kaum zu findende Fehler auslösen. Andererseits
weist die Sperre darauf hin, dass deine Interruptroutine lang im
Verhältnis zum Aufrufinterval ist. Alternativ könntest du auch ein Flag
setzen, das dann in einer Hauptschleife ausgewertet und abgearbeitet
wird. Oder zumindest die Sperre sauber implementieren, Stichwort:
http://de.wikipedia.org/wiki/Semaphor_%28Informatik%29
HildeK schrieb:> Stefan Ernst schrieb:>>> Variante 1 und Variante 2 machen verschiende dinge>>>> Nö. "!i" und "i == 0" sind identisch.>> Das stimmt schon, aber es trotzdem Varianten dabei, die nicht dasselbe> tun.
Was ich in meinen Post ja auch ergänzt hatte. ;-)
Ja aber eine Semaphore und Mutex macht doch auch nichts anderes, als
sich ein Flag zu setzten ... Mein Flag ist halt "i = 1".
Ich sehe hier den unterschied nicht.
Mure schrieb:> Ja aber eine Semaphore und Mutex macht doch auch nichts anderes, als> sich ein Flag zu setzten ... Mein Flag ist halt "i = 1".> Ich sehe hier den unterschied nicht.
Der springende Punkt ist, dass das "test-and-set" atomar sein muss.
Mure schrieb:> Dann müsste man noch i als volatile definieren
Solange i++ nicht mit einer atomaren Operation errechnet werden kann,
nutzt volatile überhaupt nichts, denn dann kann da immer noch ein
Interrupt dazwischenfunken.
Es nutzt nichts, da muust du die Doku zu deinem Compiler und deinem
Prozessor lesen, und dafür sorgen, daß i++ oder i=1, oder was auch
immer, nicht unterbrochen werden kann.
Oliver
Oliver schrieb:> Es nutzt nichts, da muust du die Doku zu deinem Compiler und deinem> Prozessor lesen, und dafür sorgen, daß i++ oder i=1, oder was auch> immer, nicht unterbrochen werden kann.
Ich google schon wie blöde. Finde aber für nen MSP430 keinen Code für ne
Mutex...
HildeK schrieb:> Stefan Ernst schrieb:>> Was ich in meinen Post ja auch ergänzt hatte. ;-)>> Jaja, nachdem ich meinen geschrieben hatte ... :-)
Nö, denn man kann einen Post nicht mehr editieren, wenn bereits ein
weiterer in dem Thread ist. Mein Edit war also mindestens 5 Minuten vor
deinen Post da. ;-)
Mure schrieb:> Ich google schon wie blöde. Finde aber für nen MSP430 keinen Code für ne> Mutex...
Kann man recht einfach auch selber schreiben. Oder mache die Zuweisung
an i einfach atomar, indem du Interrupts kurz ausschaltest. Das sollte
auf dem MSP430 wohl ähnlich funktionieren wie auf einem AVR.
P. M. schrieb:> Kann man recht einfach auch selber schreiben.
Wenn man weiß wie's geht. Assembler kann ich leider nicht ...
P. M. schrieb:> der mache die Zuweisung> an i einfach atomar, indem du Interrupts kurz ausschaltest.
Quasi so was:
1
#define EnterMutex(_myMutex) _DINT(); /* Disable Global interrupt */ \
2
_myMutex++; \
3
if(_myMutex != 1){ \
4
goto _LeaveMutex; \
5
} \
6
_EINT(); /* Enable Global interrupt */\
7
8
#define LeaveMutex(_myMutex) _DINT(); /* Disable Global interrupt */ \
9
_myMutex--; \
10
_EINT(); /* Enable Global interrupt */\
11
12
13
unsignedchari;
14
voidVariante7()
15
{
16
EnterMutex(i);
17
/* Code ausführen */
18
LeaveMutex(i);
19
20
return;
21
}
Aber streng genommen müsste ich den Zustand von Global Interrupt Flag
abfragen, bevor ich es setze. Ich glaube es ist möglich, das die Mutex
betreten wird (Main-Loop), wenn der globale Interrupt deaktiviert ist.
Mure schrieb:> Bronco schrieb:>> Du bräuchtest eine Konstruktion wie diese ...> Sieht eigentlich wie meine aus.Mure schrieb:> goto _LeaveMutex; \
Nein, in meiner Konstruktion wäre ganz gewiß kein GOTO!
Kan asta schrieb:> Ich weiß ne Lösung!>> Der C-Chef sagt, so geht das:> (i == 0) ? i = 1 : i = 0;>> Eine Zeile, ein Befehl, alles atomar.
Das ist aber gelogen...
Bronco schrieb:> Nein, in meiner Konstruktion wäre ganz gewiß kein GOTO!
Richtig, aber was ist daran so schlimm?
Sven P. schrieb:>> Eine Zeile, ein Befehl, alles atomar.> Das ist aber gelogen...
Det habe ich mich grad auch gefragt.
Mure schrieb:> Sven P. schrieb:>>> Eine Zeile, ein Befehl, alles atomar.
Die gilt nur für Basic Interpreter, die arbeiten nähmlich alles Zeile
für
Zeile ab. Teilweise sogar für Compiler.
Ach ja klar, bei der Syntax der vorangegagenen Beispiele habe ich auch
sofort an Basic gedacht... und zwar an genau eines der zehntausend
verschiedenen Dialekte, welches zeilenweise tut :-)
Sven P. schrieb:> bei der Syntax der vorangegagenen Beispiele habe ich auch> sofort an Basic gedacht
Jetzt mal ohne SCh***. - Gibt es Basic für die
Mikrocontroller-Porgrammierung?
Zurück zum ursprünglichen Problem:
Richtig schlau bin ich jetzt aber noch immer nicht!
Wie macht man jetzt am Besten eine Mutex für den MSP?
Und zwar so, dass ich diese als Funktion oder Makro habe und in beliebig
vielen Codeabschnitten einsetzen kann?!?
Gruß
Mure
Mure schrieb:> Sven P. schrieb:>>> Eine Zeile, ein Befehl, alles atomar.>> Das ist aber gelogen...>> Det habe ich mich grad auch gefragt.
Hey Mure,
falls Du das wirklich nicht weißt:
Atomar bedeutet, daß es für die CPU ein ununterbrechbarer Vorgang ist.
Das sind z.B. einzelne Maschinen/Assembler-Befehle.
C-Code wird vom C-Compiler in Maschinen-Code umgewandelt.
D.h. ein C-Befehl ergibt oft in mehrere Maschinen-Befehle und ist
damit nicht atomar!
Bsp:
8-Bit Microcontroller macht
1
uint32_tx:
2
x++;
Das x++ erzeugt in vier Assembler-Befehle, weil die CPU pro Befehl nur
jeweils 8 der 32Bit berechnen kann.
So ist es ein sehr typischer Fehler, auf Variablen aus dem Interrupt
heraus zuzugreifen, dabei solche Befehlsblöcke zu unterbrechnen und
damit den Variableninhalt zu zerstören.
Falls Du IAR verwendest: lies mal "Monitor"-Funktionen in der Doku nach.
Bronco schrieb:> Atomar bedeutet, daß es für die CPU ein ununterbrechbarer Vorgang ist.
Habe ich inzwischen verstanden. Deswegen wird ja auch der GIE
deaktiviert.
Aber mit meinem Makro warst du aber nicht zufrieden.
Bronco schrieb:> Falls Du IAR verwendest
Nein. Habe Code Composer Studio.