mikrocontroller.net

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


Autor: Kurt (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht 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

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

Bewertung
0 lesenswert
nicht 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.

Autor: Kurt (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

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

Bewertung
0 lesenswert
nicht 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.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Damit gehts auf den Zyklus genau,

Naja, nicht ganz.

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.