mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AVR pgm_read_word_far(.) liefert quatsch


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: Ole J. (ojepsen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo liebe Leute,

ich arbeite mit einem ATmeag1284P und versuche gerade meinem Bootloader 
beizupulen, dass er die Application (Addr: 0x000000000) zur sicherheit 
an die Mitte des Flashspeichers (0x0000F000) kopiert.
Eigentlich klappt dies auch, allerdings sind nur die ersten 2 Bytes 
immer 0xFFFF, obwohl dort 0x4CC0 steht!?

Ich habe das ganze auch beim debuggen gesehen. Nach dem auslesen von 
Addr 0x00000000 gibt er immer 0xFFFF zurück...?

Hier mein Code:
//Ausruf:
_flashCopy(0x00000000, 0x0000F0000, 0x0000F0000);

bool _flashCopy(uint32_t srcAddr, uint32_t dstAddr, uint32_t byteCount)
{
  bool ret = true;
  uint8_t sreg;
  
  /* Disable interrupts */
  sreg = SREG;
  cli();
  uint32_t addr;
  uint32_t page = dstAddr;
  uint32_t count;
  uint16_t value16;
  for (addr = srcAddr, count = 0 ; addr < (srcAddr + byteCount) ;)
  { 
    if(count == 0)
    {
      eeprom_busy_wait ();
      boot_page_erase (page);
      boot_spm_busy_wait ();      /* Wait until the memory is erased. */
    }
    value16 = pgm_read_word_far(addr);
    
    boot_page_fill (page + count, value16);
    if(count >= SPM_PAGESIZE-2)
    {
      boot_page_write (page);
      boot_spm_busy_wait();
      count = 0;
      page+=SPM_PAGESIZE;
    }
    else
      count += 2;
      
    addr  += 2;
  }
  /* Re-enable interrupts (if they were ever enabled). */
  SREG = sreg;
  return ret;
}

Vielleicht habe ich auch etwas vergessen oder übersehen!? hat jemand 
einen Tipp woran es liegen könnte?

Gruß und Danke im Voraus!

Autor: Ole J. (ojepsen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hat wirklich niemand eine Idee warum pgm_read_word_far() bei der ersten 
"page addr" immer 0xffff zu liefern scheint?!

Gruß

Autor: Stefanus F. (Firma: Äppel) (stefanus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nee, keine Idee.

Autor: Marc V. (Firma: Vescomp) (logarithmus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ole J. schrieb:
> Hat wirklich niemand eine Idee warum pgm_read_word_far() bei der ersten
> "page addr" immer 0xffff zu liefern scheint?!

 Probiere mal so:
 for (addr = srcAddr, count = 0 ; addr < (srcAddr + byteCount); addr +=2)

 Keine Ahnung ob das hilft, aber for variable sollte nicht im loop
 modifiziert werden, sondern in der Deklaration.
 Es ist übersichtlicher und gibt dem Compiler die Möglichkeit, mit
 Registern zu arbeiten.

Autor: Harry L. (mysth)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde zum Testen mal alle Compiler-Optimierungen abschalten.

Autor: Chaos Programmierer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Harry L. schrieb:
> Ich würde zum Testen mal alle Compiler-Optimierungen abschalten.

Ich würde mal nachschauen welchen Compiler ich verwende.
Die "alten" WinAVR konnten das lange Adressieren nämlich
oft noch nicht.

Autor: c-hater (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Ole J. schrieb:

> Hat wirklich niemand eine Idee warum pgm_read_word_far() bei der ersten
> "page addr" immer 0xffff zu liefern scheint?!

Mein Gott. Schau dir an, was wirklich passiert, sprich: den vom 
C-Compiler erzeugten Asssembler-Code. Wenn der Fehler nicht in deiner 
Benutzung des C'ischen-Eyecandy liegt, dann liegt er in der Lib oder im 
Compiler. Beidem kann man nur beikommen, wenn man sich den 
Asssemblercode ansieht, der hinten rausfällt.

Das ist ein Grund, warum jeder wirklich gute C-Programmierer immer 
auch Assembler kann. Zumindest lesend...

Autor: Ole J. (ojepsen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe soeben das Problem gefunden!
Danke trotzdem für die Rückmeldungen.

Lösung:
Das hinzufügen von boot_rww_enable(), nach jedem wait hat das Problem 
gelöst!
...
boot_page_erase (page);
boot_spm_busy_wait ();      // Wait until the memory is erased.
boot_rww_enable ();
...

Gruß

Autor: Stefanus F. (Firma: Äppel) (stefanus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Das hinzufügen von boot_rww_enable(), nach jedem wait hat
> das Problem gelöst!

Hast du auch herausgefunden, warum das nötig war? Welcher Mechanismus 
steckt dahinter, das interessiert mich jetzt. In der Doku der Funktion 
habe ich dazu nicht wirklich was gefunden.

Autor: Ole J. (ojepsen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefanus F. schrieb:
> Hast du auch herausgefunden, warum das nötig war? Welcher Mechanismus
> steckt dahinter, das interessiert mich jetzt. In der Doku der Funktion
> habe ich dazu nicht wirklich was gefunden.

Nein ich habe einen ähnlichen Codeschnipsel gefunden und dies 
ausprobiert. Auffällig war, dass immer nur jedes erste WORD einer PAGE 
falsch ausgelesen wurde (0xFFFF).
Daraufhin habe ich beim zweiten Schleifendurchlauf einfach die erste 
Addr der PAGE nochmal gelesen, was auch klappte.
Somit war klar, dass nicht das lesen sondern der Zeitpunkt / Zugriff des 
lesens ein Problem war.
Das hinzufügen von boot_rww_enable() hat dieses Problem behoben.

Vermutlich wird durch boot_page_fill(...) der Zurgriff zum rww bereich 
enabled, aber dies findet erst nach dem ersten auslesen statt. Simit ist 
das vorherige "enablen" nötig. Ist aber nur meine vermutung :)

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.