mikrocontroller.net

Forum: Compiler & IDEs ARM GCC Assemblerprogrammierung


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Martin O. (ossi-2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
static inline int32_t asmDelay(int32_t val)  { 
  asm volatile("loop%=:  subs  %0, %0, #1     \n\t"
               "         nop                  \n\t"
               "         bne   loop%=         \n\t"
               :  : "r" (val) ) ;
  }

Ich habe gerade meine erste Routine in Assembler auf nem ARM 
geschrieben. Sie scheint zu funktionieren (liefert den gewünschten 
delay), aber ich bin mir nicht sicher, ob die Prorammierung wirklich in 
Ordnung ist.

Kann bitte einer der Experten mal seinen Kommentar loslassen?
Und um einer Frage gleich vorzubeugen: Ich programmiere in Assembler 
weil mir das Spass macht (ich bin Masochist).

Autor: Verzögert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gerade bei einer Delay Funktion ist es extrem wichtig diese in Assembler 
zu kodieren.

Autor: Dr. Sommer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"r" ist falsch, weil der Wert ja geändert wird. Ich meine es müsste "+r" 
sein, und bei den Output Operands gelistet werden.

Wozu das %= ?

Kennst du:
http://www.ethernut.de/en/documents/arm-inline-asm.html
https://hardwarebug.org/2010/07/06/arm-inline-asm-secrets/

Das delay ist natürlich ungenau, hängt von Flash Latenz und so ab. 
Besser macht man das mit Timern.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dr. Sommer schrieb:
> "r" ist falsch, weil der Wert ja geändert wird. Ich meine es müsste "+r"
> sein, und bei den Output Operands gelistet werden.

Jau.  Ansonsten konnte man bei

asmDelay(10);
asmDelay(10);

falschen Code bekommen.

> Wozu das %= ?

%= liefert eine für die Übersetzungseinheit eindeutige Zahl pro Inline 
Asm, so dass Code wie

asmDelay(10);
asmDelay(10);

nicht dazu führt, dass ein Label wie loop 2x auftaucht, was zu einen 
Assembler-Fehler führen würde.

Alternativ gehen lokale Labels:
static inline void asmDelay (int32_t val)
{ 
  asm volatile ("1:  subs  %0, %0, #1"   "\n\t"
                "    nop"                "\n\t"
                "    bne   1b"
                : "+r" (val));
}

Seltsam ist außerden, dass val signed ist.  Oder ist SUBS eine 
saturierte Subtraktion, so dass -1 -1 = 0 wird? (Ich kenn kein ARM-Asm).

Und asmDelay will einen Rückgabewert; alo entweder was zurückgeben oder 
void asmDelay (..).

> Das delay ist natürlich ungenau, hängt von Flash Latenz und so ab.
> Besser macht man das mit Timern.

Für längere, exakte Zeiten besser mit Timer.  Wenn es nur sehr kurze 
Zeiten sind, z.B. ne handvoll Ticks zum für eine langsame I/O Line bis 
sich Pegel stabilisiert haben, dann ist ein Delay einfacher und durchaus 
sinnvoll, da es nur um Mindestzeiten geht und Cache-, Pipeline- und 
Interrupt-Effekte nicht stören.  Außerdem verschendet man nicht einen 
ganzen Timer um 2 Ticks zu schnarchen.

: Bearbeitet durch User
Autor: Martin O. (ossi-2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Besten Dank für die hilfreichen Kommentare und Hinweise.
Wenn ich neue Probleme habe melde ich mich wieder.

Autor: Dr. Sommer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johann L. schrieb:
> Oder ist SUBS eine saturierte Subtraktion, so dass -1 -1 = 0 wird?

Nein, aber solange man nur positive Zahlen übergibt ist es egal. Bei 0 
bekommt man aber so oder so ein Problem, weil man da als Erstes einen 
Underflow bekommt und 2^32 Takte zählt. Daher am Besten als erstes auf 0 
prüfen.

Johann L. schrieb:
> Alternativ gehen lokale Labels:

Ja, so hätte ich das jetzt gemacht...

Autor: Markus F. (mfro)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
auch eine Assemblerroutine sollte irgendeinen Wert zurückliefern, wenn 
sie int32_t deklariert ist

auch wenn's hier (wahrscheinlich) keine Rolle spielt "cc" sollte in die 
Clobber list (schließlich werden die Flags verändert)

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johann L. schrieb:
> Seltsam ist außerden, dass val signed ist.  Oder ist SUBS eine
> saturierte Subtraktion, so dass -1 -1 = 0 wird? (Ich kenn kein ARM-Asm).

SUBS = SUB mit Status. Unsigned val wär zutreffender.

: Bearbeitet durch User
Autor: W.S. (Gast)
Datum:

Bewertung
-2 lesenswert
nicht lesenswert
Martin O. schrieb:
> static inline int32_t asmDelay(int32_t val)  {
>   asm volatile("loop%=:......

Solange sowas dasteht, programmierst du in C und nicht in Assembler.

W.S.

Autor: Dr. Sommer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde auch "__asm__" statt "asm" schreiben, denn dann funktioniert 
es auch mit "-std=c99" o.ä. Statt %0 bevorzuge ich es auch, den 
Registern Namen zu geben. Zusammengefasst also z.B. so:
static inline void asmDelay (uint32_t val) {
  if (val == 0) return;
  __asm__ volatile (
    "1:  subs  %[val], %[val], #1\n"
    "nop\n"
    "bne 1b\n"
    : [val] "+r" (val) : : "cc");
}

Als nicht-geinlinete normale Funktion kommt dann heraus:
00000000 <asmDelay>:
   0:  b110        cbz  r0, 8 <asmDelay+0x8>
   2:  3801        subs  r0, #1
   4:  bf00        nop
   6:  d1fc        bne.n  2 <asmDelay+0x2>
   8:  4770        bx  lr
   a:  bf00        nop

Autor: Michael F. (michaelfu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bist Du sicher, dass das NOP wirklich ausgeführt wird?

In der Doku der ganzen Cortex-M steht, dass der Core das NOP aus der 
Pipeline entfernen kann, bevor es die Execution Stage erreicht.

z.B. CM3 
https://developer.arm.com/docs/dui0552/latest/the-cortex-m3-instruction-set/miscellaneous-instructions/nop

=> die Verzögerung kann funktionieren, und wird es wahrscheinlich auch 
(fast) immer, eine Garantie dafür gibt es aber beim Cortex-M nicht.

Autor: Peter D. (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde besser einen freilaufenden Timer dafür verwenden, dann hat man 
wenigstens einen ungefähren Anhaltspunkt, wie groß das Delay wirklich 
ist.
Und die ARMs haben ja reichlich Timer bzw. der Timer kann ja noch andere 
Sachen machen.

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.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.