simple test EEPROM emulation for STM32F401 (STM algorithm described in the application notes: AN4061, AN3969, AN2594, AN3390, AN4056).

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers eeprom.cpp Source File

eeprom.cpp

00001 /**
00002   ******************************************************************************
00003   * @file    EEPROM/EEPROM_Emulation/src/eeprom.c 
00004   * @author  MCD Application Team
00005   * @version V1.0.1
00006   * @date    29-January-2016
00007   * @brief   This file provides all the EEPROM emulation firmware functions.
00008   ******************************************************************************
00009   * @attention
00010   *
00011   * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
00012   *
00013   * Redistribution and use in source and binary forms, with or without modification,
00014   * are permitted provided that the following conditions are met:
00015   *   1. Redistributions of source code must retain the above copyright notice,
00016   *      this list of conditions and the following disclaimer.
00017   *   2. Redistributions in binary form must reproduce the above copyright notice,
00018   *      this list of conditions and the following disclaimer in the documentation
00019   *      and/or other materials provided with the distribution.
00020   *   3. Neither the name of STMicroelectronics nor the names of its contributors
00021   *      may be used to endorse or promote products derived from this software
00022   *      without specific prior written permission.
00023   *
00024   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00025   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00026   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00027   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00028   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00029   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00030   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00032   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00033   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034   *
00035   ******************************************************************************
00036   */
00037 
00038 /** @addtogroup EEPROM_Emulation
00039   * @{
00040   */ 
00041 
00042 /* Includes ------------------------------------------------------------------*/
00043 #include "eeprom.h"
00044 
00045 /* Private typedef -----------------------------------------------------------*/
00046 /* Private define ------------------------------------------------------------*/
00047 /* Private macro -------------------------------------------------------------*/
00048 /* Private variables ---------------------------------------------------------*/
00049 
00050 /* Dummy variables to protect eeprom pages if code size is bigger than 32kb (F401) 
00051 needed in Mbed online compiler to avoid conflict with linker (N.S.) */
00052 const uint8_t Eeprom_area0[PAGE_SIZE] __attribute__((at(PAGE0_BASE_ADDRESS),used))={ [0 ... (PAGE_SIZE-1)] = 0xFF };
00053 const uint8_t Eeprom_area1[PAGE_SIZE] __attribute__((at(PAGE1_BASE_ADDRESS),used))={ [0 ... (PAGE_SIZE-1)] = 0xFF };
00054 
00055 
00056 /* Global variable used to store variable value in read sequence */
00057 uint16_t DataVar = 0;
00058 
00059 /* Virtual address defined by the user: 0xFFFF value is prohibited */
00060 extern uint16_t VirtAddVarTab[NB_OF_VAR];
00061 
00062 /* Private function prototypes -----------------------------------------------*/
00063 /* Private functions ---------------------------------------------------------*/
00064 static HAL_StatusTypeDef EE_Format(void);
00065 static uint16_t EE_FindValidPage(uint8_t Operation);
00066 static uint16_t EE_VerifyPageFullWriteVariable(uint16_t VirtAddress, uint16_t Data);
00067 static uint16_t EE_PageTransfer(uint16_t VirtAddress, uint16_t Data);
00068 static uint16_t EE_VerifyPageFullyErased(uint32_t Address);
00069 
00070 /**
00071   * @brief  Restore the pages to a known good state in case of page's status
00072   *   corruption after a power loss.
00073   * @param  None.
00074   * @retval - Flash error code: on write Flash error
00075   *         - FLASH_COMPLETE: on success
00076   */
00077 uint16_t EE_Init(void)
00078 {
00079   uint16_t PageStatus0 = 6, PageStatus1 = 6;
00080   uint16_t VarIdx = 0;
00081   uint16_t EepromStatus = 0, ReadStatus = 0;
00082   int16_t x = -1;
00083   HAL_StatusTypeDef  FlashStatus;
00084   uint32_t SectorError = 0;
00085   FLASH_EraseInitTypeDef pEraseInit;
00086 
00087 
00088   /* Get Page0 status */
00089   PageStatus0 = (*(__IO uint16_t*)PAGE0_BASE_ADDRESS);
00090   /* Get Page1 status */
00091   PageStatus1 = (*(__IO uint16_t*)PAGE1_BASE_ADDRESS);
00092 
00093   pEraseInit.TypeErase = TYPEERASE_SECTORS;
00094   pEraseInit.Sector = PAGE0_ID;
00095   pEraseInit.NbSectors = 1;
00096   pEraseInit.VoltageRange = VOLTAGE_RANGE;
00097   
00098   /* Check for invalid header states and repair if necessary */
00099   switch (PageStatus0)
00100   {
00101     case ERASED:
00102       if (PageStatus1 == VALID_PAGE) /* Page0 erased, Page1 valid */
00103       {
00104           /* Erase Page0 */
00105         if(!EE_VerifyPageFullyErased(PAGE0_BASE_ADDRESS))
00106         {
00107           FlashStatus = HAL_FLASHEx_Erase(&pEraseInit, &SectorError);
00108           /* If erase operation was failed, a Flash error code is returned */
00109           if (FlashStatus != HAL_OK)
00110           {
00111             return FlashStatus;
00112           }
00113         }
00114       }
00115       else if (PageStatus1 == RECEIVE_DATA) /* Page0 erased, Page1 receive */
00116       {
00117         /* Erase Page0 */
00118         if(!EE_VerifyPageFullyErased(PAGE0_BASE_ADDRESS))
00119         { 
00120           FlashStatus = HAL_FLASHEx_Erase(&pEraseInit, &SectorError);
00121           /* If erase operation was failed, a Flash error code is returned */
00122           if (FlashStatus != HAL_OK)
00123           {
00124             return FlashStatus;
00125           }
00126         }
00127         /* Mark Page1 as valid */
00128         FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, PAGE1_BASE_ADDRESS, VALID_PAGE);
00129         /* If program operation was failed, a Flash error code is returned */
00130         if (FlashStatus != HAL_OK)
00131         {
00132           return FlashStatus;
00133         }
00134       }
00135       else /* First EEPROM access (Page0&1 are erased) or invalid state -> format EEPROM */
00136       {
00137         /* Erase both Page0 and Page1 and set Page0 as valid page */
00138         FlashStatus = EE_Format();
00139         /* If erase/program operation was failed, a Flash error code is returned */
00140         if (FlashStatus != HAL_OK)
00141         {
00142           return FlashStatus;
00143         }
00144       }
00145       break;
00146 
00147     case RECEIVE_DATA:
00148       if (PageStatus1 == VALID_PAGE) /* Page0 receive, Page1 valid */
00149       {
00150         /* Transfer data from Page1 to Page0 */
00151         for (VarIdx = 0; VarIdx < NB_OF_VAR; VarIdx++)
00152         {
00153           if (( *(__IO uint16_t*)(PAGE0_BASE_ADDRESS + 6)) == VirtAddVarTab[VarIdx])
00154           {
00155             x = VarIdx;
00156           }
00157           if (VarIdx != x)
00158           {
00159             /* Read the last variables' updates */
00160             ReadStatus = EE_ReadVariable(VirtAddVarTab[VarIdx], &DataVar);
00161             /* In case variable corresponding to the virtual address was found */
00162             if (ReadStatus != 0x1)
00163             {
00164               /* Transfer the variable to the Page0 */
00165               EepromStatus = EE_VerifyPageFullWriteVariable(VirtAddVarTab[VarIdx], DataVar);
00166               /* If program operation was failed, a Flash error code is returned */
00167               if (EepromStatus != HAL_OK)
00168               {
00169                 return EepromStatus;
00170               }
00171             }
00172           }
00173         }
00174         /* Mark Page0 as valid */
00175         FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, PAGE0_BASE_ADDRESS, VALID_PAGE);
00176         /* If program operation was failed, a Flash error code is returned */
00177         if (FlashStatus != HAL_OK)
00178         {
00179           return FlashStatus;
00180         }
00181         pEraseInit.Sector = PAGE1_ID;
00182         pEraseInit.NbSectors = 1;
00183         pEraseInit.VoltageRange = VOLTAGE_RANGE;
00184         /* Erase Page1 */
00185         if(!EE_VerifyPageFullyErased(PAGE1_BASE_ADDRESS))
00186         { 
00187           FlashStatus = HAL_FLASHEx_Erase(&pEraseInit, &SectorError);
00188           /* If erase operation was failed, a Flash error code is returned */
00189           if (FlashStatus != HAL_OK)
00190           {
00191             return FlashStatus;
00192           }
00193         }
00194       }
00195       else if (PageStatus1 == ERASED) /* Page0 receive, Page1 erased */
00196       {
00197         pEraseInit.Sector = PAGE1_ID;
00198         pEraseInit.NbSectors = 1;
00199         pEraseInit.VoltageRange = VOLTAGE_RANGE;
00200         /* Erase Page1 */
00201         if(!EE_VerifyPageFullyErased(PAGE1_BASE_ADDRESS))
00202         { 
00203           FlashStatus = HAL_FLASHEx_Erase(&pEraseInit, &SectorError);
00204           /* If erase operation was failed, a Flash error code is returned */
00205           if (FlashStatus != HAL_OK)
00206           {
00207             return FlashStatus;
00208           }
00209         }
00210         /* Mark Page0 as valid */
00211         FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, PAGE0_BASE_ADDRESS, VALID_PAGE);
00212         /* If program operation was failed, a Flash error code is returned */
00213         if (FlashStatus != HAL_OK)
00214         {
00215           return FlashStatus;
00216         }
00217       }
00218       else /* Invalid state -> format eeprom */
00219       {
00220         /* Erase both Page0 and Page1 and set Page0 as valid page */
00221         FlashStatus = EE_Format();
00222         /* If erase/program operation was failed, a Flash error code is returned */
00223         if (FlashStatus != HAL_OK)
00224         {
00225           return FlashStatus;
00226         }
00227       }
00228       break;
00229 
00230     case VALID_PAGE:
00231       if (PageStatus1 == VALID_PAGE) /* Invalid state -> format eeprom */
00232       {
00233         /* Erase both Page0 and Page1 and set Page0 as valid page */
00234         FlashStatus = EE_Format();
00235         /* If erase/program operation was failed, a Flash error code is returned */
00236         if (FlashStatus != HAL_OK)
00237         {
00238           return FlashStatus;
00239         }
00240       }
00241       else if (PageStatus1 == ERASED) /* Page0 valid, Page1 erased */
00242       {
00243         pEraseInit.Sector = PAGE1_ID;
00244         pEraseInit.NbSectors = 1;
00245         pEraseInit.VoltageRange = VOLTAGE_RANGE;
00246         /* Erase Page1 */
00247         if(!EE_VerifyPageFullyErased(PAGE1_BASE_ADDRESS))
00248         { 
00249           FlashStatus = HAL_FLASHEx_Erase(&pEraseInit, &SectorError);
00250           /* If erase operation was failed, a Flash error code is returned */
00251           if (FlashStatus != HAL_OK)
00252           {
00253             return FlashStatus;
00254           }
00255         }
00256       }
00257       else /* Page0 valid, Page1 receive */
00258       {
00259         /* Transfer data from Page0 to Page1 */
00260         for (VarIdx = 0; VarIdx < NB_OF_VAR; VarIdx++)
00261         {
00262           if ((*(__IO uint16_t*)(PAGE1_BASE_ADDRESS + 6)) == VirtAddVarTab[VarIdx])
00263           {
00264             x = VarIdx;
00265           }
00266           if (VarIdx != x)
00267           {
00268             /* Read the last variables' updates */
00269             ReadStatus = EE_ReadVariable(VirtAddVarTab[VarIdx], &DataVar);
00270             /* In case variable corresponding to the virtual address was found */
00271             if (ReadStatus != 0x1)
00272             {
00273               /* Transfer the variable to the Page1 */
00274               EepromStatus = EE_VerifyPageFullWriteVariable(VirtAddVarTab[VarIdx], DataVar);
00275               /* If program operation was failed, a Flash error code is returned */
00276               if (EepromStatus != HAL_OK)
00277               {
00278                 return EepromStatus;
00279               }
00280             }
00281           }
00282         }
00283         /* Mark Page1 as valid */
00284         FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, PAGE1_BASE_ADDRESS, VALID_PAGE);        
00285         /* If program operation was failed, a Flash error code is returned */
00286         if (FlashStatus != HAL_OK)
00287         {
00288           return FlashStatus;
00289         }
00290         pEraseInit.Sector = PAGE0_ID;
00291         pEraseInit.NbSectors = 1;
00292         pEraseInit.VoltageRange = VOLTAGE_RANGE;
00293         /* Erase Page0 */
00294         if(!EE_VerifyPageFullyErased(PAGE0_BASE_ADDRESS))
00295         { 
00296           FlashStatus = HAL_FLASHEx_Erase(&pEraseInit, &SectorError);
00297           /* If erase operation was failed, a Flash error code is returned */
00298           if (FlashStatus != HAL_OK)
00299           {
00300             return FlashStatus;
00301           }
00302         }
00303       }
00304       break;
00305 
00306     default:  /* Any other state -> format eeprom */
00307       /* Erase both Page0 and Page1 and set Page0 as valid page */
00308       FlashStatus = EE_Format();
00309       /* If erase/program operation was failed, a Flash error code is returned */
00310       if (FlashStatus != HAL_OK)
00311       {
00312         return FlashStatus;
00313       }
00314       break;
00315   }
00316 
00317   return HAL_OK;
00318 }
00319 
00320 /**
00321   * @brief  Verify if specified page is fully erased.
00322   * @param  Address: page address
00323   *   This parameter can be one of the following values:
00324   *     @arg PAGE0_BASE_ADDRESS: Page0 base address
00325   *     @arg PAGE1_BASE_ADDRESS: Page1 base address
00326   * @retval page fully erased status:
00327   *           - 0: if Page not erased
00328   *           - 1: if Page erased
00329   */
00330 uint16_t EE_VerifyPageFullyErased(uint32_t Address)
00331 {
00332   uint32_t readstatus = 1;
00333   uint16_t addressvalue = 0x5555;
00334   uint32_t end_address;
00335   
00336   if (PAGE0_BASE_ADDRESS==Address)
00337   {
00338     end_address = PAGE0_END_ADDRESS;
00339   }
00340   else
00341   {
00342     end_address = PAGE1_END_ADDRESS;
00343   };
00344   
00345     
00346   /* Check each active page address starting from end */
00347   while (Address <= end_address)
00348   {
00349     /* Get the current location content to be compared with virtual address */
00350     addressvalue = (*(__IO uint16_t*)Address);
00351 
00352     /* Compare the read address with the virtual address */
00353     if (addressvalue != ERASED)
00354     {
00355       
00356       /* In case variable value is read, reset readstatus flag */
00357       readstatus = 0;
00358 
00359       break;
00360     }
00361     /* Next address location */
00362     Address = Address + 4;
00363   }
00364   
00365   /* Return readstatus value: (0: Page not erased, 1: Page erased) */
00366   return readstatus;
00367 }
00368 
00369 /**
00370   * @brief  Returns the last stored variable data, if found, which correspond to
00371   *   the passed virtual address
00372   * @param  VirtAddress: Variable virtual address
00373   * @param  Data: Global variable contains the read variable value
00374   * @retval Success or error status:
00375   *           - 0: if variable was found
00376   *           - 1: if the variable was not found
00377   *           - NO_VALID_PAGE: if no valid page was found.
00378   */
00379 uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data)
00380 {
00381   uint16_t ValidPage = PAGE0;
00382   uint16_t AddressValue = 0x5555, ReadStatus = 1;
00383   uint32_t Address = EEPROM_START_ADDRESS, PageStartAddress = EEPROM_START_ADDRESS;
00384 
00385   /* Get active Page for read operation */
00386   ValidPage = EE_FindValidPage(READ_FROM_VALID_PAGE);
00387 
00388   /* Check if there is no valid page */
00389   if (ValidPage == NO_VALID_PAGE)
00390   {
00391     return  NO_VALID_PAGE;
00392   }
00393 
00394   /* Get the valid Page start Address */
00395   PageStartAddress = (uint32_t)(EEPROM_START_ADDRESS + (uint32_t)(ValidPage * PAGE_SIZE));
00396 
00397   /* Get the valid Page end Address */
00398   Address = (uint32_t)((EEPROM_START_ADDRESS - 2) + (uint32_t)((1 + ValidPage) * PAGE_SIZE));
00399 
00400   /* Check each active page address starting from end */
00401   while (Address > (PageStartAddress + 2))
00402   {
00403     /* Get the current location content to be compared with virtual address */
00404     AddressValue = (*(__IO uint16_t*)Address);
00405 
00406     /* Compare the read address with the virtual address */
00407     if (AddressValue == VirtAddress)
00408     {
00409       /* Get content of Address-2 which is variable value */
00410       *Data = (*(__IO uint16_t*)(Address - 2));
00411 
00412       /* In case variable value is read, reset ReadStatus flag */
00413       ReadStatus = 0;
00414 
00415       break;
00416     }
00417     else
00418     {
00419       /* Next address location */
00420       Address = Address - 4;
00421     }
00422   }
00423 
00424   /* Return ReadStatus value: (0: variable exist, 1: variable doesn't exist) */
00425   return ReadStatus;
00426 }
00427 
00428 /**
00429   * @brief  Writes/upadtes variable data in EEPROM.
00430   * @param  VirtAddress: Variable virtual address
00431   * @param  Data: 16 bit data to be written
00432   * @retval Success or error status:
00433   *           - FLASH_COMPLETE: on success
00434   *           - PAGE_FULL: if valid page is full
00435   *           - NO_VALID_PAGE: if no valid page was found
00436   *           - Flash error code: on write Flash error
00437   */
00438 uint16_t EE_WriteVariable(uint16_t VirtAddress, uint16_t Data)
00439 {
00440   uint16_t Status = 0;
00441 
00442   /* Write the variable virtual address and value in the EEPROM */
00443   Status = EE_VerifyPageFullWriteVariable(VirtAddress, Data);
00444 
00445   /* In case the EEPROM active page is full */
00446   if (Status == PAGE_FULL)
00447   {
00448     /* Perform Page transfer */
00449     Status = EE_PageTransfer(VirtAddress, Data);
00450   }
00451 
00452   /* Return last operation status */
00453   return Status;
00454 }
00455 
00456 /**
00457   * @brief  Erases PAGE and PAGE1 and writes VALID_PAGE header to PAGE
00458   * @param  None
00459   * @retval Status of the last operation (Flash write or erase) done during
00460   *         EEPROM formating
00461   */
00462 static HAL_StatusTypeDef EE_Format(void)
00463 {
00464   HAL_StatusTypeDef FlashStatus = HAL_OK;
00465   uint32_t SectorError = 0;
00466   FLASH_EraseInitTypeDef pEraseInit;
00467 
00468   pEraseInit.TypeErase = FLASH_TYPEERASE_SECTORS;  
00469   pEraseInit.Sector = PAGE0_ID;
00470   pEraseInit.NbSectors = 1;
00471   pEraseInit.VoltageRange = VOLTAGE_RANGE;
00472   /* Erase Page0 */
00473   if(!EE_VerifyPageFullyErased(PAGE0_BASE_ADDRESS))
00474   {
00475     FlashStatus = HAL_FLASHEx_Erase(&pEraseInit, &SectorError); 
00476     /* If erase operation was failed, a Flash error code is returned */
00477     if (FlashStatus != HAL_OK)
00478     {
00479       return FlashStatus;
00480     }
00481   }
00482   /* Set Page0 as valid page: Write VALID_PAGE at Page0 base address */
00483   FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, PAGE0_BASE_ADDRESS, VALID_PAGE); 
00484   /* If program operation was failed, a Flash error code is returned */
00485   if (FlashStatus != HAL_OK)
00486   {
00487     return FlashStatus;
00488   }
00489 
00490   pEraseInit.Sector = PAGE1_ID;
00491   /* Erase Page1 */
00492   if(!EE_VerifyPageFullyErased(PAGE1_BASE_ADDRESS))
00493   {  
00494     FlashStatus = HAL_FLASHEx_Erase(&pEraseInit, &SectorError); 
00495     /* If erase operation was failed, a Flash error code is returned */
00496     if (FlashStatus != HAL_OK)
00497     {
00498       return FlashStatus;
00499     }
00500   }
00501   
00502   return HAL_OK;
00503 }
00504 
00505 /**
00506   * @brief  Find valid Page for write or read operation
00507   * @param  Operation: operation to achieve on the valid page.
00508   *   This parameter can be one of the following values:
00509   *     @arg READ_FROM_VALID_PAGE: read operation from valid page
00510   *     @arg WRITE_IN_VALID_PAGE: write operation from valid page
00511   * @retval Valid page number (PAGE or PAGE1) or NO_VALID_PAGE in case
00512   *   of no valid page was found
00513   */
00514 static uint16_t EE_FindValidPage(uint8_t Operation)
00515 {
00516   uint16_t PageStatus0 = 6, PageStatus1 = 6;
00517 
00518   /* Get Page0 actual status */
00519   PageStatus0 = (*(__IO uint16_t*)PAGE0_BASE_ADDRESS);
00520 
00521   /* Get Page1 actual status */
00522   PageStatus1 = (*(__IO uint16_t*)PAGE1_BASE_ADDRESS);
00523 
00524   /* Write or read operation */
00525   switch (Operation)
00526   {
00527     case WRITE_IN_VALID_PAGE:   /* ---- Write operation ---- */
00528       if (PageStatus1 == VALID_PAGE)
00529       {
00530         /* Page0 receiving data */
00531         if (PageStatus0 == RECEIVE_DATA)
00532         {
00533           return PAGE0;         /* Page0 valid */
00534         }
00535         else
00536         {
00537           return PAGE1;         /* Page1 valid */
00538         }
00539       }
00540       else if (PageStatus0 == VALID_PAGE)
00541       {
00542         /* Page1 receiving data */
00543         if (PageStatus1 == RECEIVE_DATA)
00544         {
00545           return PAGE1;         /* Page1 valid */
00546         }
00547         else
00548         {
00549           return PAGE0;         /* Page0 valid */
00550         }
00551       }
00552       else
00553       {
00554         return NO_VALID_PAGE;   /* No valid Page */
00555       }
00556 
00557     case READ_FROM_VALID_PAGE:  /* ---- Read operation ---- */
00558       if (PageStatus0 == VALID_PAGE)
00559       {
00560         return PAGE0;           /* Page0 valid */
00561       }
00562       else if (PageStatus1 == VALID_PAGE)
00563       {
00564         return PAGE1;           /* Page1 valid */
00565       }
00566       else
00567       {
00568         return NO_VALID_PAGE ;  /* No valid Page */
00569       }
00570 
00571     default:
00572       return PAGE0;             /* Page0 valid */
00573   }
00574 }
00575 
00576 /**
00577   * @brief  Verify if active page is full and Writes variable in EEPROM.
00578   * @param  VirtAddress: 16 bit virtual address of the variable
00579   * @param  Data: 16 bit data to be written as variable value
00580   * @retval Success or error status:
00581   *           - FLASH_COMPLETE: on success
00582   *           - PAGE_FULL: if valid page is full
00583   *           - NO_VALID_PAGE: if no valid page was found
00584   *           - Flash error code: on write Flash error
00585   */
00586 static uint16_t EE_VerifyPageFullWriteVariable(uint16_t VirtAddress, uint16_t Data)
00587 {
00588   HAL_StatusTypeDef FlashStatus = HAL_OK;
00589   uint16_t ValidPage = PAGE0;
00590   uint32_t Address = EEPROM_START_ADDRESS, PageEndAddress = EEPROM_START_ADDRESS+PAGE_SIZE;
00591 
00592   /* Get valid Page for write operation */
00593   ValidPage = EE_FindValidPage(WRITE_IN_VALID_PAGE);
00594   
00595   /* Check if there is no valid page */
00596   if (ValidPage == NO_VALID_PAGE)
00597   {
00598     return  NO_VALID_PAGE;
00599   }
00600 
00601   /* Get the valid Page start Address */
00602   Address = (uint32_t)(EEPROM_START_ADDRESS + (uint32_t)(ValidPage * PAGE_SIZE));
00603 
00604   /* Get the valid Page end Address */
00605   PageEndAddress = (uint32_t)((EEPROM_START_ADDRESS - 1) + (uint32_t)((ValidPage + 1) * PAGE_SIZE));
00606 
00607   /* Check each active page address starting from begining */
00608   while (Address < PageEndAddress)
00609   {
00610     /* Verify if Address and Address+2 contents are 0xFFFFFFFF */
00611     if ((*(__IO uint32_t*)Address) == 0xFFFFFFFF)
00612     {
00613       /* Set variable data */
00614       FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, Address, Data);       
00615       /* If program operation was failed, a Flash error code is returned */
00616       if (FlashStatus != HAL_OK)
00617       {
00618         return FlashStatus;
00619       }
00620       /* Set variable virtual address */
00621       FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, Address + 2, VirtAddress);       
00622       /* Return program operation status */
00623       return FlashStatus;
00624     }
00625     else
00626     {
00627       /* Next address location */
00628       Address = Address + 4;
00629     }
00630   }
00631 
00632   /* Return PAGE_FULL in case the valid page is full */
00633   return PAGE_FULL;
00634 }
00635 
00636 /**
00637   * @brief  Transfers last updated variables data from the full Page to
00638   *   an empty one.
00639   * @param  VirtAddress: 16 bit virtual address of the variable
00640   * @param  Data: 16 bit data to be written as variable value
00641   * @retval Success or error status:
00642   *           - FLASH_COMPLETE: on success
00643   *           - PAGE_FULL: if valid page is full
00644   *           - NO_VALID_PAGE: if no valid page was found
00645   *           - Flash error code: on write Flash error
00646   */
00647 static uint16_t EE_PageTransfer(uint16_t VirtAddress, uint16_t Data)
00648 {
00649   HAL_StatusTypeDef FlashStatus = HAL_OK;
00650   uint32_t NewPageAddress = EEPROM_START_ADDRESS;
00651   uint16_t OldPageId=0;
00652   uint16_t ValidPage = PAGE0, VarIdx = 0;
00653   uint16_t EepromStatus = 0, ReadStatus = 0;
00654   uint32_t SectorError = 0;
00655   FLASH_EraseInitTypeDef pEraseInit;
00656 
00657   /* Get active Page for read operation */
00658   ValidPage = EE_FindValidPage(READ_FROM_VALID_PAGE);
00659 
00660   if (ValidPage == PAGE1)       /* Page1 valid */
00661   {
00662     /* New page address where variable will be moved to */
00663     NewPageAddress = PAGE0_BASE_ADDRESS;
00664 
00665     /* Old page ID where variable will be taken from */
00666     OldPageId = PAGE1_ID;
00667   }
00668   else if (ValidPage == PAGE0)  /* Page0 valid */
00669   {
00670     /* New page address  where variable will be moved to */
00671     NewPageAddress = PAGE1_BASE_ADDRESS;
00672 
00673     /* Old page ID where variable will be taken from */
00674     OldPageId = PAGE0_ID;
00675   }
00676   else
00677   {
00678     return NO_VALID_PAGE;       /* No valid Page */
00679   }
00680 
00681   /* Set the new Page status to RECEIVE_DATA status */
00682   FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, NewPageAddress, RECEIVE_DATA);  
00683   /* If program operation was failed, a Flash error code is returned */
00684   if (FlashStatus != HAL_OK)
00685   {
00686     return FlashStatus;
00687   }
00688   
00689   /* Write the variable passed as parameter in the new active page */
00690   EepromStatus = EE_VerifyPageFullWriteVariable(VirtAddress, Data);
00691   /* If program operation was failed, a Flash error code is returned */
00692   if (EepromStatus != HAL_OK)
00693   {
00694     return EepromStatus;
00695   }
00696 
00697   /* Transfer process: transfer variables from old to the new active page */
00698   for (VarIdx = 0; VarIdx < NB_OF_VAR; VarIdx++)
00699   {
00700     if (VirtAddVarTab[VarIdx] != VirtAddress)  /* Check each variable except the one passed as parameter */
00701     {
00702       /* Read the other last variable updates */
00703       ReadStatus = EE_ReadVariable(VirtAddVarTab[VarIdx], &DataVar);
00704       /* In case variable corresponding to the virtual address was found */
00705       if (ReadStatus != 0x1)
00706       {
00707         /* Transfer the variable to the new active page */
00708         EepromStatus = EE_VerifyPageFullWriteVariable(VirtAddVarTab[VarIdx], DataVar);
00709         /* If program operation was failed, a Flash error code is returned */
00710         if (EepromStatus != HAL_OK)
00711         {
00712           return EepromStatus;
00713         }
00714       }
00715     }
00716   }
00717 
00718   pEraseInit.TypeErase = TYPEERASE_SECTORS;
00719   pEraseInit.Sector = OldPageId;
00720   pEraseInit.NbSectors = 1;
00721   pEraseInit.VoltageRange = VOLTAGE_RANGE;
00722   
00723   /* Erase the old Page: Set old Page status to ERASED status */
00724   FlashStatus = HAL_FLASHEx_Erase(&pEraseInit, &SectorError);  
00725   /* If erase operation was failed, a Flash error code is returned */
00726   if (FlashStatus != HAL_OK)
00727   {
00728     return FlashStatus;
00729   }
00730 
00731   /* Set new Page status to VALID_PAGE status */
00732   FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, NewPageAddress, VALID_PAGE);   
00733   /* If program operation was failed, a Flash error code is returned */
00734   if (FlashStatus != HAL_OK)
00735   {
00736     return FlashStatus;
00737   }
00738 
00739   /* Return last operation flash status */
00740   return FlashStatus;
00741 }
00742 
00743 /**
00744   * @}
00745   */ 
00746 
00747 /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/