Forum: Compiler & IDEs Fehler im avr-gcc Tutorial?


von Martin K. (mkohler)


Lesenswert?

Hallo,
In diesem Tutorial steckt möglicherweise ein Fehler:
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Programmieren_mit_Interrupts

Es geht um das Code-Segment nach diesem Abschnitt:
Oft steht man vor der Aufgabe, dass eine Codesequenz nicht unterbrochen 
werden darf. Es liegt dann nahe, zu Beginn dieser Sequenz ein cli() und 
am Ende ein sei() einzufügen. ...

In diesem Codesegment ist main Funktion wie folgt enthalten:
1
int main(void)
2
{
3
   //...
4
 
5
   cli();  
6
   // Interrupts global deaktiviert 
7
 
8
   NichtUnterbrechenBitte();
9
   // auch nach Aufruf der Funktion deaktiviert
10
 
11
   sei();
12
   // Interrupts global aktiviert 
13
 
14
   NichtUnterbrechenBitte();
15
   // weiterhin aktiviert
16
   //...
17
 
18
   /* Verdeutlichung der unguenstigen Vorgehensweise mit cli/sei: */
19
   cli();  
20
   // Interrupts jetzt global deaktiviert 
21
 
22
   NichtSoGut();
23
   // nach Aufruf der Funktion sind Interrupts global aktiviert 
24
   // dies ist mglw. ungewollt!
25
   //...
26
27
}

Nun steht nach dem zweiten "NichtUnterbrechenBitte()" der Kommentar 
"weiterhin aktiviert".
Genau da sehe ich aber das Problem: In der Funktion wird cli() 
ausgeführt, ab Ende aber kein sei() mehr.
Somit kann nach dem zweiten Aufruf der Funktion doch GlobalIRQ nicht 
"weiterhin aktiviert" sein?

Gruss, Martin

von Günter R. (galileo14)


Lesenswert?

Was das Code-Beispiel sagen will, ist folgendes:

Man sollte nicht "sei()" zum Wieder-Aktivieren der Interrupts verwenden, 
sondern man sichert vor dem "cli()" das Statusregister, macht dann 
"cli()" (damit werden die Interrupts deaktiviert), und später wird 
einfach das Statusregister rückgespeichert; damit wird einfach der 
Zustand wiederhergestellt, der vor dem "cli()" bestand. Wenn nämlich 
vorher schon an anderer Stelle die Interrupts dekativiert wurden, 
bleiben sie nun immer noch deaktiviert, bis an dieser anderen Stelle 
seinerseits das Statusregister ebenfalls (mit ggf. aktivem I-Bit) 
rückgespeichert wird. Damit soll genau die Situation vermieden werden, 
daß an einer Stelle "sei()" gemacht wird ohne Rücksicht darauf, daß 
vielleicht eine übergeordnete Funktion aktiv ist, die weiterhin 
dekativierte Interrupts benötigt.

Daher: nicht die Sequenz "cli()" / "sei()" verwenden, sondern

uint8_t tmp_sreg = SREG;
cli();

...

SREG = tmp_sreg;

Insofern steckt im Tutorial kein Fehler. Lies es nochmal aufmerksam 
durch, dann wird Dir das aufgehen.


Gruß, Günter

von Martin K. (mkohler)


Lesenswert?

Ooops!
Klar hast du recht. Wer lesen kann ist im Vorteil.
Im "gut" Fall wird ja über das Hilfsregister tmp_sreg gesichert.
Danke für die Zusatzerläuterung.

Martin

von Günter R. (galileo14)


Lesenswert?

... dekativiert ...

Schreibfehler; muß natürlich "deaktiviert" heißen  :|)

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.