/** * @brief Transfers last updated variables data from the full Page to * an empty one. * @param VirtAddress: 16 bit virtual address of the variable * @param Data: 16 bit data to be written as variable value * @retval Success or error status: * - FLASH_COMPLETE: on success * - PAGE_FULL: if valid page is full * - NO_VALID_PAGE: if no valid page was found * - Flash error code: on write Flash error */ static uint16_t EE_PageTransfer(uint16_t VirtAddress, uint16_t Data) { HAL_StatusTypeDef FlashStatus = HAL_OK; uint32_t NewPageAddress = EEPROM_START_ADDRESS; uint16_t OldPageId=0; uint16_t ValidPage = PAGE0, VarIdx = 0; uint16_t EepromStatus = 0, ReadStatus = 0; /* Get active Page for read operation */ ValidPage = EE_FindValidPage(READ_FROM_VALID_PAGE); if (ValidPage == PAGE1) /* Page1 valid */ { /* New page address where variable will be moved to */ NewPageAddress = PAGE0_BASE_ADDRESS; /* Old page ID where variable will be taken from */ OldPageId = PAGE1_ID; } else if (ValidPage == PAGE0) /* Page0 valid */ { /* New page address where variable will be moved to */ NewPageAddress = PAGE1_BASE_ADDRESS; /* Old page ID where variable will be taken from */ OldPageId = PAGE0_ID; } else { return NO_VALID_PAGE; /* No valid Page */ } /* Set the new Page status to RECEIVE_DATA status */ FlashStatus = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, NewPageAddress, RECEIVE_DATA); /* If program operation was failed, a Flash error code is returned */ if (FlashStatus != HAL_OK) { return (uint16_t)FlashStatus; } /* Write the variable passed as parameter in the new active page */ EepromStatus = EE_VerifyPageFullWriteVariable(VirtAddress, Data); /* If program operation was failed, a Flash error code is returned */ if (EepromStatus != HAL_OK) { return EepromStatus; } /* Transfer process: transfer variables from old to the new active page */ for (VarIdx = 0; VarIdx < NB_OF_VAR; VarIdx++) { if (VirtAddVarTab[VarIdx] != VirtAddress) /* Check each variable except the one passed as parameter */ { /* Read the other last variable updates */ ReadStatus = EE_ReadVariable(VirtAddVarTab[VarIdx], &DataVar); /* In case variable corresponding to the virtual address was found */ if (ReadStatus != 0x1) { /* Transfer the variable to the new active page */ EepromStatus = EE_VerifyPageFullWriteVariable(VirtAddVarTab[VarIdx], DataVar); /* If program operation was failed, a Flash error code is returned */ if (EepromStatus != HAL_OK) { return EepromStatus; } } } } /* Erase the old Page: Set old Page status to ERASED status */ FLASH_Erase_Sector(OldPageId, VOLTAGE_RANGE); /* If erase operation was failed, a Flash error code is returned */ FlashStatus = FLASH_WaitForLastOperation(1000); if(FlashStatus != HAL_OK) { return FlashStatus; } /* Set new Page status to VALID_PAGE status */ FlashStatus = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, NewPageAddress, VALID_PAGE); /* If program operation was failed, a Flash error code is returned */ if (FlashStatus != HAL_OK) { return FlashStatus; } /* Return last operation flash status */ return FlashStatus; }
/** * @brief Program halfword, word or double word at a specified address * @note The function HAL_FLASH_Unlock() should be called before to unlock the FLASH interface * The function HAL_FLASH_Lock() should be called after to lock the FLASH interface * * @note If an erase and a program operations are requested simultaneously, * the erase operation is performed before the program one. * * @note FLASH should be previously erased before new programmation (only exception to this * is when 0x0000 is programmed) * * @param TypeProgram: Indicate the way to program at a specified address. * This parameter can be a value of @ref FLASH_Type_Program * @param Address: Specifies the address to be programmed. * @param Data: Specifies the data to be programmed * * @retval HAL_StatusTypeDef HAL Status */ HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data) { HAL_StatusTypeDef status = HAL_ERROR; uint8_t index = 0; uint8_t nbiterations = 0; /* Process Locked */ __HAL_LOCK(&pFlash); /* Check the parameters */ assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram)); assert_param(IS_FLASH_PROGRAM_ADDRESS(Address)); #if defined(FLASH_BANK2_END) if(Address <= FLASH_BANK1_END) { #endif /* FLASH_BANK2_END */ /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE); #if defined(FLASH_BANK2_END) } else { /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperationBank2(FLASH_TIMEOUT_VALUE); } #endif /* FLASH_BANK2_END */ if(status == HAL_OK) { if(TypeProgram == FLASH_TYPEPROGRAM_HALFWORD) { /* Program halfword (16-bit) at a specified address. */ nbiterations = 1U; } else if(TypeProgram == FLASH_TYPEPROGRAM_WORD) { /* Program word (32-bit = 2*16-bit) at a specified address. */ nbiterations = 2U; } else { /* Program double word (64-bit = 4*16-bit) at a specified address. */ nbiterations = 4U; } for (index = 0U; index < nbiterations; index++) { FLASH_Program_HalfWord((Address + (2U*index)), (uint16_t)(Data >> (16U*index))); #if defined(FLASH_BANK2_END) if(Address <= FLASH_BANK1_END) { #endif /* FLASH_BANK2_END */ /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE); /* If the program operation is completed, disable the PG Bit */ CLEAR_BIT(FLASH->CR, FLASH_CR_PG); #if defined(FLASH_BANK2_END) } else { /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperationBank2(FLASH_TIMEOUT_VALUE); /* If the program operation is completed, disable the PG Bit */ CLEAR_BIT(FLASH->CR2, FLASH_CR2_PG); } #endif /* FLASH_BANK2_END */ /* In case of error, stop programation procedure */ if (status != HAL_OK) { break; } } } /* Process Unlocked */ __HAL_UNLOCK(&pFlash); return status; }
/** * @brief Perform a mass erase or erase the specified FLASH memory sectors * @param[in] pEraseInit: pointer to an FLASH_EraseInitTypeDef structure that * contains the configuration information for the erasing. * * @param[out] SectorError: pointer to variable that * contains the configuration information on faulty sector in case of error * (0xFFFFFFFFU means that all the sectors have been correctly erased) * * @retval HAL Status */ HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *SectorError) { HAL_StatusTypeDef status = HAL_ERROR; uint32_t index = 0U; /* Process Locked */ __HAL_LOCK(&pFlash); /* Check the parameters */ assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase)); /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); if(status == HAL_OK) { /*Initialization of SectorError variable*/ *SectorError = 0xFFFFFFFFU; if(pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE) { /*Mass erase to be done*/ FLASH_MassErase((uint8_t) pEraseInit->VoltageRange, pEraseInit->Banks); /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); /* if the erase operation is completed, disable the MER Bit */ FLASH->CR &= (~FLASH_MER_BIT); } else { /* Check the parameters */ assert_param(IS_FLASH_NBSECTORS(pEraseInit->NbSectors + pEraseInit->Sector)); /* Erase by sector by sector to be done*/ for(index = pEraseInit->Sector; index < (pEraseInit->NbSectors + pEraseInit->Sector); index++) { FLASH_Erase_Sector(index, (uint8_t) pEraseInit->VoltageRange); /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); /* If the erase operation is completed, disable the SER and SNB Bits */ CLEAR_BIT(FLASH->CR, (FLASH_CR_SER | FLASH_CR_SNB)); if(status != HAL_OK) { /* In case of error, stop erase procedure and return the faulty sector*/ *SectorError = index; break; } } } /* Flush the caches to be sure of the data consistency */ FLASH_FlushCaches(); } /* Process Unlocked */ __HAL_UNLOCK(&pFlash); return status; }
/** * @brief Perform a mass erase or erase the specified FLASH memory pages * @note To correctly run this function, the @ref HAL_FLASH_Unlock() function * must be called before. * Call the @ref HAL_FLASH_Lock() to disable the flash memory access * (recommended to protect the FLASH memory against possible unwanted operation) * @param[in] pEraseInit pointer to an FLASH_EraseInitTypeDef structure that * contains the configuration information for the erasing. * * @param[out] PageError pointer to variable that * contains the configuration information on faulty page in case of error * (0xFFFFFFFF means that all the pages have been correctly erased) * * @retval HAL_StatusTypeDef HAL Status */ HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *PageError) { HAL_StatusTypeDef status = HAL_ERROR; uint32_t address = 0U; /* Process Locked */ __HAL_LOCK(&pFlash); /* Check the parameters */ assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase)); if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE) { #if defined(FLASH_BANK2_END) if (pEraseInit->Banks == FLASH_BANK_BOTH) { /* Mass Erase requested for Bank1 and Bank2 */ /* Wait for last operation to be completed */ if ((FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE) == HAL_OK) && \ (FLASH_WaitForLastOperationBank2((uint32_t)FLASH_TIMEOUT_VALUE) == HAL_OK)) { /*Mass erase to be done*/ FLASH_MassErase(FLASH_BANK_BOTH); /* Wait for last operation to be completed */ if ((FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE) == HAL_OK) && \ (FLASH_WaitForLastOperationBank2((uint32_t)FLASH_TIMEOUT_VALUE) == HAL_OK)) { status = HAL_OK; } /* If the erase operation is completed, disable the MER Bit */ CLEAR_BIT(FLASH->CR, FLASH_CR_MER); CLEAR_BIT(FLASH->CR2, FLASH_CR2_MER); } } else if (pEraseInit->Banks == FLASH_BANK_2) { /* Mass Erase requested for Bank2 */ /* Wait for last operation to be completed */ if (FLASH_WaitForLastOperationBank2((uint32_t)FLASH_TIMEOUT_VALUE) == HAL_OK) { /*Mass erase to be done*/ FLASH_MassErase(FLASH_BANK_2); /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperationBank2((uint32_t)FLASH_TIMEOUT_VALUE); /* If the erase operation is completed, disable the MER Bit */ CLEAR_BIT(FLASH->CR2, FLASH_CR2_MER); } } else #endif /* FLASH_BANK2_END */ { /* Mass Erase requested for Bank1 */ /* Wait for last operation to be completed */ if (FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE) == HAL_OK) { /*Mass erase to be done*/ FLASH_MassErase(FLASH_BANK_1); /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); /* If the erase operation is completed, disable the MER Bit */ CLEAR_BIT(FLASH->CR, FLASH_CR_MER); } } } else { /* Page Erase is requested */ /* Check the parameters */ assert_param(IS_FLASH_PROGRAM_ADDRESS(pEraseInit->PageAddress)); assert_param(IS_FLASH_NB_PAGES(pEraseInit->PageAddress, pEraseInit->NbPages)); #if defined(FLASH_BANK2_END) /* Page Erase requested on address located on bank2 */ if(pEraseInit->PageAddress > FLASH_BANK1_END) { /* Wait for last operation to be completed */ if (FLASH_WaitForLastOperationBank2((uint32_t)FLASH_TIMEOUT_VALUE) == HAL_OK) { /*Initialization of PageError variable*/ *PageError = 0xFFFFFFFFU; /* Erase by page by page to be done*/ for(address = pEraseInit->PageAddress; address < (pEraseInit->PageAddress + (pEraseInit->NbPages)*FLASH_PAGE_SIZE); address += FLASH_PAGE_SIZE) { FLASH_PageErase(address); /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperationBank2((uint32_t)FLASH_TIMEOUT_VALUE); /* If the erase operation is completed, disable the PER Bit */ CLEAR_BIT(FLASH->CR2, FLASH_CR2_PER); if (status != HAL_OK) { /* In case of error, stop erase procedure and return the faulty address */ *PageError = address; break; } } } } else #endif /* FLASH_BANK2_END */ { /* Page Erase requested on address located on bank1 */ /* Wait for last operation to be completed */ if (FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE) == HAL_OK) { /*Initialization of PageError variable*/ *PageError = 0xFFFFFFFFU; /* Erase page by page to be done*/ for(address = pEraseInit->PageAddress; address < ((pEraseInit->NbPages * FLASH_PAGE_SIZE) + pEraseInit->PageAddress); address += FLASH_PAGE_SIZE) { FLASH_PageErase(address); /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); /* If the erase operation is completed, disable the PER Bit */ CLEAR_BIT(FLASH->CR, FLASH_CR_PER); if (status != HAL_OK) { /* In case of error, stop erase procedure and return the faulty address */ *PageError = address; break; } } } } } /* Process Unlocked */ __HAL_UNLOCK(&pFlash); return status; }