pgm_read_word im Bootloader: Falsches Ergebnis

OP Persönliche Seite #1405011
Lesenswert?

Hallo an alle,

Ich schreibe gerade einen Bootloader für einen Atmega1281. Das Schreiben 
des Flashs funktioniert bereits. Nach dem Flashalgorithmus prüfe ich im 
FLash die Adresse 0 (Resetvektor) und schaue ob sie ungleich 0xFFFF 
(unprogrammiert) ist.

Nun zum Problem: Das Auslesen des Flashs funktioniert jedoch beim ersten 
mal nicht. Obwohl im Flash 0x0C94 steht (geprüft mit avrdude) wird 
0xFFFF ausgelesen.

Erst nach einem Power-On Reset wird erkannt, dass 0x0C94 an Adresse 0 
steht und zur Applikation gesprungen.

Weiß jemand woran das liegen kann?

Ist das ein Fehler im Controller?

Danke im  Voraus
lg Robert
Gast #1409117
Lesenswert?

Die Frage ist "Was willst du lesen?"
Das hier ist ein typische "Glaskugel" Frage.
MAn weiss nichts genaueres aber der Kunde drängt auf Antwort ohne 
detailierte Hintergrundinformationen zu liefern.

Eine weitere mögliche Antwort eines Hellsehers ist:

RAMPZ häng natürlich von der Position der gesuchten Speicherstelle im 
Flash ab.

Üblicherweise würde ich sagen
1
 RAMPZ=1;

da sich (bei eine ATMegas1281) Bootloader ja jenseits der 64KB Grenze 
befindet.
Gast #1409194
Lesenswert?

Um die Adresse 0x0000 zu lesen braucht es kein pgm_read_word_far()!

Poste mal den Codeabschnitt, mal schauen wie Du die Adresse liesst und 
auswertest...

Bei mir funktionierts folgendermassen:
1
 unsigned int temp;
2
 temp=pgm_read_word(0x0000);
3
 if (temp!=0xFFFF)      
4
 {
5
   cli();
6
   asm("jmp 0x0000");
7
 }
OP Persönliche Seite #1411188
Lesenswert?

Hallo,

Ich prüfe nach dem programmieren im Bootloader die Adresse 0x0000 im 
Flash, und schaue ob die Applikation programmiert wurde.

Das programmieren funktioniert, nur das Auslesen liefert ein falsches 
Ergebnis (0xFFFF), obwohl der Flash programmiert ist.

Mach ich nun einen Reset, gelange ich wieder in den Bootloader und somit 
wieder in die Statemachine. Wenn ich die durchlaufe, komm ich wieder 
beim Auslesen der Adresse 0x0000 an. Nur wird diesmal der richtige Wert 
aus dem Flash ausgelesen.

So lese ich den Flash aus:
1
        uint16_t flash = pgm_read_word(0);
2
        
3
        if(flash == 0xFFFF)
4
        {
5
          j=0;
6
          PORTG ^= (1 << PG5);
7
          
8
        }
9
        else
10
        {
11
            // Statusbyte ist already set to 0, so we don't need to do this anymore
12
            // Now Reset AVR with Watchdog
13
            wdt_enable(WDTO_15MS);  // 15 ms Timeout  
14
  
15
            while(1);  // Wait until Reset is generated
16
        }

Irgendwo muss noch der Hund begraben sein.

lg Robert
OP Persönliche Seite #1411802
Lesenswert?

Jörg Wunsch schrieb:
> Und das passiert auch dann noch, wenn du pgm_read_word_far() benutzt?
>
> Kann ich nicht recht glauben.

Ja genau. Erzeuge ich einen Reset (es reicht ein normaler über den 
Reset-Pin), und laufe die Bootloader State-Machine einmal durch, 
funktioniert das auslesen.

Langsam bin ich echt ratlos.

Ich habe den Bootloader vom Mega128 auf den Mega1281 angepasst. Dort 
habe kann ich das Problem nicht reproduzieren.

Kann vielleicht jemand das Programm auf einen Mega1281 auspielen? Das 
Programmieren erfolgt über den UART.

lg Robert
OP Persönliche Seite #1417795
Lesenswert?

Hallo Peter,

das mache ich bereits. Ich lese die Speicherstelle 0 in einer Schleife 
aus
1
while(!newDataAvailable())
2
{
3
  if(j++>20000)
4
  {
5
     uint16_t flash = pgm_read_word(0);
6

7
     if(flash == 0xFFFF)
8
     {
9
       j=0;
10
       PORTG ^= (1 << PG5);
11
     }
12
     else
13
     {
14
       wdt_enable(WDTO_15MS);   
15
       while(1);
16
     }
17
   }
18
   
19
  for(uint8_t i=0;i<50;i++) asm volatile("nop");
20
}

Nachdem ich den Flash programmiert habe, blinkt nur die Led an PG5. 
Sprich das auslesen funktioniert nicht. Leider habe ich bis jetzt keinen 
Workaround gefunden. Auch das Errata Sheet des Mega1281 schweigt 
darüber.

Vielleciht kann mir jemand helfen.

Danke!
lg Robert
#1417892
Lesenswert?

Du kannst ja mal meinen Bootloader probieren.

Ich hatte ihn auf dem ATmega2561 getestet und da lief er.
D.h. da das Verify nach dem Programmieren geklappt hat, muß er ja von 
Adresse 0x00000 das richtige gelesen haben ohne ein Reset dazwischen.

Wenn er bei Dir funktioniert, mußt Du mal ein Minmalprogramm schreiben, 
welches die erste Page programmiert und zurückliest und dann davon das 
Assemblerlistung erzeugen. Dann kann man nachsehen, ob was falsch 
compiliert wurde.


Peter
OP Persönliche Seite #1419356
Lesenswert?

Hallo Peter,

Nach mehreren Tests bin ich drauf gekommen, dass das Programm mit der 
ausgeschalteter Optimierung und Optimierung -O1 funktioniert. Mit -O2 
und -Os habe ich obiges Verhalten.

Im Anhang habe ich den Source Code, sowie alle generierten Assembler 
Listings. Interessant ist, dass bei -Os und -O2 das Auslesen des Flashs 
(LPM Befehle) am Anfang, und nicht in der Endlosschleife sind.

Das blicke ich nun nicht mehr durch. Generiert der Optimizer einen 
falschen Code?

lg Robert
#1812772
Lesenswert?

Hallo Robert S.,

gibt es eigentlich eine Lösung für das beschriebene Problem? Ich habe 
ein vergleichbares Verhalten mit einem AT90CAN128 - der Schreibvorgang 
funktioniert (verifiziert durch Zurücklesen), der Lesevorgang klappt 
erst nach einem Reset. Den Optimizer kann ich aber leider nicht 
ausschalten, da ich CAN+UART+TWI im Bootloader benutze.

Gruß,
captorg

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