mikrocontroller.net

Forum: Compiler & IDEs Inline Assembler übersetztung


Autor: R. B. (p1ng)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi Leuti ich hab mal wieder ein echtes Problem ich hab ein C programm 
was nicht funktionieren will, weis auch warum find aber keine lösung in 
Assembler funktioniert das Programm. Jetzt will ich das Stück halt in 
Inline Assembler schreiben leider komm ich da absolut nicht klar. kann 
mir einer das mal schnell Übersetzte wär das möglich wäre super.

Quellcode:

EEWrite:
  out  EEARH,adressH  ;Output address
  out  EEARL,adressL  ;Output adress
  out  EEDR,data    ;Output data
  sbi  EECR,2      ;set EEPROM Write EnabLED
  sbi  EECR,1      ;set EEPROM Write EnabLED
waitEEW:
  sbic  EECR,1    ;wait for Handshake
  rjmp  waitEEW
  ret

und das in Inline-Assembler wäre echt klasse.

Gruß Renaldo

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dein bisheriger C-Code
void EEPROM_write(unsigned int uiAddress, unsigned char data)
{
  while(EECR & (1<<EEWE));
  EEAR = uiAddress;
  EEDR = ucData;
  EECR |= (1<<EEMWE);
  EECR |= (1<<EEWE);
}

entspricht nicht dem funktionierenden Assembler-Code
EEWrite:
  out  EEARH,adressH  ;Output address
  out  EEARL,adressL  ;Output adress
  out  EEDR,data    ;Output data
  sbi  EECR,2      ;set EEPROM Write EnabLED
  sbi  EECR,1      ;set EEPROM Write EnabLED
waitEEW:
  sbic  EECR,1    ;wait for Handshake
; Teste Bit 1 von EECR und überspringe nächste Anweisung,
; wenn Bit 1 gleich 0 ist
; if ((EECR & (1<<EEWE)))
  rjmp  waitEEW
; else // (EECR & (1<<EEWE)) == 0
  ret

Ein C-Code entsprechend dem Assembler-Abschnitt würde sp aussehen
void EEPROM_write(unsigned int uiAddress, unsigned char data)
{
  EEARH = uiAddress >> 8;     // siehe #)
  EEARL = uiAddress & 0x00FF; // siehe #)
  EEDR = ucData;
  EECR |= (1<<EEMWE);      // EEMWE == 2 lt. avr/iom8.h
  EECR |= (1<<EEWE);       // EEWE  == 1
  while(EECR & (1<<EEWE));
}

#) Das ist wahrscheinlich zuviel des Guten und EEAR = uiAddress; geht 
auch
http://www.mikrocontroller.net/articles/AVR_Checkl...

Autor: R. B. (p1ng)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke aber fuktioniert so auch nicht,

Naja will das ja nicht direct in Assembler in Inline-Assembler haben um 
dies zu testen weist.

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
void EEPROM_write(unsigned int addr, unsigned char value)
{
    eeprom_write_byte((uint8_t *) addr, value);
}
Ginge es so ? :O)
(<avr/eeprom.h> includen...)

hth. Jörg

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

Bewertung
0 lesenswert
nicht lesenswert
Das Problem mit dem C-Code ist, dass er das Timing nicht einhält, wenn
er nicht mit Optmimierung compiliert wird.  Aber genau dafür gibt es
ja auch <avr/eeprom.h>.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Renaldo B. wrote:
> danke aber fuktioniert so auch nicht,
>
> Naja will das ja nicht direct in Assembler in Inline-Assembler haben um
> dies zu testen weist.

Dann hast du einen anderen Bug im Programm.

Dein Assembler-Code weicht übrigens stark von dem Verfahren ab, welches 
Atmel in Datenblatt als Referenzcode angibt.

Der Vollstänigkeit halber eine 1:1 Übersetzung in Inline-ASM für C
#include "avr/io.h"

#define TEST

void __attribute__ ((noinline)) EEPROM_write(unsigned int uiAddress, unsigned char data)
{
  asm volatile (
    "out  %0+1,%B3"    "\n"
    "out  %0,%A3"      "\n"
    "out  %1,%4"       "\n"
    "sbi  %2,2"        "\n"
    "sbi  %2,1"        "\n"
    "waitEEW:"               "\n"
    "sbic  %2,1"       "\n"
    "rjmp  waitEEW"         "\n"
    "ret; Problematisch bei Inline-Optimierung!"
      :
      :
      "M" (_SFR_IO_ADDR(EEAR)),
      "M" (_SFR_IO_ADDR(EEDR)),
      "M" (_SFR_IO_ADDR(EECR)),
      "r" (uiAddress),
      "r" (data)
    );
}

#ifdef TEST
int main(void)
{
    EEPROM_write(0x5678, 0x12);
    while(1)
        ;

    return 0;
}
#endif /* TEST */

Das _attribute_ ((noinline)) ist nötig, damit GCC nicht auf die 
Optimierungsidee kommt, die Funktion als Inline-Funktion in den 
main-Code zu setze.

Durch das manuell eingefügte 'ret' im Assemblerteil wäre das tödlich für 
das Programm.

Das Listing (Ausschnitt) sieht anschliessend so aus:
0000005c <EEPROM_write>:

#define TEST

void __attribute__ ((noinline)) EEPROM_write(unsigned int uiAddress, unsigned char data)
{
  5c:  9f bb         out  0x1f, r25  ; 31
  5e:  8e bb         out  0x1e, r24  ; 30
  60:  6d bb         out  0x1d, r22  ; 29
  62:  e2 9a         sbi  0x1c, 2  ; 28
  64:  e1 9a         sbi  0x1c, 1  ; 28

00000066 <waitEEW>:
  66:  e1 99         sbic  0x1c, 1  ; 28
  68:  fe cf         rjmp  .-4        ; 0x66 <waitEEW>
  6a:  08 95         ret
  6c:  08 95         ret

0000006e <main>:
  asm volatile (
    "out  %0+1,%B3"    "\n"
    "out  %0,%A3"      "\n"
    "out  %1,%4"       "\n"
    "sbi  %2,2"        "\n"
    "sbi  %2,1"        "\n"
    "waitEEW:"               "\n"
    "sbic  %2,1"       "\n"
    "rjmp  waitEEW"         "\n"
    "ret; Problematisch bei Inline-Optimierung!"
      :
      :
      "M" (_SFR_IO_ADDR(EEAR)),
      "M" (_SFR_IO_ADDR(EEDR)),
      "M" (_SFR_IO_ADDR(EECR)),
      "r" (uiAddress),
      "r" (data)
    );
}

#ifdef TEST
int main(void)
{
  6e:  62 e1         ldi  r22, 0x12  ; 18
  70:  88 e7         ldi  r24, 0x78  ; 120
  72:  96 e5         ldi  r25, 0x56  ; 86
  74:  f3 df         rcall  .-26       ; 0x5c <EEPROM_write>
  76:  ff cf         rjmp  .-2        ; 0x76 <main+0x8>

Autor: R. B. (p1ng)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
mhh naja ich hab das problem jetzt ziemlich stark einschränken können!

Lösung Vorschlag ist so das Fuktutioniert aber so soll das nun doch 
nicht werden.

void EEPROM_write(unsigned int uiAddress, unsigned char ucData)
{
  while(EECR & (1<<EEWE));
  EEAR= uiAddress;
  EEDR = ucData;
  //  EECR |= (1<<EEMWE);      // EEMWE == bit2 lt. avr/iom8.h
  //  EECR |= (1<<EEWE);       // EEWE  == bit1

     asm volatile (
     "sbi 0x1c,2" "\r\n"
     "sbi 0x1c,1" "\r\n"
       );
}

Hier ist der Fehler im Programm aus irgend einem Grund rafft er das 
nicht!!

EECR |= (1<<EEMWE);      // EEMWE == bit2 lt. avr/iom8.h
EECR |= (1<<EEWE);       // EEWE  == bit1

Weis einer warum er das nicht rafft ? ergibt meiner meinung nach keinen 
sinn!

Autor: Stefan B. (stefan) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Was "rafft er nicht"? Wird falscher Code für die Zeilen

EECR |= (1<<EEMWE);      // EEMWE == bit2 lt. avr/iom8.h
EECR |= (1<<EEWE);       // EEWE  == bit1

produziert? Wenn ja, welcher? Und nach deiner Änderung zu asm()-Variante 
funktioniert es?

Wenn ja, dann: Welchen GCC hast du? Bei mir wird durch WinAVR 20070122 
(GCC 4.1.1) bei beiden Varianten der gleiche Code produziert. 
Einstellungen im Makefile s. Anhang (Optimierung: s)

Mein Listing (test.lss, Ausschnitt):
void EEPROM_write(unsigned int uiAddress, unsigned char ucData)
{
  5c:  e1 99         sbic  0x1c, 1  ; 28
  5e:  fe cf         rjmp  .-4        ; 0x5c <EEPROM_write>

  while(EECR & (1<<EEWE));

  EEAR = uiAddress;
  60:  9f bb         out  0x1f, r25  ; 31
  62:  8e bb         out  0x1e, r24  ; 30

  EEDR = ucData;
  64:  6d bb         out  0x1d, r22  ; 29

  // ASM-Version
     asm volatile (
  66:  e2 9a         sbi  0x1c, 2  ; 28
  68:  e1 9a         sbi  0x1c, 1  ; 28
     "sbi 0x1c,2" "\r\n"
     "sbi 0x1c,1" "\r\n"
       );

  // C-Version
  EECR |= (1<<EEMWE);      // EEMWE == bit2 lt. avr/iom8.h
  6a:  e2 9a         sbi  0x1c, 2  ; 28
  EECR |= (1<<EEWE);       // EEWE  == bit1
  6c:  e1 9a         sbi  0x1c, 1  ; 28
  6e:  08 95         ret
}

Autor: R. B. (p1ng)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ICh danke euch für eure Hilfe wir wissen warum es nicht geht es liegt am 
Compeiler wir hätten uns noch dusselig suchen können fals es 
Interressiert ich benutze das myAVR Workpad

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.