AVR pgm_read_word_far(.) liefert quatsch

OP #5411118
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!
(Firma: Vescomp) #5455330
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.
Gast #5455498
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...
OP #5455823
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ß
Gast #5455837
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.
OP #5455844
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren