Forum: Compiler & IDEs nop nop nop nop nop nop nop nop


von Nicolas S. (Gast)


Lesenswert?

Guten Morgen zusammen,
sollte jemand mehrere meiner Fragen in den letzten Wochen im GCC-Forum 
beobachtet haben wird er bemerkt haben, daß ich nach ein paar Jahren 
C-Abstinenz wieder angefangen habe und mir endlich mehr good practices 
angewöhnen will. Im diesem Rahmen mache ich schlimme Sachen: Alte 
Quelltexte refaktorieren.

Was mir momentan etwas störend aufstößt sind unübersichtliche 
nop-Schlangen in meinen Displaytreibern, da finden sich oft Konstrukte 
wie:
1
 [..]
2
 PORT_GLCD_COM |= (1<<GLCD_EN);
3
 asm volatile("nop"); // Datenblatt S. 12
4
 asm volatile("nop"); // min. X ms
5
 asm volatile("nop"); // fuer 16MHz
6
 asm volatile("nop");
7
 asm volatile("nop");
8
 asm volatile("nop"); // Angstnop
9
 asm volatile("nop"); // Angstnop
10
 PORT_GLCD_COM &= ~(1<<GLCD_EN);
11
 [...]

Ich habe ein paar Quelltexte durchforstet, die nop-Schlangen finden sich 
überall. Gibt es keine Präprozessormagische Möglichkeit, eine solche, 
übersichtlichere Schreibweise zu erreichen:
1
 [..]
2
 PORT_GLCD_COM |= (1<<GLCD_EN);
3
 NOP(8); // Datenblatt S. 12 min. X ms fuer 16MHz + 2 Angstnop
4
 PORT_GLCD_COM &= ~(1<<GLCD_EN);
5
 [...]

Eine for-Schleife ist für so kurze Wartezeiten ja eher ungeeignet, und 
die _delay_XX-Funktionen auch. Schleifenähnliche Konstrukte sind mir für 
den Präprozessor aber noch nie begegnet.

Gibt es keine bessere Lösung?

Viele Grüße
Nicolas

von Stefan E. (sternst)


Lesenswert?

1
__builtin_avr_delay_cycles(8);

Nicolas S. schrieb:
> Eine for-Schleife ist für so kurze Wartezeiten ja eher ungeeignet, und
> die _delay_XX-Funktionen auch.

Und warum bitte soll _delay_us() hier ungeeignet sein?

von Nicolas S. (Gast)


Lesenswert?

Stefan Ernst schrieb:
> Und warum bitte soll _delay_us() hier ungeeignet sein?

Weil 8 nops bei 16MHz immer noch kürzer als eine µs sind. Und 
_delay_ns(...) gibt es meines Wissens nach nicht.

Aber danke für __builtin_avr_delay_cycles, das kannte ich noch nicht.

von Stefan E. (sternst)


Lesenswert?

Nicolas S. schrieb:
> Weil 8 nops bei 16MHz immer noch kürzer als eine µs sind. Und
> _delay_ns(...) gibt es meines Wissens nach nicht.

Und was ist falsch an _delay_us(0.5)?

von Sam P. (Gast)


Lesenswert?

So am Rande: Schleifen im Präprozessor sind möglich, aber umständlich, 
unflexibel, und sehr schmuddelig. Da lohnt sich meistens, einfach 
mehrere unterschiedliche Makros mit den tatsächlich benötigten 
Wiederholsequenzen zu definieren.

von Nicolas S. (Gast)


Lesenswert?

Stefan Ernst schrieb:
> Und was ist falsch an _delay_us(0.5)?

Das Viech kann ja float! Konnte es das schon immer?

von Nicolas S. (Gast)


Lesenswert?

Hallo Stefan,
danke für die Antwort. Wenn die _delay- Funktionen mit float arbeiten 
(was ich implizit immer ausgeschlossen habe) mit sind die nop-Sammlungen 
tatsächlich obsolet geworden.

Vielleicht sollte ich mir öfter alte, vertraut erscheinende Bekannte 
ansehen...

Viele Grüße
Nicolas

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Nicolas S. schrieb:
> mit sind die nop-Sammlungen tatsächlich obsolet geworden.

Und auch noch für verschiedene Megaherze brauchbar ;-)

Nicolas S. schrieb:
> Wenn die _delay- Funktionen mit float arbeiten

Und wenn nicht, stört es echt ob das nun 1 µs oder 500ns gewartet wird?

von Stefan E. (sternst)


Lesenswert?

Nicolas S. schrieb:
> Stefan Ernst schrieb:
>> Und was ist falsch an _delay_us(0.5)?
>
> Das Viech kann ja float! Konnte es das schon immer?

Ja.

von Jörg E. (jackfritt)


Lesenswert?

Aber bitte keine variable in delay einsetzen sons bindet er die float 
mit ins programm ein und dann wird dein code grösser ;)

von Bernd W. (berndwiebus) Benutzerseite


Lesenswert?

Hallo Nicolas S.

> danke für die Antwort. Wenn die _delay- Funktionen mit float arbeiten
> (was ich implizit immer ausgeschlossen habe) mit sind die nop-Sammlungen
> tatsächlich obsolet geworden.

Warum sind solche nop-Sequenzen denn unübersichtlicher als die Delay 
Funktion?
Immerhin gibt dir die nop-Kette mit den Kommentaren einen 
Anschaulicheren Überblick, wie sich die Pause zusammensetzt.

Die Delayfunktion ist deutlich kürzer zu lesen, aber auch mit 
ausführlichem Kommentar unanschaulicher. Aber Speicherplatz auf dem 
Rechner ist ja hoffentlich dafür kein Problem.

Was passiert, wenn ich in die delay Funktion einen Wert eintrage, der 
kürzer ist als ein nop? Gibt das eine Fehlermeldung, oder krieg ich 
einfach die Kurve nicht und flieg raus? Was ist, wenn ich einen Wert 
vorgebe, der mit dem Raster der nops nicht passt? Die nops geben mir 
eine auf den Controller bezogene Quantisierung der Zeit vor. Ich kann 
nicht darunter gehen und auch keine Bruchstücke der Zeitabschnitte 
verwenden.

Oder sehe ich das zu verquer?

> Vielleicht sollte ich mir öfter alte, vertraut erscheinende Bekannte
> ansehen...
>

Immer. ;O)

Mit freundlichem Gruß: Bernd Wiebus alias dl1eic
http://www.dl0dg.de

von Falk B. (falk)


Lesenswert?

@ Bernd Wiebus (berndwiebus) Benutzerseite

>> danke für die Antwort. Wenn die _delay- Funktionen mit float arbeiten
>> (was ich implizit immer ausgeschlossen habe) mit sind die nop-Sammlungen
>> tatsächlich obsolet geworden.

>Warum sind solche nop-Sequenzen denn unübersichtlicher als die Delay
>Funktion?

Eben weil es NOP-Sequenzen sind. Riesig groß, nehmen viel Raum und 
Aufmerksamkeit ein, mehr als ihnen gebührt. Ausserdem sind sie 
taktfrequenzabhängig. Will man mal die CPU-Frequenz ändern, warum auch 
immer, muss man wieder rumfummeln.

>Immerhin gibt dir die nop-Kette mit den Kommentaren einen
>Anschaulicheren Überblick, wie sich die Pause zusammensetzt.

Sinnlose Lyrik.

>Die Delayfunktion ist deutlich kürzer zu lesen, aber auch mit
>ausführlichem Kommentar unanschaulicher.

Nö. Kurz und prägnant auf den Punkt gebracht.

>Was passiert, wenn ich in die delay Funktion einen Wert eintrage, der
>kürzer ist als ein nop? Gibt das eine Fehlermeldung, oder krieg ich
>einfach die Kurve nicht und flieg raus?

Die Funktion sorgt dafür, dass die angegebene Zeit MINDESTENS 
eingehalten wird, manchmal ist sie halt einen Tick, ähhh NOP länger.

von Nicolas S. (Gast)


Lesenswert?

Bernd Wiebus schrieb:
> Warum sind solche nop-Sequenzen denn unübersichtlicher als die Delay
> Funktion?
> Immerhin gibt dir die nop-Kette mit den Kommentaren einen
> Anschaulicheren Überblick, wie sich die Pause zusammensetzt.

Die nop-Kette gibt einen schönen, intuitiven Überblick darauf, wo Zeit 
verbraucht wird. Aber ich erwische mich immer wieder dabei, mich zu 
verzählen (wem ist eigentlich aufgefallen, daß im obigen Beispiel nicht 
8 sondern nur 7 NOPs waren?).

Und ein weiterer Hintergrund: Gerade bei den Pollin-KS0108-LCDs habe ich 
ordentliche Exemplarsteuerungen, was das notwendige delay zwischen 
enable und busy-flag angeht (die grünen brauchen irgendwie immer länger. 
Und bei den grünen ist die LED-Spannungsversorgung andersherum, stimmt 
hier zufällig mit dem Aufdruck überein). Hier einfach einen Zahlenwert 
als Konstante hinterlegen zu können hat durchaus Vorteile.

Viele Grüße
Nicolas

von Stefan E. (sternst)


Lesenswert?

Bernd Wiebus schrieb:
> Die Delayfunktion ist deutlich kürzer zu lesen, aber auch mit
> ausführlichem Kommentar unanschaulicher.

Hä? Selbst ohne jeden Kommentar steht dann doch exakt da, um was es 
geht, nämlich den Programmablauf um eine bestimmt Zeit zu verzögern. 
Sogar die Zeit selber sieht man sofort.

Bernd Wiebus schrieb:
> Was passiert, wenn ich in die delay Funktion einen Wert eintrage, der
> kürzer ist als ein nop? Gibt das eine Fehlermeldung, oder krieg ich
> einfach die Kurve nicht und flieg raus? Was ist, wenn ich einen Wert
> vorgebe, der mit dem Raster der nops nicht passt?

Die Anzahl der zu "verplempernden" Cycles wird immer auf die nächste 
ganze Zahl aufgerundet.

von Sven (Gast)


Lesenswert?

Probiers doch mal mit der Preprocessor library von boost:
http://www.boost.org/doc/libs/1_54_0/libs/preprocessor/doc/index.html
1
#include <boost/preprocessor/repetition/repeat.hpp>
2
#define NOP_DECL(z, n, text) asm volatile("nop");
3
#define NOP(N) BOOST_PP_REPEAT(N, NOP_DECL, dummy)

Viele Grüße,
    Sven

von Peter D. (peda)


Lesenswert?

Solange man NOPs oder Delays nicht unter Interruptsperre ausführt, sind 
es immer Minimalzeiten.

von Bernd W. (berndwiebus) Benutzerseite


Lesenswert?

Hallo Stefan Ernst.


>> Die Delayfunktion ist deutlich kürzer zu lesen, aber auch mit
>> ausführlichem Kommentar unanschaulicher.
> Hä? Selbst ohne jeden Kommentar steht dann doch exakt da, um was es
> geht, nämlich den Programmablauf um eine bestimmt Zeit zu verzögern.
> Sogar die Zeit selber sieht man sofort.

Ok. Vergiss es. Es ist anscheinend ein persönliches Problem meiner 
Hirnstruktur.

>> Was passiert, wenn ich in die delay Funktion einen Wert eintrage, der
>> kürzer ist als ein nop? Gibt das eine Fehlermeldung, oder krieg ich
>> einfach die Kurve nicht und flieg raus? Was ist, wenn ich einen Wert
>> vorgebe, der mit dem Raster der nops nicht passt?
>
> Die Anzahl der zu "verplempernden" Cycles wird immer auf die nächste
> ganze Zahl aufgerundet.

Danke! Klare Aussage.

Mit freundlichem Gruß: Bernd Wiebus alias dl1eic
http://www.dl0dg.de

von Dr. Sommer (Gast)


Lesenswert?

Für die, die sich schon immer gefragt haben wie man in C++ ohne Makros 
eine feste NOP-Sequenz generieren kann (just for fun ;-) ):
1
template <unsigned int N>
2
struct StaticLoop {
3
  template <typename F>
4
  __attribute__((always_inline)) inline static void run (F f) {
5
    f ();
6
    StaticLoop<N-1>::run (f);
7
  }
8
};
9
10
template <>
11
struct StaticLoop<0> {
12
  template <typename F>
13
  __attribute__((always_inline)) inline static void run (F f) {
14
  }
15
};
16
17
int main () {
18
  StaticLoop<13>::run ([] { asm volatile ("nop"); });
19
}
Benötigt leider GCC-spezifische Attribute um keine unnötigen 
Funktionsaufrufe zu generieren und klappt auch nur mit eingeschalteten 
Optimierungen. Die delay Funktion ist wohl onehin besser da sie den 
CPU-Takt mit einberechnet. Vielleicht kann das hier ja jemand für 
allgemeine statische Schleifen gebrauchen :-)

von G++ (Gast)


Lesenswert?

Attribute sollten doch ab 4.8.1 auch schöner gehen:
always inline
Das ist C++11!
In (gc)C scheint das aber nicht vorgesehen zu sein. Aber deine Templates 
ja auch nicht ;-)

von Dr. Sommer (Gast)


Lesenswert?

G++ schrieb:
> Attribute sollten doch ab 4.8.1 auch schöner gehen:
Ich weiß... aber wie du selbst siehst... ;-)

G++ schrieb:
> Aber deine Templates ja auch nicht ;-)
Wieso, die funktionieren doch?!

von G++ (Gast)


Lesenswert?

Es ging um die Frage, ob gcc auch in C ( mit ohne ++) diese Attribute 
kann. Und das es im Fall deines Codes ja egal wäre, da der eh C++ ist. 
Jetzt klar?

von Dr. Sommer (Gast)


Lesenswert?

Achso, ja. Naja, nach C war nicht explizit gefragt, und "gcc" nach "g++" 
im makefile ändern ist aufwandstechnisch vertretbar ;)

von Nicolas S. (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Naja, nach C war nicht explizit gefragt,

Och, für mich ist die ursprüngliche Fragestellung seit der Erkenntnis, 
daß _delay_XX auch float versteht gegessen. Das und ein bischen 
Hühnerfutter, das hoffentlich morgen per Post kommt, reichen mir völlig 
aus, um ein gelungenes Wochenende zu versprechen.

Insofern stört mich das nicht, wenn hier über g++ oder das Wetter 
diskutiert wird :).

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.