Inline ASM: exakte Verzögerung

Gast #664888
Lesenswert?

Hallo,

ich möchte einen möglichst exakten Zähler bauen, um mein Program exakt 
verzögern zu können. Dazu möchte ich Inline ASM in einem C Programm 
einsetzen, habe aber damit meine liebe Not.

Einer Funktion wird ein "unsigned char length" übergeben. Dieser Wert 
gibt an, wie lange verzögert werden soll.

Ich habe geschrieben:
asm volatile (  "  ld r2, 0"    "\n\t"
    "start:  add r2, 1"  "\n\t"
    "  cp r2, %e0"  "\n\t"
    "  brge start"
    :
    : "e" (length)
    : "r2"
      );
Zunächst soll in Register r2 eine Null geladen werden, die anschließend 
um eins inkrementiert wird. Anschließend soll dieser Wert mit den 
übergebenen Wert (length) verglichen werden und, wenn r2 kleiner als 
length ist, wieder nach oben gesprungen werden.

So verzögere ich zwei Taktzyklen pro Durchlauf mit einem "Overhead" zu 
Beginn von einem Taktzyklus.

Nur leider klappt das ganze nicht s, wie ich mir das vorstelle.
AVRStudio sagt:
Build started 28.9.2007 at 16:04:42
avr-gcc.exe  -mmcu=atmega32 -Wall -gdwarf-2 
-DF_CPU=8000000UL -Os -fsigned-char -MD -MP -MT sequence.o -MF 
dep/sequence.o.d  -c  ../sequence.c
C:\DOKUME~1\User\LOKALE~1\Temp/ccGZhlMJ.s: Assembler messages:
C:\DOKUME~1\User\LOKALE~1\Temp/ccGZhlMJ.s:693: Error: pointer register 
(X, Y or Z) required
make: *** [prg.o] Error 1
Build succeeded with 0 Warnings...

gcc plug-in: Error: Object file not found on expected location 
D:\Programmierung\Prg\default\Prg.elf

Ich bin über Hinweise, wie ich meinen Fehler korrigieren kann oder 
meinen Zähler verbessern kann, dankbar :-)

Gruß

Kurt
#664891
Lesenswert?

@ Kurt (Gast)

>ich möchte einen möglichst exakten Zähler bauen, um mein Program exakt
>verzögern zu können. Dazu möchte ich Inline ASM in einem C Programm
>einsetzen, habe aber damit meine liebe Not.

Erfinde das Fahrrad nicht neu. Für kurze Verzögerungen gibt es 
_delay_us() bzw. _delay_ms(), die SIND ASM Makros und die SIND sehr 
genau.
Längere genaue Verzögerungen macht man über einen Timer.

>Ich bin über Hinweise, wie ich meinen Fehler korrigieren kann oder
>meinen Zähler verbessern kann, dankbar :-)

Zähler baut man mit Timern.

MFG
Falk
Gast #665115
Lesenswert?

Ich habe es mit _delay_us() versucht, habe schlechte Ergebnisse erhalten 
und bin dann in der AVR-Lib Doku auf folgendes gestoßen:

"In order for these functions to work as intended, compiler 
optimizations must be enabled, and the delay time must be an expression 
that is a known constant at compile-time. If these requirements are not 
met, the resulting delay will be much longer (and basically 
unpredictable), and applications that otherwise do not use 
floating-point calculations will experience severe code bloat by the 
floating-point library routines linked into the application."

Meine Vorgabe ist zur Compile-Zeitnicht konstant, daher funktioniert bei 
mir _delay_us() nicht. Also muss ich es selbst machen.

Hat denn keine eine Idee, weshalb mein Inline ASM nicht funktioniert?

Gruß und danke...

Kurt
Moderator Persönliche Seite #665141
Lesenswert?

Kurt wrote:

> Meine Vorgabe ist zur Compile-Zeitnicht konstant, daher funktioniert bei
> mir _delay_us() nicht. Also muss ich es selbst machen.

Nein, musst du nicht.  Davon abgesehen, dass der Timer wohl wirklich
die bessere Variante wäre, siehe:

Beitrag "Re: Inline ASM: exakte Verzögerung"

Wenn du's partout selbst schreiben willst, kannst du dir zumindest
die dort referenzierten Funktionen als Vorlage nehmen.  Diese
Funktionen stehen übrigens mittlerweile in <avr/delay_basic.h>,
nicht mehr in <avr/delay.h> (welches aber delay_basic.h mit
einschließt).  Der Grund ist einfach, dass <avr/delay.h> Warnungen
produzieren soll, falls F_CPU nicht gesetzt ist oder ohne Optimierung
compiliert wird, während diese Warnungen für die Funktionen in
delay_basic.h nicht sinnvoll sind.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren