0
\$\begingroup\$

I have some random issue with data saved in flash on PIC32MX470F512L.

Since there is no EEPROM, part of the flash storage is used to save configuration and some statistics (ie.: reboots reason, errors on serial communication, etc).

Over about 50+ units, randomly part of configuration change, the cause is not found but some hypothesis for the moment :

  • No capacitor on MCLR
  • Reading of the configuration in flash before VDD fully stabilized
  • Power off during flash write

I am sure there is not enought writes to go beyond limit, somewhere between 1 and 25 writes per day.

Yet I've not been able to reproduce the issue periodically.

Here are some relevant parts of the code...

Main

int main()
{
    /* Variables defines */

    //Configure l'horloge systeme
    SYSTEMConfig(GetSystemClock(),SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);


    //Active le watchdog (periode de timeout de 8sec)
    EnableWDT();

    //Initialisation de la configuration non volatile
    config_init();

    /* Other init stuff */

    //Gestion des statistiques de demarrage.
    if(mGetWDTOFlag())
    {      //Reset par watchdog
        mClearWDTOFlag();
        g_stConfiguration.stats[STAT_REBOOT_WATCHDOG]++;
        config_saveStats();
    }
    else if(mGetPORFlag())
    {  //Reset par switch
        mClearPORFlag();
        g_stConfiguration.stats[STAT_REBOOT_NO_POWER]++;
        config_saveStats();
    }
    else if(mGetBORFlag())
    {  //Reset par mauvaise alimentation
        mClearBORFlag();
        g_stConfiguration.stats[STAT_REBOOT_NO_POWER]++;
        config_saveStats();
    }
    else if(mGetMCLRFlag())
    { //Reset par mclr (bouton reset)
        mClearMCLRFlag();
        g_stConfiguration.stats[STAT_REBOOT_OTHER]++;
        config_saveStats();
    }
    else if(mGetSWRFlag())
    {  //Reset software (non implemente encore)
        mClearSWRFlag();
        g_stConfiguration.stats[STAT_REBOOT_OTHER]++;
        config_saveStats();
    }

    /* Going to main loop */
}

Flash utility functions

void config_init() {
    // Lecture de la configuration presente en memoire
    nvm_lireConfig(&g_stConfiguration,NVM_PAGE_CONFIG);

    /*
     * Si le numero d'ordinateur est zero c'est parce qu'il n'y a rien dans la
    * flash, on va charger les valeurs par defaut.
    */
    if(g_stConfiguration.numero_ordinateur == 0)
    {
        config_defaut(&g_stConfiguration);
        nvm_ecrireConfig(&g_stConfiguration,NVM_PAGE_CONFIG);
        nvm_ecrireConfig(&g_stConfiguration,NVM_PAGE_CFG_BKP);
    }
}

void config_saveStats()
{
    nvm_ecrireConfig(&g_stConfiguration,NVM_PAGE_CONFIG);
}

void nvm_lireConfig(void *dataAdr, int pageNumber) {
    memcpy(dataAdr,(void*)eedata_addr[pageNumber],sizeof(ComputerConfiguration));
}

int nvm_ecrireConfig(void * dataAdr, int pageNumber) {
    int pagebuff[1024]; //Buffer d'une page, necessaire pour la fonction NVProgram

    // On efface la page avant d'ecrire dedans
    if(nvm_effacer(pageNumber) == NVM_SUCCESS) {
        // Ecriture des donnees dans la NVM
        if(NVMProgram((void*)eedata_addr[pageNumber],dataAdr,sizeof(ComputerConfiguration),(void*)pagebuff) == 0) {
            // Verification des donnees ecrits
            if(nvm_verifier(dataAdr,pageNumber) == NVM_SUCCESS) {
                return NVM_SUCCESS;
            } else {
                return NVM_VERIFY_ERROR;
            }
        } else {
            return NVM_WRITE_ERROR;
        }
    } else {
        return NVM_ERASE_ERROR;
    }
}

int nvm_effacer(int pageNumber) {
    if(pageNumber < NVM_NUM_PAGES) {
        if(NVMErasePage((void*) eedata_addr[pageNumber]) == 0) {
            return NVM_SUCCESS;
        } else {
            return NVM_ERASE_ERROR;
        }
    } else {
        return NVM_PAGE_OUT_OF_RANGE;
    }
}
\$\endgroup\$
  • 2
    \$\begingroup\$ Have you checked the datasheet on this part? Some PIC32 are 1K, others 10k endurance. Anyway, 10K / 25 = 400 days. \$\endgroup\$ – Erik Friesen Nov 2 '18 at 21:15
  • \$\begingroup\$ NVMProgram() erases the page automatically. So what is the purpose of nvm_effacer() ? Can you show us the source code of it? \$\endgroup\$ – Bruce Abbott Nov 2 '18 at 23:19
  • \$\begingroup\$ @ErikFriesen problems are occuring in first days/weeks, yes I'm aware of the 10K endurance, not bothered with it for now since it doesn't look related (if problem was occuring on old units only, yes I would check more into that). \$\endgroup\$ – Alexandre Lavoie Nov 3 '18 at 3:42
  • \$\begingroup\$ @BruceAbbott Added the missing function, please note that I've not written this code, I only have to maintain it. \$\endgroup\$ – Alexandre Lavoie Nov 3 '18 at 3:47
  • \$\begingroup\$ There really isn’t enough info for an answer. In programming, if it can happen it will. You probably need two configs with crc so one is always valid. \$\endgroup\$ – Erik Friesen Nov 3 '18 at 22:41
2
\$\begingroup\$

After further investivation and tests, it looks like Erik Friesen was right, there was too much erase/write cycles into the flash memory.

The chip used (PIC32MX470) have a minimal cell endurance of 20000 E/W cycle (found in the datasheet page 292).

In the program I found multiple calls to the configuration write that could happen many dozens of times a day, also the erace was used twice, one manually and one into NVMProgram.

To confirm the issue, I've changed the pages used in the program and read / write were working perfectly (as those pages were not used before).

The final solution was :

  • Cleaning the code, removing all unnecessary configuration save
  • Removing the double erase
  • Integrate the Data EEPROM Emulation library from MicroChip to extend duration even more
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.