Forum: Compiler & IDEs Inline ASM: exakte Verzögerung


von Kurt (Gast)


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

von Falk B. (falk)


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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> _delay_us() bzw. _delay_ms() ...

Wobei das die `convenience functions' sind.  _delay_loop_1() und
_delay_loop_2() sind die zugehörigen Basisfunktionen.

Exakt gesagt sind das übrigens keine Makros sondern inline-Funktionen.
Aber das hat rein technische Gründe.

von Kurt (Gast)


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

von Peter D. (peda)


Lesenswert?

Kurt wrote:
> ich möchte einen möglichst exakten Zähler bauen, um mein Program exakt
> verzögern zu können.

Was stört Dich daran, einen Timer zu benutzen ?

Damit gehts auf den Zyklus genau, exakter gehts nicht.


Peter

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

von Rolf Magnus (Gast)


Lesenswert?

> Damit gehts auf den Zyklus genau,

Naja, nicht ganz.

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.