simple test EEPROM emulation for STM32F401 (STM algorithm described in the application notes: AN4061, AN3969, AN2594, AN3390, AN4056).
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>© 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****/
Generated on Wed Jul 13 2022 11:37:02 by 1.7.2