Forum: Mikrocontroller und Digitale Elektronik AVR - ATOMIC_BLOCK vs. cli & sei


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Adam P. (adamap)


Bewertung
0 lesenswert
nicht lesenswert
Nabend zusammen,

seid langem bin ich mal wieder von den Cortex-M zurück bei den AVR und 
erarbeite mir grad ein wenig tieferes Wissen.

Ich hab mir nun mal ein kleines Bsp. erstellst und analysiere die *.lss 
Datei.

Ja mir ist bewusst, dass der Interrupt für "USART0_UDRE_vect" nicht 
aktiv ist, ich wollte lediglich nur den Vector belegen.
1
volatile uint32_t i;
2
3
ISR(USART0_UDRE_vect)
4
{
5
    i++;
6
}
7
8
int main(void)
9
{
10
    uint32_t tmp = 0;
11
  
12
    sei();
13
  
14
    while (1) 
15
    {
16
        /* Fall 1 */
17
        cli();
18
        if (i == 10)
19
        {
20
            tmp++;
21
        }
22
        sei();
23
            
24
        /* Fall 2 */
25
      /* ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
26
       * {
27
       *    if (i == 10)
28
       *    {
29
       *       tmp++;
30
       *    }
31
       * }
32
       */
33
    }
34
}

Aber nun zu meiner Frage:
Ist der Einzige Unterschied zwischen den beiden Varianten nur der, dass 
das SREG gesichert und wieder hergestellt wird (bei Fall 2)?

Da ich im *.lss dafür dann extra Sprünge zu
1
static __inline__ uint8_t __iCliRetVal(void)

und
1
static __inline__ void __iRestore(const  uint8_t *__s)

JA, ergibt natürlich auch Sinn...ABER muss ich bei so einem atomaren 
Zugriff mittels cli / sei, das SREG sichern?

Warum wird das beim ATOMIC_BLOCK(ATOMIC_RESTORESTATE) gemacht?

edit:
Ist natürlich eine uint32_t Variable und die Blöcke waren grad noch an 
der falschen Stelle, sorry.

:
von qwertzuiopü+ (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Adam P. schrieb:
> ABER muss ich bei so einem atomaren Zugriff mittels cli / sei, das SREG
> sichern?

Der ATOMIC_BLOCK soll ja nicht immer nach Beenden Interrupts 
einschalten, sondern nur, wenn sie auf vorher aktiv waren. Deswegen 
sichert der SREG. Wäre zumindest meine Vermutung...

Beitrag #5744249 wurde vom Autor gelöscht.
von Adam P. (adamap)


Bewertung
0 lesenswert
nicht lesenswert
Ja jetzt sehe ich es auch...vermutest du richtig.

Sonst müsste man es per Hand machen und das wäre net so schön zu lesen.

edit:
...kaum schreibt man es auf und denkt nochmal drüber nach, ist es schon 
im Forum, und man erkennt es erst dann selbst -  und denkt sicht 
nur...warum :-D

: Bearbeitet durch User
von Arduino Fanboy D. (ufuf)


Bewertung
0 lesenswert
nicht lesenswert
Auch wenn es BLOCK heißt, sind dennoch keine Blockklammern nötig.
(zumindest die modernen Kompiler brauchen keine Klammern für die for() 
Schleife)
1
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) if(i == 10) tmp++;

Adam P. schrieb:
> Sonst müsste man es per Hand machen und das wäre net so schön zu lesen.
Ja.
Jede IDE kann zusammengehörige Blockklammern zeigen.
Damit ist eine Verwirrung, welches cli() zu welchen sei() gehört, quasi 
ausgeschlossen.

von Adam P. (adamap)


Bewertung
0 lesenswert
nicht lesenswert
Arduino Fanboy D. schrieb:
> Auch wenn es BLOCK heißt, sind dennoch keine Blockklammern nötig.

Arduino Fanboy D. schrieb:
> ATOMIC_BLOCK(ATOMIC_RESTORESTATE) if(i == 10) tmp++;

D.h. aber ich muss es in 1 Zeile schreiben?

Woher weiß er sonst wann der ATOMIC_BLOCK aufhört?
Bei mehreren Anweisungen sind mir dann doch Klammern lieber und mehrere 
Zeilen. (Falls es wirklich so ist)

von Arduino Fanboy D. (ufuf)


Bewertung
0 lesenswert
nicht lesenswert
Adam P. schrieb:
> Woher weiß er sonst wann der ATOMIC_BLOCK aufhört?

Beim Semikolon!
1
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) 
2
  if(i == 10) 
3
    tmp++;

Wie bei:
1
for(....) if(i == 10) tmp++;
2
3
for(....) 
4
  if(i == 10) 
5
    tmp++;
Denn schließlich ist ATOMIC_BLOCK ja nur eine for() Schleife

von Adam P. (adamap)


Bewertung
0 lesenswert
nicht lesenswert
OK...:
1
#define ATOMIC_BLOCK(type) for ( type, __ToDo = __iCliRetVal(); \
2
                         __ToDo ; __ToDo = 0 )

Aber dann brauch man die Klammern nur bei einer Anweisung nicht...bei 
mehreren sieht es anders aus.

Gut - nun is es klar.

von leo (Gast)


Bewertung
-1 lesenswert
nicht lesenswert
Arduino Fanboy D. schrieb:
> (zumindest die modernen Kompiler brauchen keine Klammern für die for()
> Schleife)

Das hat mit modern aber gar nichts zu tun.

Eine for-Schleife ist definiert als
1
for(...)
2
  statement
Ein statement ist ein einzelnes oder (u.a.) ein compound-statement:
1
compound-statement:
2
  { block-item-list opt }
also auch eine Abfolge von statements in geschweiften Klammern.

BTW der Zusammenhang ist:
1
#define ATOMIC_BLOCK(type) for ( type, ...

leo

von Arduino Fanboy D. (ufuf)


Bewertung
-1 lesenswert
nicht lesenswert
leo schrieb:
> Das hat mit modern aber gar nichts zu tun.

Ja?
Mag sein...
Vielleicht haben wir auch verschiedene alt.
(vielleicht habe ich auch unrecht)

leo schrieb:
> Eine for-Schleife ist definiert alsfor(...)
>   statement
eben drum.

for(....);
for(....){}
Fehlende Anweisungen machten früher mal Sorgen...
Wenn meine Erinnerung mich nicht ganz arg täuscht.

Der aktuelle gcc steckt ein
ATOMIC_BLOCK(ATOMIC_RESTORESTATE);
ohne Murren weg.

Beitrag #5744444 wurde von einem Moderator gelöscht.
Beitrag #5744452 wurde von einem Moderator gelöscht.
von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert
Arduino Fanboy D. schrieb:
> Auch wenn es BLOCK heißt, sind dennoch keine Blockklammern nötig.
> (zumindest die modernen Kompiler brauchen keine Klammern für die for()
> Schleife)ATOMIC_BLOCK(ATOMIC_RESTORESTATE) if(i == 10) tmp++;

So einen SCHEIß!!! macht man einfach nicht!

Genau so wie man bei for, while und if eigentlich IMMER Klammern setzen 
sollte! Denn dadurch erreicht man nicht nur bessere Lesbarkeit sondern 
auch Sicherheit, wenn man den Code mal erweitern will.

https://www.mikrocontroller.net/articles/Strukturierte_Programmierung_auf_Mikrocontrollern#Weblinks

https://www.mikrocontroller.net/articles/Datei:CodeStyleConventions_ID_Software.pdf

Wenn die Jungs von ID Software das machen und auch sachlich begründen, 
kann es nicht so falsch sein.

> Jede IDE kann zusammengehörige Blockklammern zeigen.
> Damit ist eine Verwirrung, welches cli() zu welchen sei() gehört, quasi
> ausgeschlossen.

Nö.

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
Adam P. schrieb:
> Warum wird das beim ATOMIC_BLOCK(ATOMIC_RESTORESTATE) gemacht?

Weil Du es so willst.
Nimm ATOMIC_BLOCK(ATOMIC_FORCEON) und die SREG-Sicherung fällt weg.

von Adam P. (adamap)


Bewertung
0 lesenswert
nicht lesenswert
Peter D. schrieb:
> Nimm ATOMIC_BLOCK(ATOMIC_FORCEON)

Ja darüber bin ich dann auch gestolpert.

Beitrag #5744593 wurde von einem Moderator gelöscht.
Beitrag #5744604 wurde von einem Moderator gelöscht.
von Adam P. (adamap)


Bewertung
0 lesenswert
nicht lesenswert
G. B. schrieb im Beitrag #5744604:
> Das macht man kurz und knapp und schmerzlos in Assembler.

Spricht bei der Variante etwas dagegen, die paar Zeilen vor und nach dem 
atomaren Zugriff in inline Funktionen auszulagern?

Edit:
Warum werden hier eigentlich soviele Beiträge gelöscht? :-/

: Bearbeitet durch User
von Arduino Fanboy D. (ufuf)


Bewertung
1 lesenswert
nicht lesenswert
Falk B. schrieb:
>> Jede IDE kann zusammengehörige Blockklammern zeigen.
>> Damit ist eine Verwirrung, welches cli() zu welchen sei() gehört, quasi
>> ausgeschlossen.
>
> Nö.

Was "nööö" ?
Sind die IDE dööfer, als ich meine, oder ist es sachlich falsch, dass 
ATOMIC_BLOCK die korrekte Abfolge garantiert?

Einfach nur "Nöö" ist hier ein wenig plem plem, wie mir scheint.

Falk B. schrieb:
> So einen SCHEIß!!! macht man einfach nicht!
>
> Genau so wie man bei for, while und if eigentlich IMMER Klammern setzen
> sollte! Denn dadurch erreicht man nicht nur bessere Lesbarkeit sondern
> auch Sicherheit, wenn man den Code mal erweitern will.

Auch hier!

Ich beschreibe eine Möglichkeit, es ist keine Empfehlung es so zu tun.

Ganz im Gegenteil, ich spreche mich für die Verwendung von Blockklammern 
aus.
Das das ignorierst du gepflegt!
Bzw sagst so gar "Nö" dazu.
Etwas arg irre, du mir erscheinst.

Und ein Priester, du bist.
Dogmen, oder Vernunft?
Das ist die Frage, wie du gesteuert bist.

---------

Adam P. schrieb:
> Edit:
> Warum werden hier eigentlich soviele Beiträge gelöscht? :-/
Weil hier mal wieder Leute aus dem Ruder laufen, und vor dem betreten 
des Internets den Verstand irgendwo haben liegen gelassen.

von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert
Arduino Fanboy D. schrieb:
> Falk B. schrieb:
>>> Jede IDE kann zusammengehörige Blockklammern zeigen.
>>> Damit ist eine Verwirrung, welches cli() zu welchen sei() gehört, quasi
>>> ausgeschlossen.
>>
>> Nö.
>
> Was "nööö" ?

Das nö, das dort steht! Soll ich es vorlesen?

> Sind die IDE dööfer, als ich meine,

Sind sie nicht, aber sich immer auf eine IDE und deren Aufzuckerung zu 
verlassen ist nicht sinnvoll. Ein gut strukturierter Quelltext ist Gold 
wert und wird auch auf dem einfachsten Texteditor richtig angezeigt und 
ist auch dort sehr gut lesbar.

>oder ist es sachlich falsch, dass
> ATOMIC_BLOCK die korrekte Abfolge garantiert?

Darum ging es gar nicht.

> Einfach nur "Nöö" ist hier ein wenig plem plem, wie mir scheint.

Man sollte schon sinnerfassend lesen können und wollen.

> Falk B. schrieb:
>> So einen SCHEIß!!! macht man einfach nicht!
>>
>> Genau so wie man bei for, while und if eigentlich IMMER Klammern setzen
>> sollte! Denn dadurch erreicht man nicht nur bessere Lesbarkeit sondern
>> auch Sicherheit, wenn man den Code mal erweitern will.
>
> Auch hier!
>
> Ich beschreibe eine Möglichkeit, es ist keine Empfehlung es so zu tun.

Es ist eine schlechte Empfehlung.

> Ganz im Gegenteil, ich spreche mich für die Verwendung von Blockklammern
> aus.

Wo? Ach so.

"Jede IDE kann zusammengehörige Blockklammern zeigen."

Hab ich wohl falsch interpretiert. Mein Fehler! Tut mir leid.

von Adam P. (adamap)


Bewertung
0 lesenswert
nicht lesenswert
Wie ist es nun?

Wäre es "besser", anstelle von ATOMIC_BLOCK eigenen ASM Code für Ein- 
und Rücksprung in inline Funktionen auszulagern?

von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert
Adam P. schrieb:
> Wie ist es nun?
>
> Wäre es "besser", anstelle von ATOMIC_BLOCK eigenen ASM Code für Ein-
> und Rücksprung in inline Funktionen auszulagern?

Nein, zumindest nicht auf dem avr gcc.

von Arduino Fanboy D. (ufuf)


Bewertung
-1 lesenswert
nicht lesenswert
Falk B. schrieb:
> 
https://www.mikrocontroller.net/articles/Datei:CodeStyleConventions_ID_Software.pdf
>
> Wenn die Jungs von ID Software das machen und auch sachlich begründen,
> kann es nicht so falsch sein.
Entweder kannst du keine English, oder hast es selber nicht gelesen.
Keinerlei Empfehlung unnütze Blockklammern zu setzen. Nirgendwo nicht.
Begründungen finden sich da gar keine.
Null.

Des weiteren sind die dort aufgeführten Konventionen teilweise 
haarsträubend.
(aus meiner Sicht)

Und das ist deine Bibel?
Da wird mir einiges klarer.....
Aber deine Stil Empfehlungen werde ich in Zukunft gepflegt ignorieren.


OK, selbst solche Konventionen, sind besser als keine.
Das ist wirklich das positivste, was ich dazu sagen kann.

-------------

Adam P. schrieb:
> Wie ist es nun?
>
> Wäre es "besser", anstelle von ATOMIC_BLOCK eigenen ASM Code für Ein-
> und Rücksprung in inline Funktionen auszulagern?
Nein!
Das ist schon perfekt so für deinen Gebrauch vorbereitet.
Daran kann man nichts mehr verbessern.

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Falk B. schrieb:
> Genau so wie man bei for, while und if eigentlich IMMER Klammern setzen
> sollte!

Sehe ich genauso. Spätestens, wenn man später eine zweite Zeile ins 
if-Statement packen will, muss man die Klammern setzen. Deshalb mache 
ich sie gleich - auch wenns nur ein Statement ist.

Ebenso kann man sich ohne geschweifte Klammern auch ins Knie schiessen, 
wenn man ein (schlecht gestyltes) Preprocessor-Makro nach einem if 
aufruft, ohne es zu wissen. Dann wundert man sich zum Beispiel, warum 
ein nachfolgender else-Block niemals aufgerufen wird, obwohl die eigene 
Bedingung eigentlich false ist.

Beispiel:
1
#define filter(ch) if (ch == '@') ch = '#'     // schlecht!
2
...
3
4
int main()
5
{
6
     int ch;
7
     int cnt = 0;
8
9
     while ((ch = getchar()) != EOF)
10
     {
11
        if (cnt++ == 1000)
12
           filter(ch);
13
        else
14
           ch = '!';
15
        putchar(ch);
16
    }
17
}

Spätestens jetzt sollte man überlegen, zu welchem if das else gehört...

Mit geschweiften Klammern wäre das nicht passiert, sogar, wenn man das 
Makro so bescheuert stehen lässt, weil es zu einer externen Lib gehört, 
die man tunlichst nicht anpacken will (oder darf).

: Bearbeitet durch Moderator
von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert
Arduino Fanboy D. schrieb:
> Falk B. schrieb:
>>
> 
https://www.mikrocontroller.net/articles/Datei:CodeStyleConventions_ID_Software.pdf
>>
>> Wenn die Jungs von ID Software das machen und auch sachlich begründen,
>> kann es nicht so falsch sein.
> Entweder kannst du keine English, oder hast es selber nicht gelesen.

Weder noch.

> Keinerlei Empfehlung unnütze Blockklammern zu setzen. Nirgendwo nicht.

"Use typically trailing braces everywhere (if, else, functions, 
structures, typedefs, class definitions, etc.)
if ( x ) { }"

> Begründungen finden sich da gar keine.
> Null.

Stimmt, das war woanders. Hab ich wohl verwechselt.

von Arduino Fanboy D. (ufuf)


Bewertung
0 lesenswert
nicht lesenswert
Falk B. schrieb:
> Man sollte schon sinnerfassend lesen können und wollen.
Das wirfst du mir vor?

Und dann kommst du mir mit sowas:
Falk B. schrieb:
> "Use typically trailing braces everywhere (if, else, functions,
> structures, typedefs, class definitions, etc.)
Erstens:
"typically" Ist kein Aufruf zur Verwendung unnützer Klammern.
Sagt nur, dass typischer weise Klammern auf diese Statements folgen, 
aber nicht, dass sie unbedingt folgen müssen.

Eher, wenn Klammern, dann so (siehe Zweitens).

Zweitens:
"trailing braces" Damit ist gemeint, dass die Klammern, wenn "typically" 
vorhanden, in der gleichen Zeile folgen sollen. Wie der Schwanz vom 
Hund. Der geht auch nicht alleine auf der anderen Straßenseite. Der ist 
"typically" angewachsen.
Mehr hat das nicht zu bedeuten.

Also: (Der typische K&R Stil)
if ( x ) {
  tuwas();
}

Und nicht irgendwie so:
if(x)
{
  tuwas();
}


Welcher Stil hübscher, oder leichte zu lesen ist, überlasse ich dir.
Ich persönlich finde den K&R Stil hässlich.
Alleine deswegen, weil die zusammengehörigen Klammern nicht übereinander 
stehen, schlechter lesbar.
Wie gesagt: Die IDEs zeigen zusammengehörige Klammern an und wenn genau 
übereinander, dann alles gut.

Im dem style guide finden sich noch mehr komische Dinge....
Sowas würde ich niemals freiwillig zu meiner Bibel machen wollen.


Und Nein.
Dein Textverständnis hat offensichtlich arge Lücken.
Das dürfte auch der Grund dafür sein, dass du mit meinen Texten Probleme 
hast.
Dann will ich in Zukunft dann doch etwas Nachsicht mit dir üben.
(Was du wohl sonst noch alles falsch interpretierst?)

: Bearbeitet durch User
von Adam P. (adamap)


Bewertung
0 lesenswert
nicht lesenswert
Also...

Ich finde es ja echt interessant, dass ich euch zu so einem motiviertem 
Gespräch geführt habe,

aber der Sytle von "wo und wie setze ich meine Klammern {}",
war eigentlich nicht das Anfangsthema (auch wenn es aus dem ATOMIC_BLOCK 
erst dazu gekommen ist) :-P

Ich finde es nicht schlimm, aber über Geschmack lässt sich streiten...

Ich bevorzuge auch lieber:
1
if (x == y)
2
{
3
   foo();
4
}

Aber ich danke euch, dass ihr mir meine "doch so offensichtlichen" 
Fragen beantwortet habt - manchmal sieht man es einfach nicht.

: Bearbeitet durch User
Dieser Beitrag kann nur von angemeldeten Benutzern beantwortet werden. 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, Yahoo oder Facebook? Keine Anmeldung erforderlich!
Mit Google-Account einloggen | Mit Facebook-Account einloggen
Noch kein Account? Hier anmelden.