mikrocontroller.net

Forum: Compiler & IDEs Präprozessor: Variable Anzahl von "nop"s?


Autor: Michael Z. (incunabulum)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für die Ansteuerung eines Displays (KS108, lib von Ape) würde ich gerne 
die Anzahl der "nop" Instruktionen je nach Prozessortakt konfigurierbar 
machen.

Für einen einzelnen Taktschritt verwende ich:
#define nop() asm volatile("nop")

Was ich nun gerne hätte wäre sowas wie
 nop(4) 
das mir genau 4 nop-Instruktionen mittels Präprozessor erzeugt. Die 
Anzahl soll dann in einer Config-Datei als #define anpassbar sein.

Kann man sowas per Präprozessor hinbekommen? Wenn ja, wie? Irgendwie 
steh ich da auf dem Schlauch bzw. mir fehlt die Erfahrung....

Rekursion? Geht sowas wie:
#define nop(x)   asm volatile("nop"); nop(x-1)
Nur wie bekomme ich dort die Abbruchbedingung (x > 0) rein?

Danke, Michael

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Michael Z. (incunabulum)

>Für die Ansteuerung eines Displays (KS108, lib von Ape) würde ich gerne
>die Anzahl der "nop" Instruktionen je nach Prozessortakt konfigurierbar
>machen.

http://www.mikrocontroller.net/articles/AVR-GCC-Tu...

MFG
Falk

Autor: Michael Z. (incunabulum)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schön, nur was mach ich, wenn ich eine Wartezeit von min. 450 ns 
einhalten muss und die Wartezeit möglichst gering sein soll?

In meinem Fall ist eine Funktion ist sehr zeitkritisch, da sie vielfach 
je Page für das Display aufgerufen wird. Eine Verzögerung von 1000 ns = 
1 µs ist hier sichtbar langsamer verglichen mit 6 nop-Commands = ca. 500 
ns.

Daher meine Idee, mir ein entsprechendes Makro zu schreiben....

cu, Michael

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Michael Z. (incunabulum)

>1 µs ist hier sichtbar langsamer verglichen mit 6 nop-Commands = ca. 500
>ns.

Optimierung eingeschaltet?

>Daher meine Idee, mir ein entsprechendes Makro zu schreiben....

Die gibt es schon, siehe Doku der libc.

MFG
Falk

Autor: let (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
_delay_us(0.5) schon probiert? Wenn dir das zu grob ist könntest
du dir noch eine Handvoll Makros mit fester Verzögerung schreiben.

Autor: chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das geht so, solltest du es noch benötigen

#define nop(x) nop##x()

#define nop0()
#define nop_(x) asm volatile(#x)
#define nop1() nop_(nop)
#define nop2() nop_(nop ; nop)
...

Autor: Michael Z. (incunabulum)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@let:
_delay_us() kann ich mit double-Werten füttern, da hast du recht. Dies 
hatte ich nicht bedacht.

_delay_us() ruft intern _delay_loop_1() auf. Diese braucht je "count" 
genau 3 Taktzyklen, so dass ich nur folgende Delays erreichen könnte: 
3,6,9,... Zyklen + einmaling einen Overhead für die Register.

@Falk: Optimierung ist an, klar. Für eine Verzögerung von 450 ns sind 
8-9 Takte nötig. Dies kann ich mit den avr-libc Funktionen erreichen.

Nenn es Erbsenzählerei, aber ich habe Feuer gefangen, wie man dies exakt 
per Makro auch für delays von 2-3 Zyklen erzielen kann. Mal schauen, was 
der Präprozessor da alles kann.

Alternativ ginge für größere Zyklenzahlen auch sowas: 
Beitrag "AVR: Delay 7 ... 65542 Zyklen"

Michael

Autor: risu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn Du weder die "_delay_us(..)" noch so viele "nop" verwenden willst, 
schreibe Dir eine Inline-Stub-Funktion -- etwa so:

void inline cyc4(uint16_t cnt) {
    asm volatile (
      "0: sbiw %0,1" "\n\t"
      "brne 0b"
      :
      : "w" (cnt)
    );
}

Diese Funktion benötigt (4*cnt)+1 Zyklen.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für kurze parametrisierbare Delays:
https://www.redhat.com/docs/manuals/enterprise/RHE...

Autor: Michael H. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo, wie wäre es mit edelay. Das ist doch genau das was du suchst.

http://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=402820

Autor: Michael Z. (incunabulum)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wow, da habe ich jetzt ja gleich die Auswahl, welche Möglichkeit ich für 
sehr geringe Delayzeiten (< 10 Takte) verwenden kann.

@chirs: Genau soetwas habe ich gesucht, bin allerdings an meinen 
Präprozessor-Kenntnissen gescheitert. Einfach Rekursion geht ja leider 
nicht.

@risu: Eine schöne Inline-Funktion, die auch ich asm-Banause noch 
halbwegs verstehe.

Und die Roboternetz-Variante erschlägt per Präprozessor fast alles, was 
man sich vorstellen kann. Wunderbar.

Danke, Michael

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

Bewertung
0 lesenswert
nicht lesenswert
Michael Z. wrote:

> _delay_us() ruft intern _delay_loop_1() auf. Diese braucht je "count"
> genau 3 Taktzyklen, so dass ich nur folgende Delays erreichen könnte:
> 3,6,9,... Zyklen + einmaling einen Overhead für die Register.

Dann bau sie so um, dass der Rest der Zyklenzahl bei einer Division
durch 3 dann als NOPs aufgefüllt wird.  Wenn du's gemacht hast, schick
es der avr-libc als Patch, damit andere auch was davon haben.

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.