Forum: Mikrocontroller und Digitale Elektronik Xmega, EEPROM geht nicht nach Bootloader


von Martin (Gast)


Lesenswert?

Hallo zusammen,

ich habe hier ein Problem mit einem atxmega128A1 bzw. D3 (Fehler kommt 
bei beiden Projekten). Es ist eine Applikation, in welcher ich EEPROM 
nutze. Um zu prüfen, ob im EEPROM was sinnvolles drin ist, prüfe ich zu 
Beginn von main ein paar Variablen im EEPROM ab:
1
int main(void)
2
  {
3
    cli();
4
    if ( (EEPROM_read_byte(&myEE.mainversion) != pgm_read_byte(&myFLASH.mainversion))
5
       ||(EEPROM_read_byte(&myEE.version) != pgm_read_byte(&myFLASH.version)) )
6
      {
7
        // panic! EEPROM falsch
Das funktioniert bei normalen Reset.

Das EEPROM lese ich mit den Routinen von Alex Forencich (xboot):
1
void wait_for_nvm(void)
2
{
3
        while (NVM.STATUS & NVM_NVMBUSY_bm) { };
4
}
5
6
uint8_t EEPROM_read_byte(void *addr)
7
{
8
        wait_for_nvm();
9
        
10
        NVM.ADDR0 = (uint16_t)addr & 0xFF;
11
        NVM.ADDR1 = ((uint16_t)addr >> 8) & 0x1F;
12
        NVM.ADDR2 = 0;
13
        
14
        NVM.CMD = NVM_CMD_READ_EEPROM_gc;
15
        NVM_EXEC();
16
        
17
        return NVM.DATA0;
18
}

wobei NVM_EXEC() einfach ein inline ist:
1
// NVM call
2
static inline void NVM_EXEC(void)
3
{
4
        void *z = (void *)&NVM_CTRLA;
5
        
6
        __asm__ volatile("out %[ccp], %[ioreg]"  "\n\t"
7
        "st z, %[cmdex]"
8
        :
9
        : [ccp] "I" (_SFR_IO_ADDR(CCP)),
10
        [ioreg] "d" (CCP_IOREG_gc),
11
                     [cmdex] "r" (NVM_CMDEX_bm),
12
                     [z] "z" (z)
13
                     );
14
}

Problem:
Komme ich nicht aus Kaltstart, sondern vom Bootloader, dann liefert mir 
die Routine EEPROM_read_byte immer 0 als Ergebnis zurück. Also ist 
offenbar irgendwas durch den Bootloader 'verbogen', ich finde partout 
nicht raus, was es sein könnte. Habe hier und auf avrfreaks schon die 
Suche durchwühlt, nichts gefunden. Ich hoffe, dass einer der hier 
mitlesenden Spezialisten mit dem Finger schnippt und hast Du da schon 
... sagen kann. Vielen Dank!

Martin

von Wolfgang K. (opendcc)


Lesenswert?

Hallo,

ich habe vermutlich das gleiche Problem: Benutze auch einen atxmega128A1 
mit Bootloader. Mittels dieses Bootloaders wird im Feld ein FW-Update 
durchgeführt. Das spielt soweit alles sowohl mit Flash, als auch mit 
EEPROM. Springe ich aber aus den Bootloader zurück in die Applikation, 
geht ein Read aufs EEPROM schief - ich bekomme nur 0. Starte ich die 
Applikation direkt aus Kaltstart, funktioniert alles.

Ich verlasse den Bootloader mit:
1
void application_start(void)
2
  {
3
    uint8_t temp;
4
    void   (*start)( void ) = 0x0000;   // Funktionspointer auf 0x0000
5
    
6
    cli();
7
    close_all_interrupts();
8
    
9
    SP_WaitForSPM();
10
        temp = (PMIC.CTRL & ((uint8_t) ~PMIC_IVSEL_bm));  // Interrupt Vektoren wieder gerade biegen
11
        CCPWrite( &PMIC.CTRL, temp );
12
        RAMPZ = 0;
13
        EIND = 0x00;
14
      start();             // Reset
15
  }
Das sollte doch passen, oder? Verwendeter Compiler ist der aktuell auf 
der Atmelseite verfügbare gcc 4.7.2

Irgendwie scheint es da ein irgendein Register zu geben, welches der 
Compiler offenbar nicht zurückstellt. Nur ich habe noch nicht 
rausgefunden, was genau. Ich habe schon RAMPX, Y, Z kontrolliert, alle 
sind 0, wie es sein soll.

Servus Wolfgang

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Lese bitte mal die Errata für den A3/D3, das EEPROM Problem wird dort 
addressiert.
http://www.atmel.com/Images/doc8241.pdf

Kurzgefasst - anständiges Lesen vom EEPROM geht nur im 'Sleep' Mode.
Beim A1 sollte es eigentlich klappen...

von Wolfgang K. (opendcc)


Lesenswert?

Hallo,

das adressiert aber nur die Rev. B des A3/D3, gilt nicht für aktuelle 
Chips und auch nicht für den A1, den ich da verwende.

Servus Wolfgang

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Setze vor dem Sprung ins Hauptprogramm oder direkt nach dem Anlaufen des 
Hauptprogramms NVM_CTRLB auf Null. Es kann auch nicht schaden, NVM_CMD 
auf Null zu setzen.

von Wolfgang K. (opendcc)


Lesenswert?

Hallo,

NVM.CTRLB auf 0, das war's. Vielen Dank.

Servus Wolfgang

: Bearbeitet durch User
von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Bitte ;-)

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.