Xmega, EEPROM geht nicht nach Bootloader

Gast #3404205
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
#3449873
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

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