preprocessor loop



  • Hallo,
    ich brauche für mein Projekt eine genaue Anzahl an "leeren" Befehlen als eine Art Delay.
    Letztendlich soll es eigentlich dem hier entsprechen:

    uint32_t i = (frequency/1000000) * delay_us;
    for(; i; --i)
        asm("nop");
    

    Nur verursacht die Schleife leider einen derart großen Overhead, dass nicht einmal annähernd die Zeit stimmt. Ich brauche aber eine Genauigkeit von +/- 2us, was vermutlich letztendlich nur durch bereits ausgeschriebene nop-Befehle ermöglicht wird. Um die nicht überall im Code herumstehen zu haben, brauche ich deswegen eine preprocessor-Schleife.

    Hat da jemand einen Tipp oder sogar ein Stück Code, mit dem das möglich ist?

    Danke!


  • Mod

    Klingt nach einem XY-Problem. Kann es sein, dass du in Wirklichkeit ein sleep suchst?



  • SeppJ schrieb:

    Klingt nach einem XY-Problem. Kann es sein, dass du in Wirklichkeit ein sleep suchst?

    Ja. Gibt es aber für das Gerät nicht fertig.
    -> muss ich mir selbst erstellen.
    Es geht hier um keinen PC sondern um einen µC.
    Auf dem PC wäre das alleine durch das OS schwachsinnig.


  • Mod

    Von wie vielen Wiederholungen und welcher Genauigkeit sprechen wir hier? Mit dem Präprozessor kann man realistisch ein paar hundert Wiederholungen eines Codestücks erzeugen, darüber hinaus (oft bei 255) wird man Probleme mit der maximalen Rekursionstiefe bekommen (Der Präprozessor kennt keine Schleifen, nur Rekursion).

    Du könntest also ein Makro schreiben das bis zu 255 Mal ein einzelnes NOP erzeugt. Dann ein weiteres Makro, das bis zu 255 Mal ein 256-faches NOP erzeugt. Und falls das noch nicht reicht, ein Makro, das bis zu 255 Mal ein 65536-faches NOP erzeugt. Daraus kannst du dann alle Werte zwischen 0 und 16.7 Millionen erzeugen. Oder falls du gar nicht so einen großen Wertebereich oder so eine große Genauigkeit brauchst, lässt du einen Teil der Lösung weg.

    Alternativ werfe ich mal in den Raum, dass du deine Zählschleife einfach am Anfang des Programms eichst. Einfach mal ein bisschen zählen lassen und dabei die Zeit stoppen. Dann hast du die wahre Frequenz für die Dauer der nop-Zählschleifen. Das sollte wesentlich einfacher, flexibler, und übersichtlicher sein als alles Makrogefrickel.



  • wie wäre es mit einem timer, der eine variable setzt, und einer schleife? also quasi

    void MySleep(int usec)
    {
         int stop = 0;
    
         //timer setzen
    
         while(!stop);
    }
    


  • SeppJ schrieb:

    Von wie vielen Wiederholungen und welcher Genauigkeit sprechen wir hier? Mit dem Präprozessor kann man realistisch ein paar hundert Wiederholungen eines Codestücks erzeugen, darüber hinaus (oft bei 255) wird man Probleme mit der maximalen Rekursionstiefe bekommen (Der Präprozessor kennt keine Schleifen, nur Rekursion).

    Es geht darum, auch verschiedene Anzahlen von Wiederholungen mit einem Makro abzudecken. Das kann von 100 bis ca. 2^26 Wiederholungen reichen.
    Es geht um ca. 2^26 Wiederholungen mit einer Genauigkeit von +- 50 Wiederholungen.

    Alternativ werfe ich mal in den Raum, dass du deine Zählschleife einfach am Anfang des Programms eichst. Einfach mal ein bisschen zählen lassen und dabei die Zeit stoppen. Dann hast du die wahre Frequenz für die Dauer der nop-Zählschleifen. Das sollte wesentlich einfacher, flexibler, und übersichtlicher sein als alles Makrogefrickel.

    Viel zu ungenau. Und als einfacher würde ich das definitiv nicht erachten. Da wäre es leichter, jedes Mal im erstellten ASM-Code die Instructions zu zählen.

    Wade1234 schrieb:

    wie wäre es mit einem timer, der eine variable setzt, und einer schleife? also quasi

    void MySleep(int usec)
    {
         int stop = 0;
    
         //timer setzen
    
         while(!stop);
    }
    

    Darauf wird es wohl hinauslaufen. Ich hatte gehofft, ohne Timer auszukommen.

    Danke aber euch beiden!


  • Mod

    fluggi schrieb:

    Viel zu ungenau. Und als einfacher würde ich das definitiv nicht erachten.

    Wieso? Ich glaube nicht, dass du meinen Vorschlag richtig verstanden hast, wenn dir das nicht als einfach und genau einleuchtet. Du sollst genau das machen, was dein eigener Vorschlag war, bloß sollst du nicht die Schleifeninstruktionen selbst vernachlässigen, sondern zuvor messen, wie lange diese benötigen. Falls dein µC wirklich so primitiv ist, dass dein erster Vorschlag mit der Taktfrequenz funktioniert hätte (was ein ziemlich dickes "falls" ist, aber nicht ausgeschlossen), dann wird dieser Vorschlag wortwörtlich so genau gehen wie ein Uhrwerk. Und es wäre exakt der gleiche Code, bloß ein zuvor gemessener Wert für frequency .

    Es geht darum, auch verschiedene Anzahlen von Wiederholungen mit einem Makro abzudecken. Das kann von 100 bis ca. 2^26 Wiederholungen reichen.
    Es geht um ca. 2^26 Wiederholungen mit einer Genauigkeit von +- 50 Wiederholungen.

    Dann geht mein anderer Vorschlag ja auch locker, bloß eben mit 50 NOPs als kleinster Einheit. Es darf natürlich auch ein zentrales Steuermakro geben, das dann drei Parameter auf die drei Untermakros verteilt.

    Allgemein glaube ich aber, dass du mit Makros auf dem Holzweg bist und einen der anderen Vorschläge nehmen solltest. Daher gehe ich auch nicht weiter auf die Details ein. Es ist eher als Hinweis zu verstehen, dass es auf deine Eingangsfrage auch eine Antwort gäbe, bloß halte ich dies nicht für eine gute Lösung für das eigentliche Problem.



  • fluggi schrieb:

    Ich hatte gehofft, ohne Timer auszukommen.

    Hardware-Timer sind das Beste und sehr genau.

    Idealerweise startet man einen Timer und schickt den Controller schlafen. Durch einen Timer-Interrupt wird er wieder aufgeweckt.



  • @fluggi

    Progger0815 schrieb:

    Hardware-Timer sind das Beste und sehr genau.

    Idealerweise startet man einen Timer und schickt den Controller schlafen. Durch einen Timer-Interrupt wird er wieder aufgeweckt.

    Da hat Progger 0815 recht. Das mit nops und Makros ist zwischen foolig und Bastler und geht eh nur, wenn der Prozessor sonst nichts zu tun hat.

    2 µs ist nichtmal besonders ambitioniert, aber mit HW- Timern fährt man richtig. Kann man mit Makros konfigurieren, einfacher ist es auf jeden Fall, die in normalem Code zu schreiben und Makros nur zur Steuerung herzunehmen.

    Eigentlich ein exzellenter Anlaß, sich mal mit Timer- und Interruptprogrammierung auseinanderzusetzen. Du wirst dich hinterher ärgern, überhaupt über den nop- Kram mit Makros nachgedacht zu haben. 🙂


Anmelden zum Antworten