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

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers eeprom.cpp Source File

eeprom.cpp

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