mikrocontroller.net

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


Autor: Martin Kohler (mkohler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
In diesem Tutorial steckt möglicherweise ein Fehler:
http://www.mikrocontroller.net/articles/AVR-GCC-Tu...

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:
int main(void)
{
   //...
 
   cli();  
   // Interrupts global deaktiviert 
 
   NichtUnterbrechenBitte();
   // auch nach Aufruf der Funktion deaktiviert
 
   sei();
   // Interrupts global aktiviert 
 
   NichtUnterbrechenBitte();
   // weiterhin aktiviert
   //...
 
   /* Verdeutlichung der unguenstigen Vorgehensweise mit cli/sei: */
   cli();  
   // Interrupts jetzt global deaktiviert 
 
   NichtSoGut();
   // nach Aufruf der Funktion sind Interrupts global aktiviert 
   // dies ist mglw. ungewollt!
   //...

}

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

Autor: Günter R. (galileo14)
Datum:

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

Autor: Martin Kohler (mkohler)
Datum:

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

Autor: Günter R. (galileo14)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
... dekativiert ...

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

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.