Files
CelloEffects/Drivers/STM32H7RSxx_HAL_Driver/Src/stm32h7rsxx_hal_flash_ex.c
T
2026-09-04 09:57:30 +02:00

1323 lines
39 KiB
C

/**
******************************************************************************
* @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 tickstart = HAL_GetTick();
/* 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() - tickstart) > Timeout) || (Timeout == 0U))
{
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 */
/**
* @}
*/
/**
* @}
*/