cancel
Showing results for 
Search instead for 
Did you mean: 

EEPROM Emulation brings EE_ERROR_NOACTIVE_PAGE on STM32U599

mraehle
Visitor

Hi

Initial situation
MCU = STM32U599VJTxQ
STM32CubeIDE = v1.19.0
TouchGFX = v4.26.0
EEPROM Emulator = x-cube-eeprom-v8-0-0 (downloaded direct from STM website)

I use the eeprom emulator to save an array of 251 bytes permant on the flash. To save the data into the flash I use the EE_WriteVariable32bits function

This are my function to init the EEPROM emulator, write data to EEPROM and read data from EEPROM

void Datastore::EEPROM_Init()
{
    HAL_FLASH_Unlock();   // 1. Flash freigeben

    // 2. Sicherstellen, dass Flash idle ist
    uint32_t timeout = 1000000;
    while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY))
    {
        if(timeout-- == 0)
        {
            HAL_FLASH_Lock();
            this->m_errorHdl_p->Add(ERR_ID_EEPROM_INIT_FAILURE);
            return;
        }
    }

    // 3. Critical Section / Interrupts kurz maskieren
    __disable_irq();

    // 4. EEPROM Init mit Retry
    EE_Status status = EE_WRITE_ERROR;
    const uint8_t max_retries = 3;
    uint8_t attempt = 0;

    while(((status != EE_OK) && (status != EE_PAGE_FULL)) && (attempt < max_retries))
    {
        status = EE_Init(EE_FORCED_ERASE);
        attempt++;
    }

    // 5. Interrupts wieder freigeben
    __enable_irq();

    HAL_FLASH_Lock();     // 6. Flash wieder sperren

    // 6. Fehlerbehandlung
    if((status != EE_OK) && (status != EE_PAGE_FULL))
    {
        this->m_errorHdl_p->Add(ERR_ID_EEPROM_INIT_FAILURE);
    }
}


#define EEPROM_WRITE_MAX_RETRIES 5
#define EEPROM_TRANSFER_WAIT_US   10
void Datastore::EEPROM_WriteData()
{
    if (!this->m_isInitDone) return;

    HAL_GPIO_WritePin(RUNLED_GPIO_Port, RUNLED_Pin, GPIO_PIN_SET);
    HAL_FLASH_Unlock();

    // Sicherstellen, dass Flash idle ist
    uint32_t timeout = 1000000;
    while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY))
    {
        if(timeout-- == 0)
        {
            HAL_FLASH_Lock();
            this->m_errorHdl_p->Add(ERR_ID_EEPROM_WRITE_FAILURE);
            HAL_GPIO_WritePin(RUNLED_GPIO_Port, RUNLED_Pin, GPIO_PIN_RESET);
            return;
        }
    }

    __disable_irq();  // IRQs maskieren

    EE_Status status;
    const uint32_t numVars = NB_OF_VARIABLES;

    for (uint32_t varIndex = 0; varIndex < numVars; varIndex++)
    {
        uint8_t attempt = 0;

        do
        {
            status = EE_WriteVariable32bits(varIndex + 1, this->m_parameter.param32[varIndex]);
            attempt++;

            // Wenn Page-Transfer aktiv oder sporadischer Schreibfehler
            if(status == EE_ERROR_NOACTIVE_PAGE || status == EE_WRITE_ERROR)
            {
                // Kurzes Delay, damit Flash Page-Transfer abgeschlossen wird
                for(volatile uint32_t i = 0; i < 10000; i++);
            }

        } while((status == EE_ERROR_NOACTIVE_PAGE || status == EE_WRITE_ERROR) && (attempt < EEPROM_WRITE_MAX_RETRIES));

        if(status != EE_OK)
        {
            // Persistenter Fehler -> abbrechen
            this->m_errorHdl_p->Add(ERR_ID_EEPROM_WRITE_FAILURE);
            break;
        }
    }

    __enable_irq(); // IRQs wieder freigeben
    HAL_FLASH_Lock();
    HAL_GPIO_WritePin(RUNLED_GPIO_Port, RUNLED_Pin, GPIO_PIN_RESET);
}


void Datastore::EEPROM_ReadData()
{
    EE_Status status;

    for (uint32_t varIndex = 0; varIndex < NB_OF_VARIABLES; varIndex++)
    {
        status = EE_ReadVariable32bits(varIndex + 1, &this->m_parameter.param32[varIndex]);
        if (status != EE_OK)
        {
            if (status != EE_NO_DATA) {
                this->m_errorHdl_p->Add(ERR_ID_EEPROM_READ_FAILURE);
            }

            // Setze die Bytes auf Default 0xFF
            uint32_t bytesToClear = 4;
            if(varIndex == NB_OF_VARIABLES - 1)
            {
                // Letzter Block evtl. weniger als 4 Bytes gültig
                bytesToClear = PARAM_DATASTORE_SIZE - (NB_OF_VARIABLES - 1) * 4;
            }

            for(uint32_t i = 0; i < bytesToClear; i++)
            {
                this->m_parameter.param8[varIndex*4 + i] = 0xFF;
            }
        }
    }
}


Here you can see my eeprom_emul_conf.h 

#define PARAM_DATASTORE_SIZE 251

#define START_PAGE_ADDRESS      (FLASH_BASE + FLASH_SIZE - 0x20000) /*!< Start address of the 1st page in flash, for EEPROM emulation */
#define CYCLES_NUMBER           2U   /*!< Number of 10Kcycles requested, minimum 1 for 10Kcycles (default),
                                        for instance 10 to reach 100Kcycles. This factor will increase
                                        pages number */
#define GUARD_PAGES_NUMBER      2U   /*!< Number of guard pages avoiding frequent transfers (must be multiple of 2): 0,2,4.. */

/* Configuration of crc calculation for eeprom emulation in flash */
#define CRC_POLYNOMIAL_LENGTH   LL_CRC_POLYLENGTH_16B /* CRC polynomial lenght 16 bits */
#define CRC_POLYNOMIAL_VALUE    0x8005U /* Polynomial to use for CRC calculation */

#define NB_OF_VARIABLES         ((PARAM_DATASTORE_SIZE + 3) / 4U)  /*!< Number of variables to handle in eeprom */



MEMORY
{
  RAM (xrw)   : ORIGIN = 0x20000000, LENGTH = 2496K
  SRAM4 (xrw) : ORIGIN = 0x28000000, LENGTH = 16K
  FLASH (rx)  : ORIGIN = 0x08000000, LENGTH = 3968K  /* 4096K - 128K */
  EEPROM (rx) : ORIGIN = 0x083E0000, LENGTH = 128K
}


The Problem
After writting 10 times the complete array to the EEPROM, then the EEPROM_WriteData function brings an error: EE_ERROR_NOACTIVE_PAGE
It looks like that the page swap does not work as expected. 
Further the compiler brings a warning: 
Description Resource Path Location Type
suggest parentheses around '&&' within '||' [-Wparentheses] eeprom_emul.c /WarmingDrawer_UI/Middlewares/ST/EEPROM_Emul/Core line 1548 C/C++ Problem


Is there a problem with braces around this if statement, in the file "eeprom_emul.c" on line 1548? Is that the reason, why page swap does not work as expected? 

else if ((addressvalue != EE_PAGESTAT_ERASED) || (addressvalue2 != EE_PAGESTAT_ERASED)&&(addressvalue != 0x0000000000000000U)|| (addressvalue2 != 0x0000000000000000U))


Or what else might be wrong, that the page swap does not work?

Thanks a lot for your help
best regards
Markus

0 REPLIES 0