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


von Ole J. (ojepsen)


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:
1
//Ausruf:
2
_flashCopy(0x00000000, 0x0000F0000, 0x0000F0000);
3
4
bool _flashCopy(uint32_t srcAddr, uint32_t dstAddr, uint32_t byteCount)
5
{
6
  bool ret = true;
7
  uint8_t sreg;
8
  
9
  /* Disable interrupts */
10
  sreg = SREG;
11
  cli();
12
  uint32_t addr;
13
  uint32_t page = dstAddr;
14
  uint32_t count;
15
  uint16_t value16;
16
  for (addr = srcAddr, count = 0 ; addr < (srcAddr + byteCount) ;)
17
  { 
18
    if(count == 0)
19
    {
20
      eeprom_busy_wait ();
21
      boot_page_erase (page);
22
      boot_spm_busy_wait ();      /* Wait until the memory is erased. */
23
    }
24
    value16 = pgm_read_word_far(addr);
25
    
26
    boot_page_fill (page + count, value16);
27
    if(count >= SPM_PAGESIZE-2)
28
    {
29
      boot_page_write (page);
30
      boot_spm_busy_wait();
31
      count = 0;
32
      page+=SPM_PAGESIZE;
33
    }
34
    else
35
      count += 2;
36
      
37
    addr  += 2;
38
  }
39
  /* Re-enable interrupts (if they were ever enabled). */
40
  SREG = sreg;
41
  return ret;
42
}

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

Gruß und Danke im Voraus!

von Ole J. (ojepsen)


Lesenswert?

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

Gruß

von Stefan F. (Gast)


Lesenswert?

Nee, keine Idee.

von Marc V. (Firma: Vescomp) (logarithmus)


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:
1
 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.

von Harry L. (mysth)


Lesenswert?

Ich würde zum Testen mal alle Compiler-Optimierungen abschalten.

von Chaos Programmierer (Gast)


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.

von c-hater (Gast)


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...

von Ole J. (ojepsen)


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!
1
...
2
boot_page_erase (page);
3
boot_spm_busy_wait ();      // Wait until the memory is erased.
4
boot_rww_enable ();
5
...

Gruß

von Stefan F. (Gast)


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.

von Ole J. (ojepsen)


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 :)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.