www.mikrocontroller.net

Forum: Compiler & IDEs AVR GCC inline assembler problem


Autor: ajax (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

folgendes Problem bringt mich zur Verzweiflung: Mit folgendem Code 
schreibe ich Werte in den Flash-Speicher. Der Funktion wird die 
Flash-Page und ein Pointer auf die zu schreibenden Daten übergeben. Aber 
aus irgendwelchen Gründen wird das erste Wort in der Flash-Page immer 
mit 0 beschrieben, die restlichen Wert sind korrekt. Ich habe schon 
alles Mögliche probiert, aber der erste Wert bleibt 0.

Ich verwende einen Atmega8, so langsam glaube ich an einen Bug.

static void write_page(uint16_t page,uint16_t *data)
{
  volatile uint16_t wert,n;
  volatile uint16_t seite;

  cli();

  seite=page;
  seite=seite*(PAGESIZE/2); // für Atmega8 um 5 bit nach links schieben

  // page buffer laden
  for(n=0;n<(PAGESIZE);n+=2) // Atmega8 Page Buffer Worte: 32
  {
    wert=*data++;

    asm volatile("\n\t"
      "nop  \n\t"
      "movw r30, %[wortadresse]  \n\t"  // z Register mit Adresse laden
      "movw r0, %[flashwert]  \n\t"  // z Register mit Adresse laden
          :                  // output Argument Liste ( keine )
      :[wortadresse] "w" (n),[flashwert] "w" (wert)      // input 
Argument Liste ( w fuer word )
      );

    SPMCR = (1<<SPMEN); // write pagebuffer flag
    asm volatile ( "spm" );
    while ((SPMCR & (1<<SPMEN)) == 1); //warten bis fertig
  }
  asm volatile ( "clr _zero_reg_ " );

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

Bewertung
0 lesenswert
nicht lesenswert
Genau dafür gibt es fertige, erprobte und debuggte Routinen (auch
,,nur'' in inline asm letztlich) in der avr-libc in <avr/boot.h>.

Autor: ajax (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Jörg,

besten Dank für die schnelle Antwort. Ich hatte keine Ahnung, dass in 
der avr-libc schon fertige Routinen vorhanden sind. Da hätte ich mir 
doch glatt 2 Tage Arbeit sparen können.

Trotzdem hätte mich der Fehler in meiner Routine interessiert. Ich habe 
den Inline-Assembler zum ersten Mal verwendet.

Das Interessante ist, dass wenn man die Routine im AVR-Studio-Simulator 
debugged alle Register richtig geladen werden und das Programm damit 
wohl auch korrekt funktionieren sollte.
Wenn man die Zeile

wert=*data++;

durdh

wert=0x1234;

ersetzt, wird der Flashspeicher im echten Prozessor korrekt beschrieben.
Untersucht man den Code mit dem Simulator und macht einen Speicherdump, 
ist auch das Array richtig initialisiert.

Aber es ist und bleibt dabei, das erste Wort im echten Flash ist 0, 
falls man das Array verwendet.

In der avr-libc ist am Amfang der Routine eine Abfrage ob EEPROM Zyklen 
abgeschlossen sind. Diese Abfrage habe ich in meinem Code nicht drin, da 
ich das EEPROM nicht beschreibe. Sollte es eventuell doch aus anderen 
Gründen notwendig sein?

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

Bewertung
0 lesenswert
nicht lesenswert
ajax wrote:

> Trotzdem hätte mich der Fehler in meiner Routine interessiert.

Du müsstest vielleicht als erstes damit anfangen, den tatsächlich
für alles generierten Assemblercode mal anzusehen.

Was mir auf jeden Fall auffällt: zuerst kommt ein Stück inline
asm, dann aber, wenn es wirklich zeitkritisch wird (SPM muss ja
innerhalb eines Zeitfensters nach SPMEN ausgeführt werden),
schiebst du noch extra C-Code rein.

> Aber es ist und bleibt dabei, das erste Wort im echten Flash ist 0,
> falls man das Array verwendet.

Du könntest den Prozessor durch einen ATmega88 upgraden und dann
mit debugWire auf der echten CPU live nachsehen.

> In der avr-libc ist am Amfang der Routine eine Abfrage ob EEPROM Zyklen
> abgeschlossen sind. Diese Abfrage habe ich in meinem Code nicht drin, da
> ich das EEPROM nicht beschreibe. Sollte es eventuell doch aus anderen
> Gründen notwendig sein?

Nicht, dass ich wüsste, aber ich habe das auch noch nicht praktisch
gemacht.

Autor: ajax (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Was mir auf jeden Fall auffällt: zuerst kommt ein Stück inline
>asm, dann aber, wenn es wirklich zeitkritisch wird (SPM muss ja
>innerhalb eines Zeitfensters nach SPMEN ausgeführt werden),
>schiebst du noch extra C-Code rein.

In der Hinsicht war es mir auch etwas unwohl, aber andererseits: Was 
soll der Compiler gross zwischen Register setzen und dem SPM-Befehle 
machen?:

125:          SPMCR = (1<<SPMEN); // write pagebuffer flag
+00000EAA:   BF47        OUT     0x37,R20         Out to I/O location
126:          asm volatile ( "spm" );
+00000EAB:   95E8        SPM                      Store program memory

(Wie man sieht, passt's)

Aber irgendwie habe ich heute keinen guten Programmiertag. Auf die 
schnelle habe ich mal die Routine

void boot_program_page (uint32_t page, uint8_t *buf)

aus der avr-libc eingebunden. Und was erhalte ich:

avr-gcc.exe -mmcu=atmega8 -Wl,--section-start=.text=0x1c00 
chBootloader.o     -o chBootloader.elf
chBootloader.o: In function `boot_program_page':
../chBootloader.c:87: undefined reference to `eeprom_busy_wait'
../chBootloader.c:89: undefined reference to `boot_page_erase'
../chBootloader.c:90: undefined reference to `boot_spm_busy_wait'
../chBootloader.c:99: undefined reference to `boot_page_fill'
../chBootloader.c:102: undefined reference to `boot_page_write'
../chBootloader.c:103: undefined reference to `boot_spm_busy_wait'
../chBootloader.c:108: undefined reference to `boot_rww_enable'
make: *** [chBootloader.elf] Error 1
Build failed with 7 errors and 0 warnings...

Trotz "#include <avr/pgmspace.h>"

Bin ich jetzt völlig daneben?

Autor: ajax (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Halt, Komando zurück, war mein Fehler, boot.h vergessen.

Es ist schon spät, ich glaub, ich mach morgen weiter....

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.