/** ****************************************************************************** * @file stm32h7rsxx_hal_flash_ex.c * @author MCD Application Team * @brief Extended FLASH HAL module driver. * This file provides firmware functions to manage the following * functionalities of the FLASH extended peripheral: * + Extended programming operations functions * @verbatim ============================================================================== ##### Flash Extended features ##### ============================================================================== [..] Comparing to other previous devices, the FLASH interface for STM32H7RSxx devices contains the following additional features (+) Non-volatile state, Root-Of-Trust and Epoch option bytes (+) Option byte keys associated with hide protection level (+) CRC hardware module to check integrity (+) OTP blocks lock mechanism ##### How to use this driver ##### ============================================================================== [..] This driver provides functions to configure and program the FLASH memory of all STM32H7RSxx devices. It includes: (#) Flash Memory Erase functions: (++) Lock and Unlock the FLASH interface using HAL_FLASH_Unlock() and HAL_FLASH_Lock() functions (++) Erase function: Sector Erase and Mass Erase (++) There are two modes of erase : (+++) Polling Mode using HAL_FLASHEx_Erase() (+++) Interrupt Mode using HAL_FLASHEx_Erase_IT() (#) Option Bytes Programming function: Use HAL_FLASHEx_OBProgram() to: (++) Configure the write protection for each sector (++) Program the user Option Bytes (++) Configure the hide protection area (++) Configure the non-volatile state (#) Get Option Bytes Configuration function: Use HAL_FLASHEx_OBGetConfig() to: (++) Get the value of the sectors write protection (++) Get the value of the user Option Bytes (++) Get the configuration of the hide protection area (++) Get the value of the non-volatile state (++) Get the value of the Root-Of-Trust configuration (++) Get the value of the Epoch (#) OTP lock configuration function: Use HAL_FLASHEx_OTPLockConfig() (++) Activate the lock of an OTP block (#) Get the OTP lock configuration function: Use HAL_FLASHEx_GetOTPLock() (++) Get the value of the OTP blocks lock configuration (#) Option Byte Keys configuration function: Use HAL_FLASHEx_KeyConfig() (++) Program an option key for a specified hide protection level (#) Get an option byte key value: Use HAL_FLASHEx_GetKey() (++) Get the value of an option byte key for a specified hide protection level (#) Perform a CRC computation function: Use HAL_FLASHEx_ComputeCRC() (++) Perform CRC computation on a area defined either by sectors or by start/end addresses and return computation result (#) ECC management functions: (++) Handle ECC Detection flash interrupt by calling HAL_FLASHEx_ECCD_IRQHandler() (++) Callback functions are called when the ECC detection or correction occurs : HAL_FLASHEx_EccDetectionCallback() for ECC detection, otherwise HAL_FLASHEx_EccCorrectionCallback() (++) Get information about ECC error by calling HAL_FLASHEx_GetEccInfo() (++) Enable/Disable the ECC correction and detection interrupts: (+++) HAL_FLASHEx_EnableEccCorrectionInterrupt() to enable ECC correction interrupt (+++) HAL_FLASHEx_DisableEccCorrectionInterrupt() to disable ECC correction interrupt (+++) HAL_FLASHEx_EnableEccDetectionInterrupt() to enable ECC detection interrupt (+++) HAL_FLASHEx_DisableEccDetectionInterrupt() to disable ECC detection interrupt @endverbatim ****************************************************************************** * @attention * * Copyright (c) 2022 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "stm32h7rsxx_hal.h" /** @addtogroup STM32H7RSxx_HAL_Driver * @{ */ /** @defgroup FLASHEx FLASHEx * @brief FLASH Extended HAL module driver * @{ */ #ifdef HAL_FLASH_MODULE_ENABLED /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ #define SYSTEM_FLASH_SIZE 0x00020000UL /*!< System Flash size : 128 KB */ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ /** @defgroup FLASHEx_Private_Functions FLASHEx Private Functions * @{ */ static void FLASH_MassErase(void); static void FLASH_OB_WRPConfig(uint32_t WRPState, uint32_t WRPSector); static void FLASH_OB_UserConfig(uint32_t UserType, uint32_t UserConfig1, uint32_t UserConfig2); static void FLASH_OB_HDPConfig(uint32_t HDPStartPage, uint32_t HDPEndPage); static void FLASH_OB_NVConfig(uint32_t NVState); static void FLASH_OB_GetWRP(uint32_t *WRPState, uint32_t *WRPSector); static void FLASH_OB_GetUser(uint32_t *UserConfig1, uint32_t *UserConfig2); static void FLASH_OB_GetHDP(uint32_t *HDPStartPage, uint32_t *HDPEndPage); static uint32_t FLASH_OB_GetNV(void); static uint32_t FLASH_OB_GetRoT(void); static uint32_t FLASH_OB_GetEpoch(void); static void FLASH_CRC_AddSector(uint32_t Sector); static void FLASH_CRC_SelectAddress(uint32_t CRCStartAddr, uint32_t CRCEndAddr); static HAL_StatusTypeDef FLASH_CRC_WaitForLastOperation(uint32_t Timeout); /** * @} */ /* Exported functions -------------------------------------------------------*/ /** @defgroup FLASHEx_Exported_Functions FLASH Extended Exported Functions * @{ */ /** @defgroup FLASHEx_Exported_Functions_Group1 Extended IO operation functions * @brief Extended IO operation functions * @verbatim =============================================================================== ##### Extended programming operation functions ##### =============================================================================== [..] This subsection provides a set of functions allowing to manage the Extended FLASH programming operations Operations. @endverbatim * @{ */ /** * @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 (0xFFFFFFFF means that all * the sectors have been correctly erased). * * @retval HAL Status */ HAL_StatusTypeDef HAL_FLASHEx_Erase(const FLASH_EraseInitTypeDef *pEraseInit, uint32_t *SectorError) { HAL_StatusTypeDef status; uint32_t sector_index; /* Check the parameters */ assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase)); /* Process Locked */ __HAL_LOCK(&pFlash); /* Reset error code */ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE; /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE); if (status == HAL_OK) { if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE) { /* Mass erase to be done */ FLASH_MassErase(); /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE); } else { /*Initialization of SectorError variable*/ *SectorError = 0xFFFFFFFFU; for (sector_index = pEraseInit->Sector; sector_index < (pEraseInit->Sector + pEraseInit->NbSectors); sector_index++) { FLASH_SectorErase(sector_index); /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE); if (status != HAL_OK) { /* In case of error, stop erase procedure and return the faulty sector */ *SectorError = sector_index; break; } } } /* If the erase operation is completed, disable the associated bits */ CLEAR_BIT(FLASH->CR, (pEraseInit->TypeErase | FLASH_CR_SSN)); } /* Process Unlocked */ __HAL_UNLOCK(&pFlash); return status; } /** * @brief Perform a mass erase or erase the specified FLASH memory sectors with interrupt enabled. * @param pEraseInit pointer to an FLASH_EraseInitTypeDef structure that * contains the configuration information for the erasing. * * @retval HAL Status */ HAL_StatusTypeDef HAL_FLASHEx_Erase_IT(const FLASH_EraseInitTypeDef *pEraseInit) { HAL_StatusTypeDef status; /* Check the parameters */ assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase)); /* Process Locked */ __HAL_LOCK(&pFlash); /* Reset error code */ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE; /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE); if (status != HAL_OK) { /* Process Unlocked */ __HAL_UNLOCK(&pFlash); } else { /* Set internal variables used by the IRQ handler */ pFlash.ProcedureOnGoing = pEraseInit->TypeErase; /* Enable End of Operation and Error interrupts */ SET_BIT(FLASH->IER, (FLASH_IT_EOP | FLASH_IT_WRPERR | FLASH_IT_PGSERR | FLASH_IT_STRBERR | FLASH_IT_INCERR)); if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE) { /* Mass erase to be done */ FLASH_MassErase(); } else { /* Erase by sector to be done */ pFlash.NbSectorsToErase = pEraseInit->NbSectors; pFlash.Sector = pEraseInit->Sector; /* Erase first sector and wait for IT */ FLASH_SectorErase(pEraseInit->Sector); } } return status; } /** * @brief Program Option bytes. * @param pOBInit pointer to an FLASH_OBInitStruct structure that * contains the configuration information for the programming. * * @note To configure any option bytes, the option lock bit OPTLOCK must be * cleared with the call of HAL_FLASH_OB_Unlock() function. * @note New option bytes configuration will be taken into account in two cases: * - after an option bytes launch through the call of HAL_FLASH_OB_Launch() * - after a power reset (BOR reset or exit from Standby/Shutdown modes) * * @retval HAL Status */ HAL_StatusTypeDef HAL_FLASHEx_OBProgram(const FLASH_OBProgramInitTypeDef *pOBInit) { HAL_StatusTypeDef status; /* Check the parameters */ assert_param(IS_OPTIONBYTE(pOBInit->OptionType)); /* Process Locked */ __HAL_LOCK(&pFlash); /* Reset error code */ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE; /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE); if ((status == HAL_OK) && (pOBInit->OptionType != 0U)) { /* Set PG_OPT Bit */ SET_BIT(FLASH->OPTCR, FLASH_OPTCR_PG_OPT); /* Write protection configuration */ if ((pOBInit->OptionType & OPTIONBYTE_WRP) != 0U) { /* Configure of Write protection on the selected area */ FLASH_OB_WRPConfig(pOBInit->WRPState, pOBInit->WRPSector); } /* User Configuration */ if ((pOBInit->OptionType & OPTIONBYTE_USER) != 0U) { /* Configure the user option bytes */ FLASH_OB_UserConfig(pOBInit->USERType, pOBInit->USERConfig1, pOBInit->USERConfig2); } /* HDP configuration */ if ((pOBInit->OptionType & OPTIONBYTE_HDP) != 0U) { /* Configure the HDP Protection */ FLASH_OB_HDPConfig(pOBInit->HDPStartPage, pOBInit->HDPEndPage); } /* Non-volatile state configuration */ if ((pOBInit->OptionType & OPTIONBYTE_NV) != 0U) { /* Configure the non-volatile state */ FLASH_OB_NVConfig(pOBInit->NVState); } /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE); /* Clear PG_OPT Bit */ CLEAR_BIT(FLASH->OPTCR, FLASH_OPTCR_PG_OPT); } /* Process Unlocked */ __HAL_UNLOCK(&pFlash); return status; } /** * @brief Get the Option bytes configuration. * @param pOBInit pointer to an FLASH_OBInitStruct structure that contains the * configuration information. * @note The fields pOBInit->WRPArea, pOBInit->WMSecConfig and pOBInit->BootAddrConfig * should indicate which area/address is requested for the WRP, WM Security or * Boot Address, else no information will be returned * * @retval None */ void HAL_FLASHEx_OBGetConfig(FLASH_OBProgramInitTypeDef *pOBInit) { /* Get write protection on the selected area */ FLASH_OB_GetWRP(&(pOBInit->WRPState), &(pOBInit->WRPSector)); /* Get the user option bytes */ FLASH_OB_GetUser(&(pOBInit->USERConfig1), &(pOBInit->USERConfig2)); /* Get the HDP Protection */ FLASH_OB_GetHDP(&(pOBInit->HDPStartPage), &(pOBInit->HDPEndPage)); /* Get the non-volatile state */ pOBInit->NVState = FLASH_OB_GetNV(); /* Get the Root-Of-Trust configuration */ pOBInit->ROTConfig = FLASH_OB_GetRoT(); /* Get the epoch */ pOBInit->EPOCH = FLASH_OB_GetEpoch(); } /** * @} */ /** @defgroup FLASHEx_Exported_Functions_Group2 Extended protection operation functions * @brief Extended protection operation functions * @verbatim =============================================================================== ##### Extended protection operation functions ##### =============================================================================== [..] This subsection provides a set of functions allowing to manage the Extended FLASH CRC operations, OTP lock mechanism and option byte keys management. @endverbatim * @{ */ /** * @brief Configure the OTP Lock. * * @note To configure the OTP Lock options, the option lock bit OPTLOCK must be * cleared with the call of the HAL_FLASH_OB_Unlock() function. * * @param OTPLBlock Specifies the block(s) to be OTP locked (used for OPTIONBYTE_OTPL). * The value of this parameter depend on device used within the same series * * @retval HAL Status */ HAL_StatusTypeDef HAL_FLASHEx_OTPLockConfig(uint32_t OTPLBlock) { HAL_StatusTypeDef status; /* Check the parameters */ assert_param(IS_OB_OTP_BLOCK(OTPLBlock)); /* Process Locked */ __HAL_LOCK(&pFlash); /* Reset error code */ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE; /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE); if (status == HAL_OK) { /* Set the bit for the OTP programmation */ SET_BIT(FLASH->CR, FLASH_CR_PG_OTP); /* Set PG_OPT Bit */ SET_BIT(FLASH->OPTCR, FLASH_OPTCR_PG_OPT); /* Configure the write protected area */ MODIFY_REG(FLASH->OTPLSRP, FLASH_OTPLSRP_OTPL, (OTPLBlock & FLASH_OTPLSRP_OTPL)); /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE); /* Clear PG_OPT Bit */ CLEAR_BIT(FLASH->OPTCR, FLASH_OPTCR_PG_OPT); /* Clear the bit for the OTP programmation */ CLEAR_BIT(FLASH->CR, FLASH_CR_PG_OTP); } /* Process Unlocked */ __HAL_UNLOCK(&pFlash); return status; } /** * @brief Return the FLASH OTP Lock Option Bytes value. * * @retval Status of the OTP Lock */ uint32_t HAL_FLASHEx_GetOTPLock(void) { return (FLASH->OTPLSR & FLASH_OTPLSR_OTPL); } /** * @brief Configure the Keys. * * @note To configure the Keys options, the option lock bit OPTLOCK must be * cleared with the call of the HAL_FLASH_OB_Unlock() function. * * @param pKeyConfig Key(s) to be configured. * * @param pKey Address of the key * * @retval HAL Status */ HAL_StatusTypeDef HAL_FLASHEx_KeyConfig(const FLASH_KeyConfigTypeDef *pKeyConfig, const uint32_t *pKey) { uint32_t index; uint32_t index_max; const uint32_t *pdata; HAL_StatusTypeDef status; /* Check the parameters */ assert_param(IS_KEY_INDEX(pKeyConfig->Index)); assert_param(IS_KEY_SIZE(pKeyConfig->Size)); assert_param(IS_KEY_HDPL_LEVEL(pKeyConfig->HDPLLevel)); /* Process Locked */ __HAL_LOCK(&pFlash); /* Reset error code */ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE; /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE); if (status == HAL_OK) { /* Set PG_OPT Bit */ SET_BIT(FLASH->OPTCR, FLASH_OPTCR_PG_OPT); switch (pKeyConfig->Size) { case FLASH_KEY_32_BITS : index_max = 1U; break; case FLASH_KEY_64_BITS : index_max = 2U; break; case FLASH_KEY_128_BITS : index_max = 4U; break; case FLASH_KEY_256_BITS : index_max = 8U; break; default: /* This case should not occur */ index_max = 0U; break; } pdata = pKey; for (index = 0U; index < index_max; index++) { FLASH->OBKDR[index] = pdata[index]; } MODIFY_REG(FLASH->OBKCR, (FLASH_OBKCR_OBKINDEX | FLASH_OBKCR_NEXTKL | FLASH_OBKCR_OBKSIZE), (pKeyConfig->Index | pKeyConfig->HDPLLevel | pKeyConfig->Size)); SET_BIT(FLASH->OBKCR, (FLASH_OBKCR_KEYSTART | FLASH_OBKCR_KEYPROG)); /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE); CLEAR_BIT(FLASH->OBKCR, FLASH_OBKCR_KEYPROG); /* Clear PG_OPT Bit */ CLEAR_BIT(FLASH->OPTCR, FLASH_OPTCR_PG_OPT); } /* Process Unlocked */ __HAL_UNLOCK(&pFlash); return status; } /** * @brief Load and optionally return the FLASH Option Bytes Key value. * * @param pKeyConfig Configuration of the key to be loaded and optionally returned * * @param pKey Address to return the FLASH Option Bytes Key value if not NULL. * * @retval HAL Status */ HAL_StatusTypeDef HAL_FLASHEx_GetKey(const FLASH_KeyConfigTypeDef *pKeyConfig, uint32_t *pKey) { uint32_t index; uint32_t index_max; uint32_t *pdata; HAL_StatusTypeDef status; /* Check the parameters */ assert_param(IS_KEY_INDEX(pKeyConfig->Index)); assert_param(IS_KEY_SIZE(pKeyConfig->Size)); assert_param(IS_KEY_HDPL_LEVEL(pKeyConfig->HDPLLevel)); /* Process Locked */ __HAL_LOCK(&pFlash); /* Reset error code */ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE; /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE); if (status == HAL_OK) { /* Set PG_OPT Bit */ SET_BIT(FLASH->OPTCR, FLASH_OPTCR_PG_OPT); /* Configure index and HDPL level */ MODIFY_REG(FLASH->OBKCR, (FLASH_OBKCR_OBKINDEX | FLASH_OBKCR_NEXTKL | FLASH_OBKCR_OBKSIZE | FLASH_OBKCR_KEYPROG), (pKeyConfig->Index | pKeyConfig->HDPLLevel | pKeyConfig->Size)); /* Set the start bit to get the key value */ SET_BIT(FLASH->OBKCR, FLASH_OBKCR_KEYSTART); /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE); if ((status == HAL_OK) && (pKey != NULL)) { switch (pKeyConfig->Size) { case FLASH_KEY_32_BITS : index_max = 1U; break; case FLASH_KEY_64_BITS : index_max = 2U; break; case FLASH_KEY_128_BITS : index_max = 4U; break; case FLASH_KEY_256_BITS : index_max = 8U; break; default: /* This case should not occur */ index_max = 0U; break; } pdata = pKey; for (index = 0U; index < index_max; index++) { *pdata = FLASH->OBKDR[index]; pdata++; } } /* Clear PG_OPT Bit */ CLEAR_BIT(FLASH->OPTCR, FLASH_OPTCR_PG_OPT); } /* Process Unlocked */ __HAL_UNLOCK(&pFlash); return status; } /** * @brief Perform a CRC computation on the specified FLASH memory area * @param pCRCInit pointer to an FLASH_CRCInitTypeDef structure that * contains the configuration information for the CRC computation. * @param CRC_Result pointer to CRC result * @note CRC computation uses CRC-32 (Ethernet) polynomial 0x4C11DB7 * @retval HAL Status */ HAL_StatusTypeDef HAL_FLASHEx_ComputeCRC(const FLASH_CRCInitTypeDef *pCRCInit, uint32_t *CRC_Result) { HAL_StatusTypeDef status; uint32_t sector_index; /* Check the parameters */ assert_param(IS_FLASH_TYPE_CRC(pCRCInit->TypeCRC)); assert_param(IS_FLASH_BURST_SIZE_CRC(pCRCInit->BurstSize)); /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE); if (status == HAL_OK) { /* Process Locked */ __HAL_LOCK(&pFlash); /* Reset error code */ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE; /* Enable CRC feature */ SET_BIT(FLASH->CR, FLASH_CR_CRC_EN); /* Clear CRC flags in Status Register: CRC end of calculation and CRC read error */ FLASH->ICR = (FLASH_ICR_CRCRDERRF | FLASH_ICR_CRCENDF); /* Clear current CRC result and program burst size */ MODIFY_REG(FLASH->CRCCR, (FLASH_CRCCR_CLEAN_CRC | FLASH_CRCCR_CRC_BURST), (FLASH_CRCCR_CLEAN_CRC | pCRCInit->BurstSize)); if (pCRCInit->TypeCRC == FLASH_CRC_SECTORS) { /* Select CRC by sector and clear sectors list */ SET_BIT(FLASH->CRCCR, (FLASH_CRCCR_CRC_BY_SECT | FLASH_CRCCR_CLEAN_SECT)); /* Select CRC sectors */ for (sector_index = pCRCInit->Sector; sector_index < (pCRCInit->NbSectors + pCRCInit->Sector); sector_index++) { FLASH_CRC_AddSector(sector_index); } } else if (pCRCInit->TypeCRC == FLASH_CRC_BANK) { /* Select CRC by sector and all sectors */ SET_BIT(FLASH->CRCCR, (FLASH_CRCCR_CRC_BY_SECT | FLASH_CRCCR_ALL_SECT)); } else { /* Select CRC by address */ CLEAR_BIT(FLASH->CRCCR, FLASH_CRCCR_CRC_BY_SECT); /* Select CRC start and end addresses */ FLASH_CRC_SelectAddress(pCRCInit->CRCStartAddr, pCRCInit->CRCEndAddr); } /* Start the CRC calculation */ SET_BIT(FLASH->CRCCR, FLASH_CRCCR_START_CRC); /* Wait on CRC busy flag */ status = FLASH_CRC_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); /* Return CRC result */ (*CRC_Result) = FLASH->CRCDATAR; /* Disable CRC feature */ CLEAR_BIT(FLASH->CR, FLASH_CR_CRC_EN); /* Clear CRC flags */ FLASH->ICR = (FLASH_ICR_CRCRDERRF | FLASH_ICR_CRCENDF); /* Process Unlocked */ __HAL_UNLOCK(&pFlash); } return status; } /** * @} */ /** @defgroup FLASHEx_Exported_Functions_Group3 Extended ECC operation functions * @brief Extended ECC operation functions * @verbatim =============================================================================== ##### Extended ECC operation functions ##### =============================================================================== [..] This subsection provides a set of functions allowing to manage the Extended FLASH ECC Operations. @endverbatim * @{ */ /** * @brief Enable ECC correction interrupt * @retval None */ void HAL_FLASHEx_EnableEccCorrectionInterrupt(void) { __HAL_FLASH_ENABLE_IT(FLASH_IT_SNECCERR); } /** * @brief Disable ECC correction interrupt * @retval None */ void HAL_FLASHEx_DisableEccCorrectionInterrupt(void) { __HAL_FLASH_DISABLE_IT(FLASH_IT_SNECCERR); } /** * @brief Enable ECC detection interrupt * @retval None */ void HAL_FLASHEx_EnableEccDetectionInterrupt(void) { __HAL_FLASH_ENABLE_IT(FLASH_IT_DBECCERR); } /** * @brief Disable ECC detection interrupt * @retval None */ void HAL_FLASHEx_DisableEccDetectionInterrupt(void) { __HAL_FLASH_DISABLE_IT(FLASH_IT_DBECCERR); } /** * @brief Get the ECC error information. * @param pData Pointer to an FLASH_EccInfoTypeDef structure that contains the * ECC error information. * @note This function should be called before ECC bit is cleared * (in callback function) * @retval None */ void HAL_FLASHEx_GetEccInfo(FLASH_EccInfoTypeDef *pData) { /* Check Null pointer */ assert_param(pData != NULL); /* Set address which generate ECC error */ if ((FLASH->ISR & FLASH_FLAG_SNECCERR) != 0U) { pData->Address = FLASH->ECCSFADDR; } else { pData->Address = FLASH->ECCDFADDR; } /* Set area according address */ if (IS_FLASH_MAIN_MEM_ADDRESS(pData->Address)) { pData->Area = FLASH_ECC_AREA_USER_BANK1; } else if (IS_FLASH_OTP_ADDRESS(pData->Address)) { pData->Area = FLASH_ECC_AREA_OTP; } else if ((pData->Address >= SYSTEM_FLASH_BASE) && (pData->Address < (SYSTEM_FLASH_BASE + SYSTEM_FLASH_SIZE))) { pData->Area = FLASH_ECC_AREA_SYSTEM; } else { pData->Area = FLASH_ECC_AREA_READ_ONLY; } /* Set Master which initiates transaction. On H7RS, it's necessary CPU1 */ pData->MasterID = FLASH_ECC_MASTER_CPU1; } /** * @brief Handle Flash ECC Detection interrupt request. * @note On STM32H7RS, this Irq Handler should be called in Bus Fault * interrupt subroutine. * @retval None */ void HAL_FLASHEx_ECCD_IRQHandler(void) { /* Check ECC Detection Error */ if ((FLASH->ISR & FLASH_FLAG_DBECCERR) != 0U) { /* Call User callback */ HAL_FLASHEx_EccDetectionCallback(); /* Clear ECC detection flag in order to allow new ECC error record */ FLASH->ICR = FLASH_FLAG_DBECCERR; } } /** * @brief FLASH ECC Correction interrupt callback. * @retval None */ __weak void HAL_FLASHEx_EccCorrectionCallback(void) { /* NOTE : This function should not be modified, when the callback is needed, the HAL_FLASHEx_EccCorrectionCallback could be implemented in the user file */ } /** * @brief FLASH ECC Detection interrupt callback. * @retval None */ __weak void HAL_FLASHEx_EccDetectionCallback(void) { /* NOTE : This function should not be modified, when the callback is needed, the HAL_FLASHEx_EccDetectionCallback could be implemented in the user file */ } /** * @} */ /** * @} */ /* Private functions ---------------------------------------------------------*/ /** @addtogroup FLASHEx_Private_Functions * @{ */ /** * @brief Mass erase of FLASH memory. * @retval None */ static void FLASH_MassErase(void) { /* Set the Mass Erase Bit and proceed to erase */ SET_BIT(FLASH->CR, (FLASH_CR_BER | FLASH_CR_START)); } /** * @brief Erase the specified FLASH memory sector. * @param Sector FLASH sector to erase * This parameter must be a value between 0 and (max number of sectors in the bank - 1) * @retval None */ void FLASH_SectorErase(uint32_t Sector) { /* Check the parameters */ assert_param(IS_FLASH_SECTOR(Sector)); /* Proceed to erase the page */ MODIFY_REG(FLASH->CR, (FLASH_CR_SSN | FLASH_CR_SER | FLASH_CR_START), \ ((Sector << FLASH_CR_SSN_Pos) | FLASH_CR_SER | FLASH_CR_START)); } /** * @brief Configure the write protection of the desired sectors. * * @note To configure the WRP options, the option lock bit OPTLOCK must be * cleared with the call of the HAL_FLASH_OB_Unlock() function. * * @param WRPState * * @param WRPSector * * @retval None */ static void FLASH_OB_WRPConfig(uint32_t WRPState, uint32_t WRPSector) { /* Check the parameters */ assert_param(IS_OB_WRPSTATE(WRPState)); /* Configure the write protected area */ if (WRPState == OB_WRPSTATE_DISABLE) { FLASH->WRPSRP |= (WRPSector & FLASH_WRPSRP_WRPS); } else if (WRPState == OB_WRPSTATE_ENABLE) { FLASH->WRPSRP &= (~(WRPSector & FLASH_WRPSRP_WRPS)); } else { /* Empty statement (to be compliant MISRA 15.7) */ } } /** * @brief Program the FLASH User Option Byte. * * @note To configure the user option bytes, the option lock bit OPTLOCK must * be cleared with the call of the HAL_FLASH_OB_Unlock() function. * @param UserType: The FLASH User Option Bytes to be modified. * This parameter can be a combination of @ref FLASH_OB_USER_TYPE * @param UserConfig1 The selected User Option Bytes values * @param UserConfig2 The selected User Option Bytes values * @retval None */ static void FLASH_OB_UserConfig(uint32_t UserType, uint32_t UserConfig1, uint32_t UserConfig2) { uint32_t optr_reg_val = 0; uint32_t optr_reg_mask = 0; /* Check the parameters */ assert_param(IS_OB_USER_TYPE(UserType)); if ((UserType & OB_USER_BOR_LEV) != 0U) { /* BOR level option byte should be modified */ assert_param(IS_OB_USER_BOR_LEVEL(UserConfig1 & FLASH_OBW1SR_BOR_LEVEL)); /* Set value and mask for BOR level option byte */ optr_reg_val |= (UserConfig1 & FLASH_OBW1SR_BOR_LEVEL); optr_reg_mask |= FLASH_OBW1SR_BOR_LEVEL; } if ((UserType & OB_USER_IWDG_SW) != 0U) { /* IWDG1_HW option byte should be modified */ assert_param(IS_OB_USER_IWDG(UserConfig1 & FLASH_OBW1SR_IWDG_HW)); /* Set value and mask for IWDG1_HW option byte */ optr_reg_val |= (UserConfig1 & FLASH_OBW1SR_IWDG_HW); optr_reg_mask |= FLASH_OBW1SR_IWDG_HW; } if ((UserType & OB_USER_NRST_STOP) != 0U) { /* NRST_STOP_D1 option byte should be modified */ assert_param(IS_OB_USER_STOP(UserConfig1 & FLASH_OBW1SR_NRST_STOP)); /* Set value and mask for NRST_STOP_D1 option byte */ optr_reg_val |= (UserConfig1 & FLASH_OBW1SR_NRST_STOP); optr_reg_mask |= FLASH_OBW1SR_NRST_STOP; } if ((UserType & OB_USER_NRST_STDBY) != 0U) { /* NRST_STBY_D1 option byte should be modified */ assert_param(IS_OB_USER_STANDBY(UserConfig1 & FLASH_OBW1SR_NRST_STBY)); /* Set value and mask for NRST_STBY_D1 option byte */ optr_reg_val |= (UserConfig1 & FLASH_OBW1SR_NRST_STBY); optr_reg_mask |= FLASH_OBW1SR_NRST_STBY; } if ((UserType & OB_USER_XSPI1_HSLV) != 0U) { /* XSPI1_HSLV option byte should be modified */ assert_param(IS_OB_USER_XSPI1_HSLV(UserConfig1 & FLASH_OBW1SR_XSPI1_HSLV)); /* Set value and mask for XSPI1_HSLV option byte */ optr_reg_val |= (UserConfig1 & FLASH_OBW1SR_XSPI1_HSLV); optr_reg_mask |= FLASH_OBW1SR_XSPI1_HSLV; } if ((UserType & OB_USER_XSPI2_HSLV) != 0U) { /* XSPI2_HSLV option byte should be modified */ assert_param(IS_OB_USER_XSPI2_HSLV(UserConfig1 & FLASH_OBW1SR_XSPI2_HSLV)); /* Set value and mask for XSPI2_HSLV option byte */ optr_reg_val |= (UserConfig1 & FLASH_OBW1SR_XSPI2_HSLV); optr_reg_mask |= FLASH_OBW1SR_XSPI2_HSLV; } if ((UserType & OB_USER_IWDG_STOP) != 0U) { /* IWDG_FZ_STOP option byte should be modified */ assert_param(IS_OB_USER_IWDG_STOP(UserConfig1 & FLASH_OBW1SR_IWDG_FZ_STOP)); /* Set value and mask for IWDG_FZ_STOP option byte */ optr_reg_val |= (UserConfig1 & FLASH_OBW1SR_IWDG_FZ_STOP); optr_reg_mask |= FLASH_OBW1SR_IWDG_FZ_STOP; } if ((UserType & OB_USER_IWDG_STDBY) != 0U) { /* IWDG_FZ_SDBY option byte should be modified */ assert_param(IS_OB_USER_IWDG_STDBY(UserConfig1 & FLASH_OBW1SR_IWDG_FZ_STBY)); /* Set value and mask for IWDG_FZ_SDBY option byte */ optr_reg_val |= (UserConfig1 & FLASH_OBW1SR_IWDG_FZ_STBY); optr_reg_mask |= FLASH_OBW1SR_IWDG_FZ_STBY; } if ((UserType & OB_USER_VDDIO_HSLV) != 0U) { /* VDDIO_HSLV option byte should be modified */ assert_param(IS_OB_USER_VDDIO_HSLV(UserConfig1 & FLASH_OBW1SR_VDDIO_HSLV)); /* Set value and mask for VDDIO_HSLV option byte */ optr_reg_val |= (UserConfig1 & FLASH_OBW1SR_VDDIO_HSLV); optr_reg_mask |= FLASH_OBW1SR_VDDIO_HSLV; } /* Configure the option bytes register 1 if necessary */ if (optr_reg_mask != 0U) { MODIFY_REG(FLASH->OBW1SRP, optr_reg_mask, optr_reg_val); } optr_reg_val = 0; optr_reg_mask = 0; if ((UserType & OB_USER_ITCM_AXI_SHARE) != 0U) { /* ITCM_AXI_SHARE option byte should be modified */ assert_param(IS_OB_USER_ITCM_AXI_SHARE(UserConfig2 & FLASH_OBW2SR_ITCM_AXI_SHARE)); /* Set value and mask for ITCM_AXI_SHARE option byte */ optr_reg_val |= (UserConfig2 & FLASH_OBW2SR_ITCM_AXI_SHARE); optr_reg_mask |= FLASH_OBW2SR_ITCM_AXI_SHARE; } if ((UserType & OB_USER_DTCM_AXI_SHARE) != 0U) { /* DTCM_AXI_SHARE option byte should be modified */ assert_param(IS_OB_USER_DTCM_AXI_SHARE(UserConfig2 & FLASH_OBW2SR_DTCM_AXI_SHARE)); /* Set value and mask for DTCM_AXI_SHARE option byte */ optr_reg_val |= (UserConfig2 & FLASH_OBW2SR_DTCM_AXI_SHARE); optr_reg_mask |= FLASH_OBW2SR_DTCM_AXI_SHARE; } if ((UserType & OB_USER_SRAM_ECC) != 0U) { /* SRAM_ECC option byte should be modified */ assert_param(IS_OB_USER_AXISRAM_ECC(UserConfig2 & FLASH_OBW2SR_ECC_ON_SRAM)); /* Set value and mask for SRAM_ECC option byte */ optr_reg_val |= (UserConfig2 & FLASH_OBW2SR_ECC_ON_SRAM); optr_reg_mask |= FLASH_OBW2SR_ECC_ON_SRAM; } if ((UserType & OB_USER_I2C_NI3C) != 0U) { /* I2C_NI3C option byte should be modified */ assert_param(IS_OB_USER_I2C_NI3C(UserConfig2 & FLASH_OBW2SR_I2C_NI3C)); /* Set value and mask for I2C_NI3C option byte */ optr_reg_val |= (UserConfig2 & FLASH_OBW2SR_I2C_NI3C); optr_reg_mask |= FLASH_OBW2SR_I2C_NI3C; } /* Configure the option bytes register 2 if necessary */ if (optr_reg_mask != 0U) { MODIFY_REG(FLASH->OBW2SRP, optr_reg_mask, optr_reg_val); } } /** * @brief Configure the Hide Protection. * * @note To configure the HDP options, the option lock bit OPTLOCK must be * cleared with the call of the HAL_FLASH_OB_Unlock() function. * * @param HDPStartPage * * @param HDPEndPage * * @retval None */ static void FLASH_OB_HDPConfig(uint32_t HDPStartPage, uint32_t HDPEndPage) { /* Check the parameters */ assert_param(IS_OB_HDP_PAGE(HDPStartPage)); assert_param(IS_OB_HDP_PAGE(HDPEndPage)); MODIFY_REG(FLASH->HDPSRP, (FLASH_HDPSRP_HDP_AREA_START | FLASH_HDPSRP_HDP_AREA_END), \ (HDPStartPage | (HDPEndPage << FLASH_HDPSRP_HDP_AREA_END_Pos))); } /** * @brief Configure the Non-Volatile state. * * @note To configure the Non-volatile options, the option lock bit OPTLOCK must be * cleared with the call of the HAL_FLASH_OB_Unlock() function. * * @param NVState * * @retval None */ static void FLASH_OB_NVConfig(uint32_t NVState) { /* Check the parameter */ assert_param(IS_OB_NVSTATE(NVState)); MODIFY_REG(FLASH->NVSRP, FLASH_NVSRP_NVSTATE, NVState); } /** * @brief Return the FLASH Write Protection Option Bytes value. * * @param WRPState * * @param WRPSector * * @retval None */ static void FLASH_OB_GetWRP(uint32_t *WRPState, uint32_t *WRPSector) { if ((FLASH->WRPSR & FLASH_WRPSR_WRPS) == FLASH_WRPSR_WRPS) { /* All sectors aren't write protected */ *WRPState = OB_WRPSTATE_DISABLE; } else { /* Some sectors are write protected */ *WRPState = OB_WRPSTATE_ENABLE; *WRPSector = ((~(FLASH->WRPSR)) & FLASH_WRPSR_WRPS); } } /** * @brief Return the FLASH User Option Byte value. * * @param UserConfig1 Address to return the FLASH User Option Bytes values configuration 1. * The return value can be a combination of * @param UserConfig2 Address to return the FLASH User Option Bytes values configuration 2. * The return value can be a combination of * * @retval None */ static void FLASH_OB_GetUser(uint32_t *UserConfig1, uint32_t *UserConfig2) { *UserConfig1 = FLASH->OBW1SR; *UserConfig2 = FLASH->OBW2SR; } /** * @brief Return the FLASH Hide Protection Option Bytes value. * * @param HDPStartPage Address to return the FLASH HDP Option Bytes Start Sector. * The return value can be a combination of * @param HDPEndPage Address to return the FLASH HDP Option Bytes End Sector. * The return value can be a combination of * * @retval None */ static void FLASH_OB_GetHDP(uint32_t *HDPStartPage, uint32_t *HDPEndPage) { *HDPStartPage = (FLASH->HDPSR & FLASH_HDPSR_HDP_AREA_START); *HDPEndPage = ((FLASH->HDPSR & FLASH_HDPSR_HDP_AREA_END) >> FLASH_HDPSR_HDP_AREA_END_Pos); } /** * @brief Return the FLASH Non-volatile state Option Bytes value. * * @retval Value of Non-volatile state */ static uint32_t FLASH_OB_GetNV(void) { return (FLASH->NVSR & FLASH_NVSR_NVSTATE); } /** * @brief Return the FLASH RoT Option Bytes value. * * @retval Value of the RoT */ static uint32_t FLASH_OB_GetRoT(void) { return (FLASH->ROTSR & (FLASH_ROTSR_OEM_PROVD | FLASH_ROTSR_DBG_AUTH | FLASH_ROTSR_IROT_SELECT)); } /** * @brief Return the FLASH Epoch Option Bytes value. * * @retval Value of the Epoch */ static uint32_t FLASH_OB_GetEpoch(void) { return (FLASH->EPOCHSR & FLASH_EPOCHSR_EPOCH); } /** * @brief Add a CRC sector to the list of sectors on which the CRC will be calculated * @param Sector Specifies the CRC sector number * @retval None */ static void FLASH_CRC_AddSector(uint32_t Sector) { /* Check the parameters */ assert_param(IS_FLASH_SECTOR(Sector)); /* Clear CRC sector */ MODIFY_REG(FLASH->CRCCR, FLASH_CRCCR_CRC_SECT, Sector); /* Activate ADD_SECT bit */ SET_BIT(FLASH->CRCCR, FLASH_CRCCR_ADD_SECT); } /** * @brief Select CRC start and end memory addresses on which the CRC will be calculated * @param CRCStartAddr Specifies the CRC start address * @param CRCEndAddr Specifies the CRC end address * @retval None */ static void FLASH_CRC_SelectAddress(uint32_t CRCStartAddr, uint32_t CRCEndAddr) { assert_param(IS_FLASH_MAIN_MEM_ADDRESS(CRCStartAddr)); assert_param(IS_FLASH_MAIN_MEM_ADDRESS(CRCEndAddr)); /* Write CRC Start and End addresses */ FLASH->CRCSADDR = (CRCStartAddr - FLASH_BASE); FLASH->CRCEADDR = (CRCEndAddr - FLASH_BASE); } /** * @brief Wait for a FLASH CRC computation to complete. * @param Timeout maximum flash operation timeout * @retval HAL_StatusTypeDef HAL Status */ static HAL_StatusTypeDef FLASH_CRC_WaitForLastOperation(uint32_t Timeout) { uint32_t timeout = HAL_GetTick() + Timeout; /* Wait for the FLASH CRC computation to complete by polling on CRC_BUSY flag to be reset */ while ((FLASH->SR & FLASH_SR_CRC_BUSY) != 0U) { if (HAL_GetTick() >= timeout) { return HAL_TIMEOUT; } } /* Check FLASH CRC calculation error flag */ if ((FLASH->ISR & FLASH_FLAG_CRCERR) != 0U) { /*Save the error code*/ pFlash.ErrorCode |= HAL_FLASH_ERROR_CRC; /* Clear CRC error flag */ FLASH->ICR = FLASH_FLAG_CRCERR; return HAL_ERROR; } /* Check FLASH CRC End of Calculation flag */ if ((FLASH->ISR & FLASH_FLAG_CRCEND) != 0U) { /* Clear FLASH End of Calculation pending bit */ FLASH->ICR = FLASH_FLAG_CRCEND; } /* If there is no error flag set */ return HAL_OK; } /** * @} */ /** * @} */ #endif /* HAL_FLASH_MODULE_ENABLED */ /** * @} */ /** * @} */