mikrocontroller.net

Forum: Compiler & IDEs Überlauf geht verloren


Autor: Hannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Forum,

ich lasse Timer1 mit F-CPU laufen (TCCR1B=(1<<CS10); ) und zähle mit 
Timer0 externe Ereignisse (TCCR0=(1<<CS01)|(1<<CS02); )

Jetzt habe ich folgendes festgestellt:

Wenn ich das ICF1-Bit lösche mit TIFR|=(1<<ICF1); und just im gleichen 
CPU-Zyklus läuft Timer0 über, geht das TOV0-Bit in TIFR verloren bzw. 
wird gar nicht gesetzt!?

Kann das sein? Odr mache ich was falsch?

Danke für Eure Antworten

Hannes.

Autor: SeriousSam (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bit löschen geht in diesem Fall mit TIFR = (1<<ICF1).
Siehe: http://www.nongnu.org/avr-libc/user-manual/FAQ.htm...

Autor: Hannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Sam,

danke für die Antwort! Das war die Ursache.

Ciao

Hannes

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hannes schrieb:
> Das war die Ursache.
Und der Hintergrund?

Im TIFR werden die Bits gelöscht, die mit einer '1' beschrieben 
werden. Wenn also im TIFR neben dem ICF1 auch das TOV0 gesetzt war, dann 
wird bei
> TIFR|=(1<<ICF1);
erst mal das TIFR eingelesen, dann ICF1 dazuverodert, und dann das Ganze 
wieder auf das TIFR rausgeschrieben.
TIFR
Bit  7   6   5   4   3   2   1   0   
  OCF2   TOV2   ICF1   OCF1A   OCF1B   TOV1   OCF0   TOV0   
Wenn jetzt also im TIFR sowas steht  "0010 0001" (ICF1 und TOV0 
gesetzt),
dann wird "0010 0000" dazuverodert, das gibt dann "0010 0001" (es ändert 
sich nichts).
Und wenn das wieder auf TIFR rausgeschrieben wird, werden beide Bits 
gelöscht. Hoppla, der Overflow ist verschwunden... :-o
Das wäre also das selbe wie wenn ich schreibe:
> TIFR = TIFR;

Mit
> TIFR = (1<<ICF1);
wird dagegen nur das ICF1 Flag gelöscht. Und das war gewünscht.

Autor: Michael Buesch (mb_)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lothar Miller schrieb:
> Hannes schrieb:
>> Das war die Ursache.
> Und der Hintergrund?
>
> Im TIFR werden die Bits gelöscht, die mit einer '1' beschrieben
> werden. Wenn also im TIFR neben dem ICF1 auch das TOV0 gesetzt war, dann
> wird bei
>> TIFR|=(1<<ICF1);
> erst mal das TIFR eingelesen, dann ICF1 dazuverodert, und dann das Ganze
> wieder auf das TIFR rausgeschrieben.

Naja, und was ist wenn der compiler TIFR |= (1 << ICF1) zu sbi 
compiliert? Würde das immer noch nicht funktionieren?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael Buesch schrieb:

>>> TIFR|=(1<<ICF1);
>> erst mal das TIFR eingelesen, dann ICF1 dazuverodert, und dann das Ganze
>> wieder auf das TIFR rausgeschrieben.
>
> Naja, und was ist wenn der compiler TIFR |= (1 << ICF1) zu sbi
> compiliert? Würde das immer noch nicht funktionieren?

Gute Frage. Sogar eine sehr gute Frage.
Die tiefer liegende Frage lautet: Darf er das überhaupt?

Das Problem:
Die ganze Operation ist auf C Ebene nur schlecht definiert, wenn 
überhaupt. Man beschreibt ein Register (eine spezielle Variable) mit 
einem Wert und hinterher steht hardwarebedingt etwas ganz anderes in 
diesem Register. Das alleine widerspricht doch schon allem was in C 
vorausgesetzt wird.

Die daraus abgeleitete Frage lautet:
Wenn die oberste Prämisse für den Optimizer die 'As If' Regel ist, woran 
muss er sich dann orientieren? An dem was das C-Statement aussagt, 
nämlich das ein Bit zu einem Wert hinzugeodert wird. Dann darf er zu 
einem sbi optimieren, selbst wenn das auf der Hardware nicht dieselben 
Auswirkungen hat, wie bei einer reinen Betrachtung auf C Ebene.
Oder muss er sich an den Auswirkungen orientieren? Dann dar er die 
Optimierung nicht durchführen, weil sie ja nicht den identischen Effekt 
hat.

In der Tat eine gute Frage.

Autor: Michael Buesch (mb_)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Michael Buesch schrieb:
>
>>>> TIFR|=(1<<ICF1);
>>> erst mal das TIFR eingelesen, dann ICF1 dazuverodert, und dann das Ganze
>>> wieder auf das TIFR rausgeschrieben.
>>
>> Naja, und was ist wenn der compiler TIFR |= (1 << ICF1) zu sbi
>> compiliert? Würde das immer noch nicht funktionieren?
>
> Gute Frage. Sogar eine sehr gute Frage.
> Die tiefer liegende Frage lautet: Darf er das überhaupt?
>
> Das Problem:
> Die ganze Operation ist auf C Ebene nur schlecht definiert, wenn
> überhaupt. Man beschreibt ein Register (eine spezielle Variable) mit
> einem Wert und hinterher steht hardwarebedingt etwas ganz anderes in
> diesem Register. Das alleine widerspricht doch schon allem was in C
> vorausgesetzt wird.
>
> Die daraus abgeleitete Frage lautet:
> Wenn die oberste Prämisse für den Optimizer die 'As If' Regel ist, woran
> muss er sich dann orientieren? An dem was das C-Statement aussagt,
> nämlich das ein Bit zu einem Wert hinzugeodert wird. Dann darf er zu
> einem sbi optimieren, selbst wenn das auf der Hardware nicht dieselben
> Auswirkungen hat, wie bei einer reinen Betrachtung auf C Ebene.
> Oder muss er sich an den Auswirkungen orientieren? Dann dar er die
> Optimierung nicht durchführen, weil sie ja nicht den identischen Effekt
> hat.
>
> In der Tat eine gute Frage.

Darauf wollte ich eigentlich nicht hinaus. Der GCC wird REG |= (1 << 
const) als sbi übersetzen, wenn die Optimierung eingeschaltet ist. Das 
ist in keinem Standard festgeschrieben, aber er macht es halt. Ob man 
sich darauf verlassen kann und sollte ist eine andere Frage.

Meine Frage war eher, gibt es einen Unterschied zwischen:

sbi TIFR, bitnr

und

ldi r0, (1 << bitnr)
out TIFR, r0

außer, dass das zweite einen Zyklus mehr braucht.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael Buesch schrieb:
> Meine Frage war eher, gibt es einen Unterschied zwischen:
>
> sbi TIFR, bitnr
>
> und
>
> ldi r0, (1 << bitnr)
> out TIFR, r0
>
> außer, dass das zweite einen Zyklus mehr braucht.

Nein, es gibt keinen weiteren Unterschied dazwischen.  Für einige
Register zumindest ist das auch explizit dokumentiert:

[...] Beware that if doing a Read-Modify-Write on ADCSRA,
a pending interrupt can be disabled. This also applies if the SBI and
CBI instructions are used.

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.