Einige Syntaxfragen / AVR GCC preprocessor



  • Ich arbeite gerade mit dem AVR GCC und habe folgenden Code aus einer mit Preprocessorbedingungen und so Zeug gespickten Lib (steht so aehnlich in Peter Fleury LCD Lib, falls es interessiert) :

    #define DATA1 0
    #define DATA2 DATA1
    #define DATA3 DATA1
    // ...
    if ( (&DATA1 == &DATA2) && (&DATA2 == DATA3) ) //...
    else //...
    

    Was bewirkt hier das "&" vor diesen konstanten Zahlen?

    Praktisch soll das pruefen, ob "DATA"-Definitionen gleich sind, um einen leicht optimierten Code auszufuehren. Ich hoffe mal, der Compiler optimiert die if-Pruefung und alternative Zweige weg, wenn die Definitionen nirgendwo im Code geaendert werden (habe es noch nicht nachgeprueft).
    Waere es unabhaengig davon nicht besser, da mit Preprocessor #if-Abfragen ranzugehen? Und was wuerde der Compiler machen, wenn die Definitionen geaendert werden? Wird die Funktion dann zuverlaessig in 2 verschiedenen Versionen erzeugt? (Hoffe das gehoert hier auch noch hin 😃 )

    Die letzte Frage hat nicht wirklich etwas mit ANSI C zu tun, aber falls hier zufaellig schon jemand versucht hat, ein HD44870-kompatibles LCD-Modul an einem AVR zu betreiben: Warum benutzt scheinbar alle Welt immer nur den 4Bit-Modus, ausser bei Memory Mapping? Gibt es, von den 4 eingesparten Port-Pins abgesehen, irgendeinen besonderen Grund dafuer?



  • Nobuo T schrieb:

    Was bewirkt hier das "&" vor diesen konstanten Zahlen?

    Es wird die Adresse der Variablen verwendet. Lies es als "Adresse von ..."

    Nobuo T schrieb:

    Praktisch soll das pruefen, ob "DATA"-Definitionen gleich sind, um einen leicht optimierten Code auszufuehren. Ich hoffe mal, der Compiler optimiert die if-Pruefung und alternative Zweige weg, wenn die Definitionen nirgendwo im Code geaendert werden (habe es noch nicht nachgeprueft).

    Die Hoffnung stirbt zuletzt.

    Nobuo T schrieb:

    Waere es unabhaengig davon nicht besser, da mit Preprocessor #if-Abfragen ranzugehen? Und was wuerde der Compiler machen, wenn die Definitionen geaendert werden? Wird die Funktion dann zuverlaessig in 2 verschiedenen Versionen erzeugt? (Hoffe das gehoert hier auch noch hin 😃 )

    Nicht unbedingt. Was zur Compiletime nicht feststeht, kann der Preprocessor nicht auflösen. Und was da dasteht ist eher sinnbefreit, aber wenn ich richtig vermute, was da stehen sollte, schmeißt der Compiler Sinnlosabfragen raus, löst sie also schon zur Compiletime auf, wenn möglich.

    Nobuo T schrieb:

    ... ein HD44870-kompatibles LCD-Modul an einem AVR zu betreiben: Warum benutzt scheinbar alle Welt immer nur den 4Bit-Modus, ausser bei Memory Mapping? Gibt es, von den 4 eingesparten Port-Pins abgesehen, irgendeinen besonderen Grund dafuer?

    Nein. 😃



  • Erstmal danke. 🙂

    pointercrash() schrieb:

    Nobuo T schrieb:

    ... ein HD44870-kompatibles LCD-Modul an einem AVR zu betreiben: Warum benutzt scheinbar alle Welt immer nur den 4Bit-Modus, ausser bei Memory Mapping? Gibt es, von den 4 eingesparten Port-Pins abgesehen, irgendeinen besonderen Grund dafuer?

    Nein. 😃

    Ok. Dann liegt es wohl scheinbar leider an mir, mit dieser Tradition zu brechen und diese frickelige Lib mal etwas zu bearbeiten. 😃

    edit:
    Arg, ich bin verpeilt. Scheint schon alles seine Richtigkeit zu haben mit dem Adress-&. Die &DATA-Dinger sollten trotzdem Konstanten sein, die sich zur Laufzeit nicht mehr aendern, also dem Praeprozessor bekannt. Compiliert jedenfalls auch mit #if-Abfragen statt if...
    Oder nimmt der Preprocessor dann "&Data" insgesamt als neuen Variablennamen?



  • Nobuo T schrieb:

    Aber haben solche ueber preprocessor-Macros definierten Konstanten ueberhaupt eine Adresse?

    Nee, die nicht, aber dann würde der Compiler motzen. Irgendwo übersiehst Du einen Include, wo eine Bindung an ein Register erfolgt, sonst wäre das wirklich sinnlos.

    Nobuo T schrieb:

    Ich dachte, der Compiler kriegt erst den Kram, den der preprocessor ausspuckt. Das muesste dann praktisch sowas sein:

    if ( (&0 == &0) && (&0 == &0) ...
    

    Wobei die Zahlen natuerlich keine Variablen sind, sondern tatsaechlich fixe Zahlen.

    Irgendwo steht die Definition, an welchem Port das Display hängt. Vermutlich wird so die Umschaltung für wechselnde Ports bzw. Multidisplaybetrieb gemacht. Aber irgendwas Wesentliches fehlt Dir noch.

    Nobuo T schrieb:

    Diese konstanten Zahlen stehen zur Compiletime fest, das ist ja genau der springende Punkt. Das wird wie in meinem Beispiel gezeigt einmal per #define am Anfang in einer Header-Datei mit konstanten Zahlen festgelegt und dann aendert sich da auch nichts mehr. Deshalb sollte das im Prinzip auch der preprocessor aufloesen koennen (auf jeden Fall compiliert es auch, wenn ich "#if" statt "if"-Abfragen verwende).

    Die Zeile da oben würde immer zum True werden, der Compiler schmeißt das if raus und der Block wird immer ausgeführt.

    Nobuo T schrieb:

    Ok. Dann liegt es wohl scheinbar leider an mir, mit dieser Tradition zu brechen und diese frickelige Lib mal etwas zu bearbeiten. 😃

    Du gewinnst nix, Du verlierst nur Pins. Wenn man mit einem 8Bit- Port auskommt, hat das viele Vorteile, hauptsächlich daß man mit Macros das Ding leicht verschieben kann. Wenn Du Routinen für den 8-Bit- Betrieb brauchst, die hab' ich noch irgendwo, ich bin froh, das Zeug auf 4 Bit zu haben.



  • Nobuo T schrieb:

    Compiliert jedenfalls auch mit #if-Abfragen statt if...
    Oder nimmt der Preprocessor dann "&Data" insgesamt als neuen Variablennamen?

    Der Präprozessor weiß absolut gar nix von C, also ist das für ihn nur "so ein Literal".



  • pointercrash() schrieb:

    Du gewinnst nix, Du verlierst nur Pins.

    das ist so nicht ganz richtig. du hast zwar recht, dass es in den meisten fällen mehr sinn macht, nur einen 8bit-port zu belegen, in einigen situationen macht eine 8bit breite übertragung ans display aber durchaus sinn. z.b. wenn man nur ein sehr enges zeitfenster für die ausgabe hat und jeder taktzyklus zählt.

    ru,
    cirion



  • Nobuo T schrieb:

    Oder nimmt der Preprocessor dann "&Data" insgesamt als neuen Variablennamen?

    Nein.

    Allerdings verstehe ich nicht, worin der Sinn bestehen sollen, die ADRESSEN von Datenbereichen zu vergleichen wie du oben schriebst. Ich vergleiche eigentlich immer die Daten selbst miteinander, also statt
    &DATA1 == &DATA2
    lieber
    DATA1 == DATA2

    Ich hoffe mal, in der o.g. Lib wird das auch so getan bloß dein "Extrakt" ist etwas danebengegangen.



  • ein sinn liegt imho nur dann vor, wenn die präprozessorsymbole auf port-register und nicht auf konstanten verweisen. da würde dann z.b. nach "#define P0 PORTB" und "#define P1 PORTC" eine abfrage "if (P0 == P1)" (nach präprozessorlauf "if (PORTB == PORTC)") auswerten, ob die flags bei beiden ports identisch gesetzt sind, während "if (&P0 == &P1)" (nach präprozessorlauf "if (&PORTB == &PORTC)") tatsächlich auswertet, ob P0 und P1 sich auf den gleichen port beziehen.

    ru,
    cirion



  • (wie pointercrash oben schon schrieb)

    editieren geht hier forum nicht, oder?

    ru,
    cirion



  • cirion schrieb:

    eine 8bit breite übertragung ans display aber durchaus sinn. z.b. wenn man nur ein sehr enges zeitfenster für die ausgabe hat und jeder taktzyklus zählt.

    Der Chip ist sowas von lahm, der verliert ja schon die Peilung, wenn man ihn mitm AVR am Uhrenquarz befeuert. Heißt, Memory Mapping scheidet aus und man verlagert ihn in eine gemütliche Service- Routine am Besten im Polling- Teil und damit jederzeit unterbrechbar. Das busy- Handling ist ziemlich unleidlich gestaltet, soweit ich mich erinnere.



  • cirion schrieb:

    (wie pointercrash oben schon schrieb)

    editieren geht hier forum nicht, oder?

    ru,
    cirion

    Doch, bei jedem Deiner Beiträge müßte es auch einen Link zum Editieren geben.



  • Wutz schrieb:

    Nobuo T schrieb:

    Oder nimmt der Preprocessor dann "&Data" insgesamt als neuen Variablennamen?

    Nein.

    Oh doch, schon. Belehr' mich eines Besseren, aber da der Präppi von C nix weiß, sind &DATA und DATA einfach nur zwei unterschiedliche Literale.



  • pointercrash() schrieb:

    Der Chip ist sowas von lahm, der verliert ja schon die Peilung, wenn man ihn mitm AVR am Uhrenquarz befeuert.

    nicht jeder hd44870-kompatible lcd-controller ist so lahm wie das original.

    ru,
    cirion



  • cirion schrieb:

    pointercrash() schrieb:

    Der Chip ist sowas von lahm, der verliert ja schon die Peilung, wenn man ihn mitm AVR am Uhrenquarz befeuert.

    nicht jeder hd44870-kompatible lcd-controller ist so lahm wie das original.

    Na und? Du kriegst irgendwelche Chinesenscheiße, mal reagiert der Controller im ns- Bereich (500 ns sind für die meisten µC sowieso noch lahm, zu lahm für memory mapping) und bei der nächsten Lieferung irgendwas mit einem Uralt- Chip. Was anderes als der 44870 war ja nicht spezifiziert - willst Du Dich dafür vom Einkauf anpissen lassen?
    Ich jedenfalls nicht. 😃



  • klar. wir sind hier in der produktion, und wenn jemand hd44870-code nutzt, dann muss es zwangsweise um einen hd44870 gehen... 🙄

    fakt ist, man hat nicht bei jeder anwendung beliebig zeit für das display, und in solchen fällen macht eine 8bit-anbindung sinn, wenn man die pins eh noch frei hat.

    ru,
    cirion



  • cirion schrieb:

    fakt ist, man hat nicht bei jeder anwendung beliebig zeit für das display, und in solchen fällen macht eine 8bit-anbindung sinn, wenn man die pins eh noch frei hat.

    Wow, Deine Ahnungslosigkeit ist beeindruckend. 👍
    Vor jedem Schreibzugriff muß man das Busy checken und das toggelt mit 60 Hz oder so, weil der Chip gerade die Backplane invertiert. Was interessiert es mich da, ob ich ihm in der Zeit 100 oder 1000 Zeichen reinblasen kann, der Controller kann nur etwa 100 Zeichen anzeigen. Der Geschwindigkeitsvorteil von 4 zu 8 Bit ist damit völlig unerheblich, alles Andere, als das unterbrechbar zu gestalten ist krasses Fehldesign. :p



  • pointercrash() schrieb:

    Wow, Deine Ahnungslosigkeit ist beeindruckend.

    nein, eher die deinige. ausser beim clearen des ganzen displays ist das busy-flag herzlich irrelevant, wenn man das timing vernünftig hinbekommt. schon mal ohne probiert? mach mal. und reiss danach erst wieder die klappe auf, bitte.

    ru,
    cirion



  • cirion schrieb:

    ausser beim clearen des ganzen displays ist das busy-flag herzlich irrelevant, wenn man das timing vernünftig hinbekommt. schon mal ohne probiert? mach mal. und reiss danach erst wieder die klappe auf, bitte.

    Ja, schon mal probiert, je nach Nachbau mit unterschiedlichen Ergebnissen, genau darauf kommt's an. FM- Technik (funktioniert manchmal) ist was für Bastler, aber nix, was ein paar Tausend mal ins Feld muß.
    Der 4-Bit- Betrieb spielt jedenfalls keine Rolle, der 8-Bit- Betrieb verschafft keine Geschwindigkeitsräusche.
    Außerhalb der Spec soll man die Dinger auch nicht betreiben, weil sie sonst gelegentlich abstürzen. Alles schon probiert.



  • rofl... und jetzt wälz nochmal das hd44780-datasheet (das originale, nicht die ganzen china-kürzungen) und stell fest, dass das busy-flag gar nicht periodisch gesetzt wird, sondern absolut berechenbar ist...

    von geschwindigkeitsrausch war eh nie die rede. aber du nutzt ja sowieso sachen wie polling...

    ru,
    cirion



  • cirion schrieb:

    rofl... und jetzt wälz nochmal das hd44780-datasheet (das originale, nicht die ganzen china-kürzungen) und stell fest, dass das busy-flag gar nicht periodisch gesetzt wird, sondern absolut berechenbar ist...

    Toll. Dann ist das Busy-Flag einfach nur da, um da zu sein 🙄


Anmelden zum Antworten