2016-03-22 10 views
-1

Ich arbeite mit einem Freescale-Mikrocontroller MCF51EM256 und ich habe einige Probleme, einige Daten im EEPROM zu speichern, um es persistent zu machen.Speichern von Daten im EEPROM, MICROCONTROLLER

Ich brauche diese Struktur im EEPROM zu speichern:

typedef struct { 
    ui64_s Ea_ps; 
    ui64_s Ea_ng; 
    ui64_s Er_q1; 
    ui64_s Er_q2; 
    ui64_s Er_q3; 
    ui64_s Er_q4; 
    uint16 F_ea; 
    uint16 F_er; 
}Ws_EnergyAcc64; 

Wo:

typedef union{  
    uint64 v; 
    uint32 p[2]; 
} ui64_s; 

und:

typedef unsigned long long int uint64; 
typedef unsigned long int uint32; 
typedef unsigned short int uint16; 

Um dies zu tun, habe ich diese Funktionen implementiert :

void Save_EEPROM_WsEnergyAcc(long addr, Ws_EnergyAcc64* Acc) { 

    // WsEnergyAcc struct needs 56 bytes in EEPROM 

    uint32 F_ea_32 = (uint32) Acc->F_ea; 
    uint32 F_er_32 = (uint32) Acc->F_er; 

    Flash_Burst(addr, 2, Acc->Ea_ps.p); 
    Flash_Burst(addr + 8, 2, Acc->Ea_ng.p); 
    Flash_Burst(addr + 16, 2, Acc->Er_q1.p); 
    Flash_Burst(addr + 24, 2, Acc->Er_q2.p); 
    Flash_Burst(addr + 32, 2, Acc->Er_q3.p); 
    Flash_Burst(addr + 40, 2, Acc->Er_q4.p); 

    Flash_Burst(addr + 48, 2, &F_ea_32); 
    Flash_Burst(addr + 52, 2, &F_er_32); 

} 

Wo "Flash_Burst":

#define Flash_Burst(Address, Size, DataPtr) \ 
     Flash_Cmd((UINT32)Address, (UINT16)Size, (UINT32*)DataPtr, FLASH_BURST_CMD) 

UINT8 /*far*/ 
Flash_Cmd(UINT32 FlashAddress, 
     UINT16 FlashDataCounter, 
     UINT32 *pFlashDataPtr, 
     UINT8 FlashCommand) 
{ 
    /* Check to see if FACCERR or PVIOL is set */ 
    if (FSTAT &0x30) 
    {   
     /* Clear Flags if set*/ 
     FSTAT = 0x30; 
    } 

    if (FlashDataCounter) 
    { 
    do 
    { 
     /* Wait for the Last Busrt Command to complete */ 
     while(!(FSTAT&FSTAT_FCBEF_MASK)){};/*wait until termination*/ 

     /* Write Data into Flash*/ 
     (*((volatile unsigned long *)(FlashAddress))) = *pFlashDataPtr; 
     FlashAddress += 4; 
     pFlashDataPtr++; 

     /* Write Command */ 
     FCMD = FlashCommand; 

     /* Put FCBEF at 1 */ 
     FSTAT = FSTAT_FCBEF_MASK; 

     asm (NOP); 
     asm (NOP); 
     asm (NOP); 

     /* Check if Flash Access Error or Protection Violation Error are Set */ 
     if (FSTAT&0x30) 
     {  
      /* If so, finish the function returning 1 to indicate error */ 
      return (1); 
     } 

    }while (--FlashDataCounter); 
    } 
    /* wait for the last command to complete */ 
    while ((FSTAT&FSTAT_FCCF_MASK)==0){};/*wait until termination*/ 

    /* Return zero to indicate that the function executed OK */ 
    return (0); 
} 

und:

void Init_EEPROM_WsEnergyAcc(long addr, Ws_EnergyAcc64* Acc) { 

    uint32 F_ea_32; 
    uint32 F_er_32; 

    Acc->Ea_ps.p[0] = *(uint32 *)addr; 
    addr = addr + 4; 
    Acc->Ea_ps.p[1] = *(uint32 *)addr; 
    Acc->Ea_ps.v = (uint64) Acc->Ea_ps.p[0] << 32 | Acc->Ea_ps.p[1]; 

    addr = addr + 4; 
    Acc->Ea_ng.p[0] = *(uint32 *)addr; 
    addr = addr + 4; 
    Acc->Ea_ng.p[1] = *(uint32 *)addr; 
    Acc->Ea_ng.v = (uint64) Acc->Ea_ng.p[0] << 32 | Acc->Ea_ng.p[1]; 

    addr = addr + 4; 
    Acc->Er_q1.p[0] = *(uint32*)addr; 
    addr = addr + 4; 
    Acc->Er_q1.p[1] = *(uint32*)addr; 
    Acc->Er_q1.v = (uint64) Acc->Er_q1.p[0] << 32 | Acc->Er_q1.p[1]; 

    addr = addr + 4; 
    Acc->Er_q2.p[0] = *(uint32*)addr; 
    addr = addr + 4; 
    Acc->Er_q2.p[1] = *(uint32*)addr; 
    Acc->Er_q2.v = (uint64) Acc->Er_q2.p[0] << 32 | Acc->Er_q2.p[1]; 

    addr = addr + 4; 
    Acc->Er_q3.p[0] = *(uint32*)addr; 
    addr = addr + 4; 
    Acc->Er_q3.p[1] = *(uint32*)addr; 
    Acc->Er_q3.v = (uint64) Acc->Er_q3.p[0] << 32 | Acc->Er_q3.p[1]; 

    addr = addr + 4; 
    Acc->Er_q4.p[0] = *(uint32*)addr; 
    addr = addr + 4; 
    Acc->Er_q4.p[1] = *(uint32*)addr; 
    Acc->Er_q4.v = (uint64) Acc->Er_q4.p[0] << 32 | Acc->Er_q4.p[1]; 

    addr = addr + 4; 
    F_ea_32 = *(uint32*) addr; 
    Acc->F_ea = (uint16) F_ea_32; 

    addr = addr + 4; 
    F_er_32 = *(uint32*) addr; 
    Acc->F_er = (uint16) F_er_32; 

}

Für meine Funktionen zu testen, habe ich ein wenig Testprogramm:

void testEEPROM(Ws_EnergyAcc64* Acc){ 

     Ws_EnergyAcc64 checkStruct; 

     Acc->Ea_ps.p[0] = 0x10000000; 
     Acc->Ea_ps.p[1] = 0x10000000; 
     Acc->Ea_ng.p[0] = 0x10000000; 
     Acc->Ea_ng.p[1] = 0x10000000; 
     Acc->Er_q1.p[0] = 0x10000000; 
     Acc->Er_q1.p[1] = 0x10000000; 
     Acc->Er_q2.p[0] = 0x10000000; 
     Acc->Er_q2.p[1] = 0x10000000; 
     Acc->Er_q3.p[0] = 0x10000000; 
     Acc->Er_q3.p[1] = 0x10000000; 
     Acc->Er_q4.p[0] = 0x10000000; 
     Acc->Er_q4.p[1] = 0x10000000; 
     Acc->F_ea = 0x0000; 
     Acc->F_er = 0x0000; 

    Save_EEPROM_WsEnergyAcc(PhR_ABS_Ws_addr, Acc); 

    Acc->Ea_ps.p[0] = 0x10011001; 
    Acc->Ea_ps.p[1] = 0x10011002; 
    Acc->Ea_ng.p[0] = 0x10011003; 
    Acc->Ea_ng.p[1] = 0x10011004; 
    Acc->Er_q1.p[0] = 0x10011005; 
    Acc->Er_q1.p[1] = 0x10011006; 
    Acc->Er_q2.p[0] = 0x10011007; 
    Acc->Er_q2.p[1] = 0x10011008; 
    Acc->Er_q3.p[0] = 0x10011009; 
    Acc->Er_q3.p[1] = 0x1001100A; 
    Acc->Er_q4.p[0] = 0x1001100B; 
    Acc->Er_q4.p[1] = 0x1001100C; 
    Acc->F_ea = 0x0000; 
    Acc->F_er = 0x0000; 

    Save_EEPROM_WsEnergyAcc(PhR_ABS_Ws_addr, Acc);  
    Init_EEPROM_WsEnergyAcc(PhR_ABS_Ws_addr, &checkStruct); 

    printf("%d\n", checkStruct.Ea_ps.p[0]); 
    printf("%d\n", checkStruct.Ea_ps.p[1]); 
    printf("%d\n", checkStruct.Ea_ng.p[0]); 
    printf("%d\n", checkStruct.Ea_ng.p[1]); 
    printf("%d\n", checkStruct.Er_q1.p[0]); 
    printf("%d\n", checkStruct.Er_q1.p[1]); 
    printf("%d\n", checkStruct.Er_q2.p[0]); 
    printf("%d\n", checkStruct.Er_q2.p[1]); 
    printf("%d\n", checkStruct.Er_q3.p[0]); 
    printf("%d\n", checkStruct.Er_q3.p[1]); 
    printf("%d\n", checkStruct.Er_q4.p[0]); 
    printf("%d\n", checkStruct.Er_q4.p[1]); 
} 

Wenn Ich schreibe nur einmal im EEPROM, es funktioniert, aber wenn ich das EEPROM öfter schreibe, wie das Beispiel, funktioniert es nicht, druckt immer 0x1000000.

Jemand kann mir helfen? Warum funktioniert das nicht? Wenn ich einmal schreiben kann, warum kann ich es nicht öfter machen?

Danke euch allen!

+0

Es scheint, dass Sie EEPROM und Flash verwirren. Sie schreiben EEPROM überall, aber es scheint, dass Sie tatsächlich Flash verwenden. – ElderBug

+0

@ElderBug Viele MCUs haben ein EEPROM-Emulationsmodul. Offensichtlich schreibt es auf Flash-Speicher. – LPs

+0

@LPs Ich habe keine gesehen, die EEPROM-on-Flash ankündigen. Alle MCUs, die ich gesehen habe, kündigen entweder EEPROM als EEPROM an (vielleicht emuliert, aber nicht explizit), oder einfach nicht, und bieten nur Flash an. Im letzteren Fall ist die MCU von OP; Es hat kein EEPROM. Es ist natürlich besser, die beiden nicht zu verwechseln, auch wenn sie Gemeinsamkeiten haben. – ElderBug

Antwort

1

Jedes Mal, wenn Sie eine EEPROM schreiben möchten, löschen Sie es. Zum ersten Mal funktioniert es, wahrscheinlich wegen JTAG führen Sie eine Massenlöschung durch.

Beachten Sie auch, dass das EEPROM in modernen MCUs emuliert wird und einen Teil des On-Chip-Flash-Speichers verwendet. Dies erklärt besser, warum Sie es löschen müssen, bevor Sie schreiben.

+0

Danke! Ich habe das Makro Flash_Erase, aber ich habe es nicht verwendet, weil es einen Kompilierungsfehler in meinem Projekt verursacht. Ich werde darüber in anderem Posten fragen. Vielen Dank! – Kroka