Forum: Compiler & IDEs Überlauf geht verloren


von Hannes (Gast)


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.

von SeriousSam (Gast)


Lesenswert?

Bit löschen geht in diesem Fall mit TIFR = (1<<ICF1).
Siehe: http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_intbits

von Hannes (Gast)


Lesenswert?

Hallo Sam,

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

Ciao

Hannes

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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.
1
TIFR
2
Bit  7   6   5   4   3   2   1   0   
3
  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.

von Michael B. (mb_)


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?

von Karl H. (kbuchegg)


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.

von Michael B. (mb_)


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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

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.