Files
BlindCane/Drivers/STM32H5xx_HAL_Driver/Src/stm32h5xx_hal_flash_ex.c
SocChina2025 7f9bede0c7 Initial commit
2025-05-07 22:22:44 +08:00

2048 lines
67 KiB
C

/**
******************************************************************************
* @file stm32h5xx_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 extension peripheral:
* + Extended programming operations functions
*
******************************************************************************
* @attention
*
* Copyright (c) 2023 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.
*
******************************************************************************
@verbatim
==============================================================================
##### Flash Extension features #####
==============================================================================
[..] Comparing to other previous devices, the FLASH interface for STM32H5xx
devices contains the following additional features
(+) Capacity up to 2 Mbyte with dual bank architecture supporting read-while-write
capability (RWW)
(+) Dual bank memory organization
(+) Product State protection
(+) Write protection
(+) Secure access only protection
(+) Bank / register swapping (when Dual-Bank)
(+) Watermark-based secure protection
(+) Block-based secure protection
(+) Block-based privilege protection
(+) Hide Protection areas
##### How to use this driver #####
==============================================================================
[..] This driver provides functions to configure and program the FLASH memory
of all STM32H5xx 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, bank erase and dual-bank mass erase
(++) There are two modes of erase :
(+++) Polling Mode using HAL_FLASHEx_Erase()
(+++) Interrupt Mode using HAL_FLASHEx_Erase_IT()
(#) Option Bytes Programming functions: Use HAL_FLASHEx_OBProgram() to:
(++) Configure the write protection per bank
(++) Set the Product State
(++) Program the user Option Bytes
(++) Configure the watermark security for each area
(++) Configure the Hide protection areas
(++) Configure the Boot addresses
(#) Get Option Bytes Configuration function: Use HAL_FLASHEx_OBGetConfig() to:
(++) Get the value of a write protection area
(++) Get the Product State
(++) Get the value of the user Option Bytes
(++) Get the configuration of watermark security areas
(++) Get the configuration of Hide protection areas
(++) Get the value of a boot address
(#) Block-based secure / privilege area configuration function: Use HAL_FLASHEx_ConfigBBAttributes()
(++) Bit-field allowing to secure or un-secure each sector
(++) Bit-field allowing to privilege or un-privilege each sector
(#) Get the block-based secure / privilege area configuration function: Use HAL_FLASHEx_GetConfigBBAttributes()
(++) Return the configuration of the block-based security and privilege for all the sectors
(#) Privilege mode configuration function: Use HAL_FLASHEx_ConfigPrivMode()
(++) FLASH register can be protected against non-privilege accesses
(#) Get the privilege mode configuration function: Use HAL_FLASHEx_GetPrivMode()
(++) Return if the FLASH registers are protected against non-privilege accesses
@endverbatim
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32h5xx_hal.h"
/** @addtogroup STM32H5xx_HAL_Driver
* @{
*/
/** @defgroup FLASHEx FLASHEx
* @brief FLASH HAL Extension module driver
* @{
*/
#ifdef HAL_FLASH_MODULE_ENABLED
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/** @defgroup FLASHEx_Private_Functions FLASHEx Private Functions
* @{
*/
static void FLASH_MassErase(uint32_t Banks);
#if defined (FLASH_SR_OBKERR)
static void FLASH_OBKErase(void);
#endif /* FLASH_SR_OBKERR */
static void FLASH_OB_EnableWRP(uint32_t WRPSector, uint32_t Banks);
static void FLASH_OB_DisableWRP(uint32_t WRPSector, uint32_t Bank);
static void FLASH_OB_GetWRP(uint32_t Bank, uint32_t *WRPState, uint32_t *WRPSector);
static void FLASH_OB_ProdStateConfig(uint32_t ProdStateConfig);
static uint32_t FLASH_OB_GetProdState(void);
static void FLASH_OB_UserConfig(uint32_t UserType, uint32_t UserConfig1, uint32_t UserConfig2);
static void FLASH_OB_GetUser(uint32_t *UserConfig1, uint32_t *UserConfig2);
static void FLASH_OB_BootAddrConfig(uint32_t BootOption, uint32_t BootAddress);
static void FLASH_OB_BootLockConfig(uint32_t BootLockOption, uint32_t BootLockConfig);
static void FLASH_OB_GetBootConfig(uint32_t BootOption, uint32_t *BootAddress, uint32_t *BootLockConfig);
static void FLASH_OB_OTP_LockConfig(uint32_t OTP_Block);
static uint32_t FLASH_OB_OTP_GetLock(void);
static void FLASH_OB_HDPConfig(uint32_t Banks, uint32_t HDPStartSector, uint32_t HDPEndSector);
static void FLASH_OB_GetHDP(uint32_t Bank, uint32_t *HDPStartSector, uint32_t *HDPEndSector);
#if defined(FLASH_EDATAR_EDATA_EN)
static void FLASH_OB_EDATAConfig(uint32_t Banks, uint32_t EDATASize);
static void FLASH_OB_GetEDATA(uint32_t Bank, uint32_t *EDATASize);
#endif /* FLASH_EDATAR_EDATA_EN */
#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
static void FLASH_OB_WMSECConfig(uint32_t Banks, uint32_t WMSecStartSector, uint32_t WMSecEndSector);
static void FLASH_OB_GetWMSEC(uint32_t Bank, uint32_t *WMSecStartSector, uint32_t *WMSecEndSector);
#endif /* __ARM_FEATURE_CMSE */
/**
* @}
*/
/* Exported functions ---------------------------------------------------------*/
/** @defgroup FLASHEx_Exported_Functions FLASHEx Exported Functions
* @{
*/
/** @defgroup FLASHEx_Exported_Functions_Group1 FLASHEx Extended IO operation functions
* @brief FLASHEx 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(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *SectorError)
{
HAL_StatusTypeDef status;
uint32_t sector_index;
__IO uint32_t *reg_cr;
/* 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)
{
/* Current operation type */
pFlash.ProcedureOnGoing = pEraseInit->TypeErase;
/* Access to SECCR or NSCR depends on operation type */
#if defined (FLASH_OPTSR2_TZEN)
reg_cr = IS_FLASH_SECURE_OPERATION() ? &(FLASH->SECCR) : &(FLASH_NS->NSCR);
#else
reg_cr = &(FLASH_NS->NSCR);
#endif /* FLASH_OPTSR2_TZEN */
if ((pEraseInit->TypeErase & (~FLASH_NON_SECURE_MASK)) == FLASH_TYPEERASE_MASSERASE)
{
/* Mass erase to be done */
FLASH_MassErase(pEraseInit->Banks);
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
}
#if defined (FLASH_SR_OBKERR)
else if (pEraseInit->TypeErase == FLASH_TYPEERASE_OBK_ALT)
{
/* OBK erase to be done */
FLASH_OBKErase();
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
}
#endif /* FLASH_SR_OBKERR */
else
{
/* Initialization of SectorError variable */
*SectorError = 0xFFFFFFFFU;
/* Erase by sector by sector to be done*/
for (sector_index = pEraseInit->Sector; sector_index < (pEraseInit->NbSectors + pEraseInit->Sector); \
sector_index++)
{
FLASH_Erase_Sector(sector_index, pEraseInit->Banks);
/* 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((*reg_cr), (pEraseInit->TypeErase) & (~(FLASH_NON_SECURE_MASK)));
}
/* 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(FLASH_EraseInitTypeDef *pEraseInit)
{
HAL_StatusTypeDef status;
__IO uint32_t *reg_cr;
/* Check the parameters */
assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase));
/* 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)
{
return status;
}
else
{
/* Set internal variables used by the IRQ handler */
pFlash.ProcedureOnGoing = pEraseInit->TypeErase;
pFlash.Bank = pEraseInit->Banks;
/* Access to SECCR or NSCR depends on operation type */
#if defined (FLASH_OPTSR2_TZEN)
reg_cr = IS_FLASH_SECURE_OPERATION() ? &(FLASH->SECCR) : &(FLASH_NS->NSCR);
#else
reg_cr = &(FLASH_NS->NSCR);
#endif /* FLASH_OPTSR2_TZEN */
/* Enable End of Operation and Error interrupts */
#if defined (FLASH_SR_OBKERR)
(*reg_cr) |= (FLASH_IT_EOP | FLASH_IT_WRPERR | FLASH_IT_PGSERR | \
FLASH_IT_STRBERR | FLASH_IT_INCERR | FLASH_IT_OBKERR | \
FLASH_IT_OBKWERR);
#else
(*reg_cr) |= (FLASH_IT_EOP | FLASH_IT_WRPERR | FLASH_IT_PGSERR | \
FLASH_IT_STRBERR | FLASH_IT_INCERR);
#endif /* FLASH_SR_OBKERR */
if ((pEraseInit->TypeErase & (~FLASH_NON_SECURE_MASK)) == FLASH_TYPEERASE_MASSERASE)
{
/* Mass erase to be done */
FLASH_MassErase(pEraseInit->Banks);
}
#if defined (FLASH_SR_OBKERR)
else if (pEraseInit->TypeErase == FLASH_TYPEERASE_OBK_ALT)
{
/* OBK erase to be done */
FLASH_OBKErase();
}
#endif /* FLASH_SR_OBKERR */
else
{
/* Erase by sector to be done */
pFlash.NbSectorsToErase = pEraseInit->NbSectors;
pFlash.Sector = pEraseInit->Sector;
/* Erase first sector and wait for IT */
FLASH_Erase_Sector(pEraseInit->Sector, pEraseInit->Banks);
}
}
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-on reset (BOR reset or exit from Standby/Shutdown modes)
* @retval HAL Status
*/
HAL_StatusTypeDef HAL_FLASHEx_OBProgram(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;
/* Current operation type */
pFlash.ProcedureOnGoing = FLASH_TYPEPROGRAM_OB;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
if (status == HAL_OK)
{
/*Write protection configuration*/
if ((pOBInit->OptionType & OPTIONBYTE_WRP) != 0U)
{
assert_param(IS_WRPSTATE(pOBInit->WRPState));
if (pOBInit->WRPState == OB_WRPSTATE_ENABLE)
{
/* Enable write protection on the selected sectors */
FLASH_OB_EnableWRP(pOBInit->WRPSector, pOBInit->Banks);
}
else
{
/* Disable write protection on the selected sectors */
FLASH_OB_DisableWRP(pOBInit->WRPSector, pOBInit->Banks);
}
}
/* Product State configuration */
if ((pOBInit->OptionType & OPTIONBYTE_PROD_STATE) != 0U)
{
/* Configure the product state */
FLASH_OB_ProdStateConfig(pOBInit->ProductState);
}
/* User Configuration */
if ((pOBInit->OptionType & OPTIONBYTE_USER) != 0U)
{
/* Configure the user option bytes */
FLASH_OB_UserConfig(pOBInit->USERType, pOBInit->USERConfig, pOBInit->USERConfig2);
}
#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
/* Watermark secure configuration */
if ((pOBInit->OptionType & OPTIONBYTE_WMSEC) != 0U)
{
/* Configure the watermark-based secure area */
FLASH_OB_WMSECConfig(pOBInit->Banks, pOBInit->WMSecStartSector, pOBInit->WMSecEndSector);
}
#endif /* __ARM_FEATURE_CMSE */
/* Boot Address configuration */
if ((pOBInit->OptionType & OPTIONBYTE_BOOTADDR) != 0U)
{
FLASH_OB_BootAddrConfig(pOBInit->BootConfig, pOBInit->BootAddr);
}
/* Unique boot entry point configuration */
if ((pOBInit->OptionType & OPTIONBYTE_BOOT_LOCK) != 0U)
{
/* Configure the unique boot entry point */
FLASH_OB_BootLockConfig(pOBInit->BootConfig, pOBInit->BootLock);
}
/* OTP Block Lock configuration */
if ((pOBInit->OptionType & OPTIONBYTE_OTP_LOCK) != 0U)
{
FLASH_OB_OTP_LockConfig(pOBInit->OTPBlockLock);
}
/* Hide Protection area configuration */
if ((pOBInit->OptionType & OPTIONBYTE_HDP) != 0U)
{
FLASH_OB_HDPConfig(pOBInit->Banks, pOBInit->HDPStartSector, pOBInit->HDPEndSector);
}
#if defined(FLASH_EDATAR_EDATA_EN)
/* Flash high-cycle data area configuration */
if ((pOBInit->OptionType & OPTIONBYTE_EDATA) != 0U)
{
FLASH_OB_EDATAConfig(pOBInit->Banks, pOBInit->EDATASize);
}
#endif /* FLASH_EDATAR_EDATA_EN */
}
/* Process Unlocked */
__HAL_UNLOCK(&pFlash);
return status;
}
/**
* @brief Get the Option byte configuration
* @param pOBInit pointer to an FLASH_OBInitStruct structure that
* contains the configuration information for the programming.
* @note The parameter Banks of the pOBInit structure must be set exclusively to FLASH_BANK_1 or FLASH_BANK_2,
* as this parameter is use to get the given Bank WRP, PCROP and secured area configuration.
*
* @retval None
*/
void HAL_FLASHEx_OBGetConfig(FLASH_OBProgramInitTypeDef *pOBInit)
{
pOBInit->OptionType = (OPTIONBYTE_USER | OPTIONBYTE_PROD_STATE);
/* Get Product State */
pOBInit->ProductState = FLASH_OB_GetProdState();
/* Get the user option bytes */
FLASH_OB_GetUser(&(pOBInit->USERConfig), &(pOBInit->USERConfig2));
if ((pOBInit->Banks == FLASH_BANK_1) || (pOBInit->Banks == FLASH_BANK_2))
{
/* Get write protection on the selected area */
pOBInit->OptionType |= OPTIONBYTE_WRP;
FLASH_OB_GetWRP(pOBInit->Banks, &(pOBInit->WRPState), &(pOBInit->WRPSector));
#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
/* Get the configuration of the watermark secure area for the selected area */
pOBInit->OptionType |= OPTIONBYTE_WMSEC;
FLASH_OB_GetWMSEC(pOBInit->Banks, &(pOBInit->WMSecStartSector), &(pOBInit->WMSecEndSector));
#endif /* __ARM_FEATURE_CMSE */
/* Get the configuration of the hide protection for the selected area */
pOBInit->OptionType |= OPTIONBYTE_HDP;
FLASH_OB_GetHDP(pOBInit->Banks, &(pOBInit->HDPStartSector), &(pOBInit->HDPEndSector));
#if defined (FLASH_EDATAR_EDATA_EN)
/* Get the Flash high-cycle data configuration for the selected area */
pOBInit->OptionType |= OPTIONBYTE_EDATA;
FLASH_OB_GetEDATA(pOBInit->Banks, &(pOBInit->EDATASize));
#endif /* FLASH_EDATAR_EDATA_EN */
}
/* Get boot configuration */
#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
if ((pOBInit->BootConfig == OB_BOOT_NS) || (pOBInit->BootConfig == OB_BOOT_SEC))
#else
if (pOBInit->BootConfig == OB_BOOT_NS)
#endif /* __ARM_FEATURE_CMSE */
{
pOBInit->OptionType |= OPTIONBYTE_BOOTADDR | OPTIONBYTE_BOOT_LOCK;
FLASH_OB_GetBootConfig(pOBInit->BootConfig, &(pOBInit->BootAddr), &(pOBInit->BootLock));
}
/* Get OTP Block Lock */
pOBInit->OptionType |= OPTIONBYTE_OTP_LOCK;
pOBInit->OTPBlockLock = FLASH_OB_OTP_GetLock();
}
#if defined (FLASH_SR_OBKERR)
/**
* @brief Unlock the FLASH OBK register access
* @retval HAL Status
*/
HAL_StatusTypeDef HAL_FLASHEx_OBK_Unlock(void)
{
HAL_StatusTypeDef status = HAL_OK;
#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
if (READ_BIT(FLASH->SECOBKCFGR, FLASH_OBKCFGR_LOCK) != 0U)
{
/* Authorize the FLASH OBK Register access */
WRITE_REG(FLASH->SECOBKKEYR, FLASH_OBK_KEY1);
WRITE_REG(FLASH->SECOBKKEYR, FLASH_OBK_KEY2);
/* Verify Flash OBK Register is unlocked */
if (READ_BIT(FLASH->SECOBKCFGR, FLASH_OBKCFGR_LOCK) != 0U)
{
status = HAL_ERROR;
}
}
#else
if (READ_BIT(FLASH->NSOBKCFGR, FLASH_OBKCFGR_LOCK) != 0U)
{
/* Authorize the FLASH OBK Register access */
WRITE_REG(FLASH->NSOBKKEYR, FLASH_OBK_KEY1);
WRITE_REG(FLASH->NSOBKKEYR, FLASH_OBK_KEY2);
/* Verify Flash OBK Register is unlocked */
if (READ_BIT(FLASH->NSOBKCFGR, FLASH_OBKCFGR_LOCK) != 0U)
{
status = HAL_ERROR;
}
}
#endif /* __ARM_FEATURE_CMSE */
return status;
}
/**
* @brief Locks the FLASH OBK register access
* @retval HAL Status
*/
HAL_StatusTypeDef HAL_FLASHEx_OBK_Lock(void)
{
HAL_StatusTypeDef status = HAL_ERROR;
#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
/* Set the LOCK Bit to lock the FLASH OBK Register access */
SET_BIT(FLASH->SECOBKCFGR, FLASH_OBKCFGR_LOCK);
/* verify Flash is locked */
if (READ_BIT(FLASH->SECOBKCFGR, FLASH_OBKCFGR_LOCK) != 0U)
{
status = HAL_OK;
}
#else
/* Set the LOCK Bit to lock the FLASH OBK Register access */
SET_BIT(FLASH->NSOBKCFGR, FLASH_OBKCFGR_LOCK);
/* Verify Flash OBK is locked */
if (READ_BIT(FLASH->NSOBKCFGR, FLASH_OBKCFGR_LOCK) != 0U)
{
status = HAL_OK;
}
#endif /* __ARM_FEATURE_CMSE */
return status;
}
/**
* @brief Swap the FLASH Option Bytes Keys (OBK)
* @param SwapOffset Specifies the number of keys to be swapped.
* This parameter can be a value between 0 (no OBK data swapped) and 511 (all OBK data swapped).
* Typical value are available in @ref FLASH_OBK_SWAP_Offset
* @retval HAL Status
*/
HAL_StatusTypeDef HAL_FLASHEx_OBK_Swap(uint32_t SwapOffset)
{
HAL_StatusTypeDef status;
__IO uint32_t *reg_obkcfgr;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
if (status == HAL_OK)
{
/* Access to SECOBKCFGR or NSOBKCFGR registers depends on operation type */
reg_obkcfgr = IS_FLASH_SECURE_OPERATION() ? &(FLASH->SECOBKCFGR) : &(FLASH_NS->NSOBKCFGR);
/* Set OBK swap offset */
MODIFY_REG((*reg_obkcfgr), FLASH_OBKCFGR_SWAP_OFFSET, (SwapOffset << FLASH_OBKCFGR_SWAP_OFFSET_Pos));
/* Set OBK swap request */
SET_BIT((*reg_obkcfgr), FLASH_OBKCFGR_SWAP_SECT_REQ);
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
}
return status;
}
/**
* @brief Swap the FLASH Option Bytes Keys (OBK) with interrupt enabled
* @param SwapOffset Specifies the number of keys to be swapped.
* This parameter can be a value between 0 (no OBK data swapped) and 511 (all OBK data swapped).
* Typical value are available in @ref FLASH_OBK_SWAP_Offset
* @retval HAL Status
*/
HAL_StatusTypeDef HAL_FLASHEx_OBK_Swap_IT(uint32_t SwapOffset)
{
HAL_StatusTypeDef status;
__IO uint32_t *reg_obkcfgr;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
if (status == HAL_OK)
{
/* Access to SECOBKCFGR or NSOBKCFGR registers depends on operation type */
reg_obkcfgr = IS_FLASH_SECURE_OPERATION() ? &(FLASH->SECOBKCFGR) : &(FLASH_NS->NSOBKCFGR);
/* Enable End of Operation and Error interrupts */
(*reg_obkcfgr) |= (FLASH_IT_EOP | FLASH_IT_WRPERR | FLASH_IT_PGSERR | FLASH_IT_STRBERR | FLASH_IT_INCERR);
/* Set OBK swap offset */
MODIFY_REG((*reg_obkcfgr), FLASH_OBKCFGR_SWAP_OFFSET, (SwapOffset << FLASH_OBKCFGR_SWAP_OFFSET_Pos));
/* Set OBK swap request */
SET_BIT((*reg_obkcfgr), FLASH_OBKCFGR_SWAP_SECT_REQ);
}
return status;
}
#endif /* FLASH_SR_OBKERR */
/**
* @brief Return the on-going Flash Operation. After a system reset, return
* the interrupted Flash operation, if any.
* @param pFlashOperation [out] pointer to a FLASH_OperationTypeDef structure
* that contains the Flash operation information.
* @retval None
*/
void HAL_FLASHEx_GetOperation(FLASH_OperationTypeDef *pFlashOperation)
{
uint32_t opsr_reg = FLASH->OPSR;
/* Get Flash operation Type */
pFlashOperation->OperationType = opsr_reg & FLASH_OPSR_CODE_OP;
/* Get Flash operation memory */
#if defined (FLASH_EDATAR_EDATA_EN)
pFlashOperation->FlashArea = opsr_reg & (FLASH_OPSR_DATA_OP | FLASH_OPSR_BK_OP | \
FLASH_OPSR_SYSF_OP | FLASH_OPSR_OTP_OP);
#else
pFlashOperation->FlashArea = opsr_reg & (FLASH_OPSR_BK_OP | FLASH_OPSR_SYSF_OP | \
FLASH_OPSR_OTP_OP);
#endif /* FLASH_EDATAR_EDATA_EN */
/* Get Flash operation address */
pFlashOperation->Address = opsr_reg & FLASH_OPSR_ADDR_OP;
}
/**
* @}
*/
/** @defgroup FLASHEx_Exported_Functions_Group2 FLASHEx Extension Protection configuration functions
* @brief Extension Protection configuration functions
* @{
*/
/**
* @brief Configure the block-based secure area.
*
* @param pBBAttributes pointer to an FLASH_BBAttributesTypeDef structure that
* contains the configuration information for the programming.
*
* @note The field pBBAttributes->Bank should indicate which area is requested
* for the block-based attributes.
* @note The field pBBAttributes->BBAttributesType should indicate which
* block-base attribute type is requested: Secure or Privilege.
*
* @retval HAL Status
*/
HAL_StatusTypeDef HAL_FLASHEx_ConfigBBAttributes(FLASH_BBAttributesTypeDef *pBBAttributes)
{
HAL_StatusTypeDef status;
uint8_t index;
__IO uint32_t *reg;
/* Check the parameters */
assert_param(IS_FLASH_BANK_EXCLUSIVE(pBBAttributes->Bank));
assert_param(IS_FLASH_BB_EXCLUSIVE(pBBAttributes->BBAttributesType));
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
if (status == HAL_OK)
{
/* Set the first Block-Based register to write */
#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
if (pBBAttributes->BBAttributesType == FLASH_BB_SEC)
{
if (pBBAttributes->Bank == FLASH_BANK_1)
{
reg = &(FLASH->SECBB1R1);
}
else
{
reg = &(FLASH->SECBB2R1);
}
}
else
#endif /* __ARM_FEATURE_CMSE */
{
if (pBBAttributes->Bank == FLASH_BANK_1)
{
reg = &(FLASH->PRIVBB1R1);
}
else
{
reg = &(FLASH->PRIVBB2R1);
}
}
/* Modify the register values and check that new attributes are taken in account */
for (index = 0; index < FLASH_BLOCKBASED_NB_REG; index++)
{
*reg = pBBAttributes->BBAttributes_array[index] & FLASH_PRIVBBR_PRIVBB;
if ((*reg) != (pBBAttributes->BBAttributes_array[index] & FLASH_PRIVBBR_PRIVBB))
{
status = HAL_ERROR;
}
reg++;
}
/* ISB instruction is called to be sure next instructions are performed with correct attributes */
__ISB();
}
/* Process Unlocked */
__HAL_UNLOCK(&pFlash);
return status;
}
/**
* @brief Return the block-based attributes.
*
* @param pBBAttributes [in/out] pointer to an FLASH_BBAttributesTypeDef structure
* that contains the configuration information.
* @note The field pBBAttributes->Bank should indicate which area is requested
* for the block-based attributes.
* @note The field pBBAttributes->BBAttributesType should indicate which
* block-base attribute type is requested: Secure or Privilege.
*
* @retval None
*/
void HAL_FLASHEx_GetConfigBBAttributes(FLASH_BBAttributesTypeDef *pBBAttributes)
{
uint8_t index;
__IO uint32_t *reg;
/* Check the parameters */
assert_param(IS_FLASH_BANK_EXCLUSIVE(pBBAttributes->Bank));
assert_param(IS_FLASH_BB_EXCLUSIVE(pBBAttributes->BBAttributesType));
/* Set the first Block-Based register to read */
#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
if (pBBAttributes->BBAttributesType == FLASH_BB_SEC)
{
if (pBBAttributes->Bank == FLASH_BANK_1)
{
reg = &(FLASH->SECBB1R1);
}
else
{
reg = &(FLASH->SECBB2R1);
}
}
else
#endif /* __ARM_FEATURE_CMSE */
{
if (pBBAttributes->Bank == FLASH_BANK_1)
{
reg = &(FLASH->PRIVBB1R1);
}
else
{
reg = &(FLASH->PRIVBB2R1);
}
}
/* Read the register values */
for (index = 0; index < FLASH_BLOCKBASED_NB_REG; index++)
{
pBBAttributes->BBAttributes_array[index] = (*reg) & FLASH_PRIVBBR_PRIVBB;
reg++;
}
}
/**
* @brief Configuration of the privilege attribute.
*
* @param PrivMode indicate privilege mode configuration
* This parameter can be one of the following values:
* @arg FLASH_SPRIV_GRANTED: access to secure Flash registers is granted to privileged or unprivileged access
* @arg FLASH_SPRIV_DENIED: access to secure Flash registers is denied to unprivileged access
* @arg FLASH_NSPRIV_GRANTED: access to non-secure Flash registers is granted to privileged or unprivileged access
* @arg FLASH_NSPRIV_DENIED: access to non-secure Flash registers is denied to unprivilege access
*
* @retval None
*/
void HAL_FLASHEx_ConfigPrivMode(uint32_t PrivMode)
{
/* Check the parameters */
assert_param(IS_FLASH_CFGPRIVMODE(PrivMode));
#if defined (FLASH_PRIVCFGR_SPRIV)
MODIFY_REG(FLASH->PRIVCFGR, (FLASH_PRIVCFGR_SPRIV | FLASH_PRIVCFGR_NSPRIV), PrivMode);
#else
MODIFY_REG(FLASH->PRIVCFGR, FLASH_PRIVCFGR_NSPRIV, PrivMode);
#endif /* FLASH_PRIVCFGR_SPRIV */
}
/**
* @brief Return the value of the privilege attribute.
*
* @retval It indicates the privilege mode configuration.
* This return value can be one of the following values:
* @arg FLASH_SPRIV_GRANTED: access to secure Flash registers is granted to privileged or unprivileged access
* @arg FLASH_SPRIV_DENIED: access to secure Flash registers is denied to unprivileged access
* @arg FLASH_NSPRIV_GRANTED: access to non-secure Flash registers is granted to privileged or unprivileged access
* @arg FLASH_NSPRIV_DENIED: access to Flash registers is denied to unprivilege accessP
*/
uint32_t HAL_FLASHEx_GetPrivMode(void)
{
#if defined (FLASH_PRIVCFGR_SPRIV)
return (FLASH->PRIVCFGR & (FLASH_PRIVCFGR_SPRIV | FLASH_PRIVCFGR_NSPRIV));
#else
return (FLASH->PRIVCFGR & FLASH_PRIVCFGR_NSPRIV);
#endif /* FLASH_PRIVCFGR_SPRIV */
}
#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
/**
* @brief Configuration of the security inversion.
*
* @param SecInvState indicate the flash security state configuration
* This parameter can be one of the following values:
* @arg FLASH_SEC_INV_DISABLE: Security state of Flash is not inverted
* @arg FLASH_SEC_INV_ENABLE: Security state of Flash is inverted
*
* @retval HAL Status
*/
HAL_StatusTypeDef HAL_FLASHEx_ConfigSecInversion(uint32_t SecInvState)
{
HAL_StatusTypeDef status;
/* Check the parameters */
assert_param(IS_FLASH_CFGSECINV(SecInvState));
/* Process Locked */
__HAL_LOCK(&pFlash);
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
if (status == HAL_OK)
{
MODIFY_REG(FLASH->SECCR, FLASH_CR_INV, SecInvState);
}
/* Process Unlocked */
__HAL_UNLOCK(&pFlash);
return status;
}
/**
* @brief Return the value of the security inversion.
*
* @retval It indicates the flash security state configuration
* This return value can be one of the following values:
* @arg FLASH_SEC_INV_DISABLE: Security state of Flash is not inverted
* @arg FLASH_SEC_INV_ENABLE: Security state of Flash is inverted
*/
uint32_t HAL_FLASHEx_GetSecInversion(void)
{
return (FLASH->SECCR & FLASH_CR_INV);
}
#endif /* __ARM_FEATURE_CMSE */
/**
* @brief Configure the HDP extension area.
*
* @param pHDPExtension pointer to an FLASH_HDPExtentionTypeDef structure that
* contains the configuration information.
*
* @note The field pHDPExtension->Banks should indicate which area is requested
* for the HDP extension.
* @note The field pHDPExtension->NbSectors should indicate the number of
* sector to be added to the HDP area.
*
* @retval HAL Status
*/
HAL_StatusTypeDef HAL_FLASHEx_ConfigHDPExtension(const FLASH_HDPExtensionTypeDef *pHDPExtension)
{
/* Check the parameters */
assert_param(IS_FLASH_BANK(pHDPExtension->Banks));
assert_param(IS_FLASH_SECTOR(pHDPExtension->NbSectors));
/* Set the HDP extension register */
if (pHDPExtension->Banks == FLASH_BANK_1)
{
MODIFY_REG(FLASH->HDPEXTR, FLASH_HDPEXTR_HDP1_EXT, pHDPExtension->NbSectors);
}
else if (pHDPExtension->Banks == FLASH_BANK_2)
{
MODIFY_REG(FLASH->HDPEXTR, FLASH_HDPEXTR_HDP2_EXT, (pHDPExtension->NbSectors << FLASH_HDPEXTR_HDP2_EXT_Pos));
}
else
{
FLASH->HDPEXTR = (pHDPExtension->NbSectors << FLASH_HDPEXTR_HDP2_EXT_Pos) | pHDPExtension->NbSectors;
}
return HAL_OK;
}
/**
* @}
*/
/**
* @}
*/
/* Private functions ---------------------------------------------------------*/
/** @addtogroup FLASHEx_Private_Functions
* @{
*/
/**
* @brief Mass erase of FLASH memory
* @param Banks Banks to be erased
* This parameter can be one of the following values:
* @arg FLASH_BANK_1: Bank1 to be erased
* @arg FLASH_BANK_2: Bank2 to be erased
* @arg FLASH_BANK_BOTH: Bank1 and Bank2 to be erased
* @retval None
*/
static void FLASH_MassErase(uint32_t Banks)
{
__IO uint32_t *reg_cr;
/* Check the parameters */
assert_param(IS_FLASH_BANK(Banks));
/* Access to SECCR or NSCR registers depends on operation type */
#if defined (FLASH_OPTSR2_TZEN)
reg_cr = IS_FLASH_SECURE_OPERATION() ? &(FLASH->SECCR) : &(FLASH_NS->NSCR);
#else
reg_cr = &(FLASH_NS->NSCR);
#endif /* FLASH_OPTSR2_TZEN */
/* Flash Mass Erase */
if ((Banks & FLASH_BANK_BOTH) == FLASH_BANK_BOTH)
{
/* Set Mass Erase Bit */
SET_BIT((*reg_cr), FLASH_CR_MER | FLASH_CR_START);
}
else
{
/* Proceed to erase Flash Bank */
if ((Banks & FLASH_BANK_1) == FLASH_BANK_1)
{
/* Erase Bank1 */
MODIFY_REG((*reg_cr), (FLASH_CR_BKSEL | FLASH_CR_BER | FLASH_CR_START), (FLASH_CR_BER | FLASH_CR_START));
}
if ((Banks & FLASH_BANK_2) == FLASH_BANK_2)
{
/* Erase Bank2 */
SET_BIT((*reg_cr), (FLASH_CR_BER | FLASH_CR_BKSEL | FLASH_CR_START));
}
}
}
/**
* @brief Erase the specified FLASH memory sector
* @param Sector FLASH sector to erase
* This parameter can be a value of @ref FLASH_Sectors
* @param Banks Bank(s) where the sector will be erased
* This parameter can be one of the following values:
* @arg FLASH_BANK_1: Sector in bank 1 to be erased
* @arg FLASH_BANK_2: Sector in bank 2 to be erased
* @retval None
*/
void FLASH_Erase_Sector(uint32_t Sector, uint32_t Banks)
{
__IO uint32_t *reg_cr;
/* Check the parameters */
assert_param(IS_FLASH_SECTOR(Sector));
assert_param(IS_FLASH_BANK_EXCLUSIVE(Banks));
/* Access to SECCR or NSCR registers depends on operation type */
#if defined (FLASH_OPTSR2_TZEN)
reg_cr = IS_FLASH_SECURE_OPERATION() ? &(FLASH->SECCR) : &(FLASH_NS->NSCR);
#else
reg_cr = &(FLASH_NS->NSCR);
#endif /* FLASH_OPTSR2_TZEN */
if ((Banks & FLASH_BANK_1) == FLASH_BANK_1)
{
/* Reset Sector Number for Bank1 */
(*reg_cr) &= ~(FLASH_CR_SNB | FLASH_CR_BKSEL);
(*reg_cr) |= (FLASH_CR_SER | (Sector << FLASH_CR_SNB_Pos) | FLASH_CR_START);
}
else
{
/* Reset Sector Number for Bank2 */
(*reg_cr) &= ~(FLASH_CR_SNB);
(*reg_cr) |= (FLASH_CR_SER | FLASH_CR_BKSEL | (Sector << FLASH_CR_SNB_Pos) | FLASH_CR_START);
}
}
#if defined (FLASH_SR_OBKERR)
/**
* @brief Erase of FLASH OBK
* @retval None
*/
static void FLASH_OBKErase()
{
__IO uint32_t *reg_obkcfgr;
/* Access to SECOBKCFGR or NSOBKCFGR registers depends on operation type */
reg_obkcfgr = IS_FLASH_SECURE_OPERATION() ? &(FLASH->SECOBKCFGR) : &(FLASH_NS->NSOBKCFGR);
/* Set OBK Erase Bit */
SET_BIT((*reg_obkcfgr), FLASH_OBKCFGR_ALT_SECT_ERASE);
}
#endif /* FLASH_SR_OBKERR */
/**
* @brief Enable the write protection of the desired bank1 or bank 2 sectors
* @param WRPSector specifies the sectors to be write protected.
* This parameter can be a value of @ref FLASH_OB_Write_Protection_Sectors
*
* @param Banks the specific bank to apply WRP sectors
* This parameter can be one of the following values:
* @arg FLASH_BANK_1: enable WRP on specified bank1 sectors
* @arg FLASH_BANK_2: enable WRP on specified bank2 sectors
* @arg FLASH_BANK_BOTH: enable WRP on both bank1 and bank2 specified sectors
*
* @retval None
*/
static void FLASH_OB_EnableWRP(uint32_t WRPSector, uint32_t Banks)
{
/* Check the parameters */
assert_param(IS_FLASH_BANK(Banks));
if ((Banks & FLASH_BANK_1) == FLASH_BANK_1)
{
/* Enable Write Protection for bank 1 */
FLASH->WRP1R_PRG &= (~(WRPSector & FLASH_WRPR_WRPSG));
}
if ((Banks & FLASH_BANK_2) == FLASH_BANK_2)
{
/* Enable Write Protection for bank 2 */
FLASH->WRP2R_PRG &= (~(WRPSector & FLASH_WRPR_WRPSG));
}
}
/**
* @brief Disable the write protection of the desired bank1 or bank 2 sectors
* @param WRPSector specifies the sectors to disable write protection.
* This parameter can be a value of @ref FLASH_OB_Write_Protection_Sectors
*
* @param Banks the specific bank to apply WRP sectors
* This parameter can be one of the following values:
* @arg FLASH_BANK_1: disable WRP on specified bank1 sectors
* @arg FLASH_BANK_2: disable WRP on specified bank2 sectors
* @arg FLASH_BANK_BOTH: disable WRP on both bank1 and bank2 specified sectors
*
* @retval None
*/
static void FLASH_OB_DisableWRP(uint32_t WRPSector, uint32_t Banks)
{
/* Check the parameters */
assert_param(IS_FLASH_BANK(Banks));
if ((Banks & FLASH_BANK_1) == FLASH_BANK_1)
{
/* Disable Write Protection for bank 1 */
FLASH->WRP1R_PRG |= (WRPSector & FLASH_WRPR_WRPSG);
}
if ((Banks & FLASH_BANK_2) == FLASH_BANK_2)
{
/* Disable Write Protection for bank 2 */
FLASH->WRP2R_PRG |= (WRPSector & FLASH_WRPR_WRPSG);
}
}
/**
* @brief Get the write protection of the given bank 1 or bank 2 sectors
* @param[in] Bank specifies the bank where to get the write protection sectors.
* This parameter can be exclusively one of the following values:
* @arg FLASH_BANK_1: Get bank1 WRP sectors
* @arg FLASH_BANK_2: Get bank2 WRP sectors
*
* @param[out] WRPState returns the write protection state of the returned sectors.
* This parameter can be one of the following values:
* @arg WRPState: OB_WRPSTATE_DISABLE or OB_WRPSTATE_ENABLE
* @param[out] WRPSector returns the write protected sectors on the given bank .
* This parameter can be a value of @ref FLASH_OB_Write_Protection_Sectors
*
* @retval None
*/
static void FLASH_OB_GetWRP(uint32_t Bank, uint32_t *WRPState, uint32_t *WRPSector)
{
uint32_t regvalue = 0U;
if (Bank == FLASH_BANK_1)
{
regvalue = FLASH->WRP1R_CUR;
}
if (Bank == FLASH_BANK_2)
{
regvalue = FLASH->WRP2R_CUR;
}
(*WRPSector) = (~regvalue) & FLASH_WRPR_WRPSG;
if (*WRPSector == 0U)
{
(*WRPState) = OB_WRPSTATE_DISABLE;
}
else
{
(*WRPState) = OB_WRPSTATE_ENABLE;
}
}
/**
* @brief Set the product state.
*
* @note To configure the product state, the option lock bit OPTLOCK must be
* cleared with the call of the HAL_FLASH_OB_Unlock() function.
* @note To validate the product state, the option bytes must be reloaded
* through the call of the HAL_FLASH_OB_Launch() function.
*
* @param ProductState specifies the product state.
* This parameter can be a value of @ref FLASH_OB_Product_State
*
* @retval None
*/
static void FLASH_OB_ProdStateConfig(uint32_t ProductState)
{
/* Check the parameters */
assert_param(IS_OB_PRODUCT_STATE(ProductState));
/* Configure the Product State in the option bytes register */
MODIFY_REG(FLASH->OPTSR_PRG, FLASH_OPTSR_PRODUCT_STATE, ProductState);
}
/**
* @brief Get the the product state.
* @retval ProductState returns the product state.
* This returned value can a value of @ref FLASH_OB_Product_State
*/
static uint32_t FLASH_OB_GetProdState(void)
{
return (FLASH->OPTSR_CUR & FLASH_OPTSR_PRODUCT_STATE);
}
/**
* @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.
* @note To validate the user option bytes, the option bytes must be reloaded
* through the call of the HAL_FLASH_OB_Launch() function.
*
* @param UserType specifies The FLASH User Option Bytes to be modified.
* This parameter can be a combination of @ref FLASH_OB_USER_Type
*
* @param UserConfig1 specifies values of the selected User Option Bytes.
* This parameter can be a combination of @ref FLASH_OB_USER_BOR_LEVEL,
* @ref FLASH_OB_USER_BORH_EN, @ref FLASH_OB_USER_IWDG_SW,
* @ref FLASH_OB_USER_WWDG_SW, @ref FLASH_OB_USER_nRST_STOP,
* @ref FLASH_OB_USER_nRST_STANDBY, @ref FLASH_OB_USER_IO_VDD_HSLV,
* @ref FLASH_OB_USER_IO_VDDIO2_HSLV, @ref FLASH_OB_USER_IWDG_STOP,
* @ref FLASH_OB_USER_IWDG_STANDBY, @ref FLASH_OB_USER_BOOT_UBE and @ref OB_USER_SWAP_BANK.
* @param UserConfig2 specifies values of the selected User Option Bytes.
* @ref FLASH_OB_USER_SRAM1_3_RST, @ref FLASH_OB_USER_SRAM2_RST,
* @ref FLASH_OB_USER_BKPRAM_ECC, @ref FLASH_OB_USER_SRAM3_ECC,
* @ref FLASH_OB_USER_SRAM2_ECC, @ref FLASH_OB_USER_SRAM1_ECC,
* @ref FLASH_OB_USER_SRAM1_RST and @ref OB_USER_TZEN.
* @retval None
*/
static void FLASH_OB_UserConfig(uint32_t UserType, uint32_t UserConfig1, uint32_t UserConfig2)
{
uint32_t optr_reg1_val = 0U;
uint32_t optr_reg1_mask = 0U;
uint32_t optr_reg2_val = 0U;
uint32_t optr_reg2_mask = 0U;
/* 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_OPTSR_BOR_LEV));
/* Set value and mask for BOR level option byte */
optr_reg1_val |= (UserConfig1 & FLASH_OPTSR_BOR_LEV);
optr_reg1_mask |= FLASH_OPTSR_BOR_LEV;
}
if ((UserType & OB_USER_BORH_EN) != 0U)
{
/* BOR high enable status bit should be modified */
assert_param(IS_OB_USER_BORH_EN(UserConfig1 & FLASH_OPTSR_BORH_EN));
/* Set value and mask for BOR high enable status bit */
optr_reg1_val |= (UserConfig1 & FLASH_OPTSR_BORH_EN);
optr_reg1_mask |= FLASH_OPTSR_BORH_EN;
}
if ((UserType & OB_USER_IWDG_SW) != 0U)
{
/* IWDG_SW option byte should be modified */
assert_param(IS_OB_USER_IWDG(UserConfig1 & FLASH_OPTSR_IWDG_SW));
/* Set value and mask for IWDG_SW option byte */
optr_reg1_val |= (UserConfig1 & FLASH_OPTSR_IWDG_SW);
optr_reg1_mask |= FLASH_OPTSR_IWDG_SW;
}
if ((UserType & OB_USER_WWDG_SW) != 0U)
{
/* WWDG_SW option byte should be modified */
assert_param(IS_OB_USER_WWDG(UserConfig1 & FLASH_OPTSR_WWDG_SW));
/* Set value and mask for WWDG_SW option byte */
optr_reg1_val |= (UserConfig1 & FLASH_OPTSR_WWDG_SW);
optr_reg1_mask |= FLASH_OPTSR_WWDG_SW;
}
if ((UserType & OB_USER_NRST_STOP) != 0U)
{
/* nRST_STOP option byte should be modified */
assert_param(IS_OB_USER_STOP(UserConfig1 & FLASH_OPTSR_NRST_STOP));
/* Set value and mask for nRST_STOP option byte */
optr_reg1_val |= (UserConfig1 & FLASH_OPTSR_NRST_STOP);
optr_reg1_mask |= FLASH_OPTSR_NRST_STOP;
}
if ((UserType & OB_USER_NRST_STDBY) != 0U)
{
/* nRST_STDBY option byte should be modified */
assert_param(IS_OB_USER_STANDBY(UserConfig1 & FLASH_OPTSR_NRST_STDBY));
/* Set value and mask for nRST_STDBY option byte */
optr_reg1_val |= (UserConfig1 & FLASH_OPTSR_NRST_STDBY);
optr_reg1_mask |= FLASH_OPTSR_NRST_STDBY;
}
if ((UserType & OB_USER_IO_VDD_HSLV) != 0U)
{
/* IO_VDD_HSLV option byte should be modified */
assert_param(IS_OB_USER_IO_VDD_HSLV(UserConfig1 & FLASH_OPTSR_IO_VDD_HSLV));
/* Set value and mask for IO_VDD_HSLV option byte */
optr_reg1_val |= (UserConfig1 & FLASH_OPTSR_IO_VDD_HSLV);
optr_reg1_mask |= FLASH_OPTSR_IO_VDD_HSLV;
}
if ((UserType & OB_USER_IO_VDDIO2_HSLV) != 0U)
{
/* IO_VDD_HSLV option byte should be modified */
assert_param(IS_OB_USER_IO_VDDIO2_HSLV(UserConfig1 & FLASH_OPTSR_IO_VDDIO2_HSLV));
/* Set value and mask for IO_VDD_HSLV option byte */
optr_reg1_val |= (UserConfig1 & FLASH_OPTSR_IO_VDDIO2_HSLV);
optr_reg1_mask |= FLASH_OPTSR_IO_VDDIO2_HSLV;
}
if ((UserType & OB_USER_IWDG_STOP) != 0U)
{
/* IWDG_STOP option byte should be modified */
assert_param(IS_OB_USER_IWDG_STOP(UserConfig1 & FLASH_OPTSR_IWDG_STOP));
/* Set value and mask for IWDG_STOP option byte */
optr_reg1_val |= (UserConfig1 & FLASH_OPTSR_IWDG_STOP);
optr_reg1_mask |= FLASH_OPTSR_IWDG_STOP;
}
if ((UserType & OB_USER_IWDG_STDBY) != 0U)
{
/* IWDG_STDBY option byte should be modified */
assert_param(IS_OB_USER_IWDG_STDBY(UserConfig1 & FLASH_OPTSR_IWDG_STDBY));
/* Set value and mask for IWDG_STDBY option byte */
optr_reg1_val |= (UserConfig1 & FLASH_OPTSR_IWDG_STDBY);
optr_reg1_mask |= FLASH_OPTSR_IWDG_STDBY;
}
#if defined (FLASH_OPTSR_BOOT_UBE)
if ((UserType & OB_USER_BOOT_UBE) != 0U)
{
/* SWAP_BANK option byte should be modified */
assert_param(IS_OB_USER_BOOT_UBE(UserConfig1 & FLASH_OPTSR_BOOT_UBE));
/* Set value and mask for BOOT_UBE option byte */
optr_reg1_val |= (UserConfig1 & FLASH_OPTSR_BOOT_UBE);
optr_reg1_mask |= FLASH_OPTSR_BOOT_UBE;
}
#endif /* FLASH_OPTSR_BOOT_UBE */
if ((UserType & OB_USER_SWAP_BANK) != 0U)
{
/* SWAP_BANK option byte should be modified */
assert_param(IS_OB_USER_SWAP_BANK(UserConfig1 & FLASH_OPTSR_SWAP_BANK));
/* Set value and mask for SWAP_BANK option byte */
optr_reg1_val |= (UserConfig1 & FLASH_OPTSR_SWAP_BANK);
optr_reg1_mask |= FLASH_OPTSR_SWAP_BANK;
}
#if defined (FLASH_OPTSR2_SRAM1_3_RST)
if ((UserType & OB_USER_SRAM1_3_RST) != 0U)
{
/* SRAM13_RST option byte should be modified */
assert_param(IS_OB_USER_SRAM1_3_RST(UserConfig2 & FLASH_OPTSR2_SRAM1_3_RST));
/* Set value and mask for SRAM13_RST option byte */
optr_reg2_val |= (UserConfig2 & FLASH_OPTSR2_SRAM1_3_RST);
optr_reg2_mask |= FLASH_OPTSR2_SRAM1_3_RST;
}
#endif /* FLASH_OPTSR2_SRAM1_3_RST */
#if defined (FLASH_OPTSR2_SRAM1_RST)
if ((UserType & OB_USER_SRAM1_RST) != 0U)
{
/* SRAM1_RST option byte should be modified */
assert_param(IS_OB_USER_SRAM1_RST(UserConfig2 & FLASH_OPTSR2_SRAM1_RST));
/* Set value and mask for SRAM1_RST option byte */
optr_reg2_val |= (UserConfig2 & FLASH_OPTSR2_SRAM1_RST);
optr_reg2_mask |= FLASH_OPTSR2_SRAM1_RST;
}
#endif /* FLASH_OPTSR2_SRAM1_RST */
if ((UserType & OB_USER_SRAM2_RST) != 0U)
{
/* SRAM2_RST option byte should be modified */
assert_param(IS_OB_USER_SRAM2_RST(UserConfig2 & FLASH_OPTSR2_SRAM2_RST));
/* Set value and mask for SRAM2_RST option byte */
optr_reg2_val |= (UserConfig2 & FLASH_OPTSR2_SRAM2_RST);
optr_reg2_mask |= FLASH_OPTSR2_SRAM2_RST;
}
if ((UserType & OB_USER_BKPRAM_ECC) != 0U)
{
/* BKPRAM_ECC option byte should be modified */
assert_param(IS_OB_USER_BKPRAM_ECC(UserConfig2 & FLASH_OPTSR2_BKPRAM_ECC));
/* Set value and mask for BKPRAM_ECC option byte */
optr_reg2_val |= (UserConfig2 & FLASH_OPTSR2_BKPRAM_ECC);
optr_reg2_mask |= FLASH_OPTSR2_BKPRAM_ECC;
}
#if defined (FLASH_OPTSR2_SRAM3_ECC)
if ((UserType & OB_USER_SRAM3_ECC) != 0U)
{
/* SRAM3_ECC option byte should be modified */
assert_param(IS_OB_USER_SRAM3_ECC(UserConfig2 & FLASH_OPTSR2_SRAM3_ECC));
/* Set value and mask for SRAM3_ECC option byte */
optr_reg2_val |= (UserConfig2 & FLASH_OPTSR2_SRAM3_ECC);
optr_reg2_mask |= FLASH_OPTSR2_SRAM3_ECC;
}
#endif /* FLASH_OPTSR2_SRAM3_ECC */
if ((UserType & OB_USER_SRAM2_ECC) != 0U)
{
/* SRAM2_ECC option byte should be modified */
assert_param(IS_OB_USER_SRAM2_ECC(UserConfig2 & FLASH_OPTSR2_SRAM2_ECC));
/* Set value and mask for SRAM2_ECC option byte */
optr_reg2_val |= (UserConfig2 & FLASH_OPTSR2_SRAM2_ECC);
optr_reg2_mask |= FLASH_OPTSR2_SRAM2_ECC;
}
#if defined (FLASH_OPTSR2_SRAM1_ECC)
if ((UserType & OB_USER_SRAM1_ECC) != 0U)
{
/* SRAM2_ECC option byte should be modified */
assert_param(IS_OB_USER_SRAM1_ECC(UserConfig2 & FLASH_OPTSR2_SRAM1_ECC));
/* Set value and mask for SRAM2_ECC option byte */
optr_reg2_val |= (UserConfig2 & FLASH_OPTSR2_SRAM1_ECC);
optr_reg2_mask |= FLASH_OPTSR2_SRAM1_ECC;
}
#endif /* FLASH_OPTSR2_SRAM1_ECC */
#if defined (FLASH_OPTSR2_USBPD_DIS)
if ((UserType & OB_USER_USBPD_DIS) != 0U)
{
/* USBPD_DIS option byte should be modified */
assert_param(IS_OB_USER_USBPD_DIS(UserConfig2 & FLASH_OPTSR2_USBPD_DIS));
/* Set value and mask for USBPD_DIS option byte */
optr_reg2_val |= (UserConfig2 & FLASH_OPTSR2_USBPD_DIS);
optr_reg2_mask |= FLASH_OPTSR2_USBPD_DIS;
}
#endif /* FLASH_OPTSR2_USBPD_DIS */
#if defined (FLASH_OPTSR2_TZEN)
if ((UserType & OB_USER_TZEN) != 0U)
{
/* TZEN option byte should be modified */
assert_param(IS_OB_USER_TZEN(UserConfig2 & FLASH_OPTSR2_TZEN));
/* Set value and mask for TZEN option byte */
optr_reg2_val |= (UserConfig2 & FLASH_OPTSR2_TZEN);
optr_reg2_mask |= FLASH_OPTSR2_TZEN;
}
#endif /* FLASH_OPTSR2_TZEN */
/* Check to write first User OB register or/and second one */
if ((UserType & 0xFFFU) != 0U)
{
/* Configure the option bytes register */
MODIFY_REG(FLASH->OPTSR_PRG, optr_reg1_mask, optr_reg1_val);
}
if ((UserType & 0xFF000U) != 0U)
{
/* Configure the option bytes register */
MODIFY_REG(FLASH->OPTSR2_PRG, optr_reg2_mask, optr_reg2_val);
}
}
/**
* @brief Return the FLASH User Option Byte values.
* @param UserConfig1 FLASH User Option Bytes values
* 2M: IWDG_SW(Bit3), WWDG_SW(Bit4), nRST_STOP(Bit 6), nRST_STDY(Bit 7),
* PRODUCT_STATE(Bit[8:15]), IO_VDD_HSLV(Bit 16), IO_VDDTO2_HSLV(Bit 17),
* IWDG_STOP(Bit 20), IWDG_STDBY (Bit 21), BOOT_UBE(Bit[22:29]) and SWAP_BANK(Bit 31).
* 128K: IWDG_SW(Bit3), WWDG_SW(Bit4), nRST_STOP(Bit 6), nRST_STDY(Bit 7),
* PRODUCT_STATE(Bit[8:15]), IO_VDD_HSLV(Bit16), IO_VDDIO2_HSLV(Bit17), IWDG_STOP(Bit 20),
* IWDG_STDBY (Bit 21) and SWAP_BANK(Bit 31).
* @param UserConfig2 FLASH User Option Bytes values
* 2M: SRAM1_3_RST(Bit2), SRAM2_RST(Bit 3), BKPRAM_ECC(Bit 4), SRAM3_ECC(Bit 5),
* SRAM2_ECC(Bit 6).
* 128K: SRAM2_RST(Bit 3), BKPRAM_ECC(Bit 4), SRAM2_ECC(Bit 6),
* SRAM1_RST(Bit9), SRAM1_ECC(Bit10).
* @retval None
*/
static void FLASH_OB_GetUser(uint32_t *UserConfig1, uint32_t *UserConfig2)
{
(*UserConfig1) = FLASH->OPTSR_CUR & (~FLASH_OPTSR_PRODUCT_STATE);
(*UserConfig2) = FLASH->OPTSR2_CUR;
}
/**
* @brief Configure Boot address
* @param BootOption specifies the Boot address option byte to be programmed.
* This parameter can be one of the following values:
* @arg OB_BOOTADDR_NS: Non-secure boot address
* @arg OB_BOOTADDR_SEC: Secure boot address
* @param BootAddress: specifies the boot address value
* This parameter can be sector number between 0 and 0xFFFFFF00
* @retval None
*/
static void FLASH_OB_BootAddrConfig(uint32_t BootOption, uint32_t BootAddress)
{
/* Check the parameters */
assert_param(IS_OB_BOOT_CONFIG(BootOption));
if (BootOption == OB_BOOT_NS)
{
MODIFY_REG(FLASH->NSBOOTR_PRG, FLASH_BOOTR_BOOTADD, BootAddress);
}
#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
else if (BootOption == OB_BOOT_SEC)
{
MODIFY_REG(FLASH->SECBOOTR_PRG, FLASH_BOOTR_BOOTADD, BootAddress);
}
#endif /* __ARM_FEATURE_CMSE */
else
{
/* Empty statement (to be compliant MISRA 15.7) */
}
}
/**
* @brief Configure the boot lock.
*
* @param BootOption select the BOOT_LOCK option: secure or non-secure.
* This parameter can be one of the following values:
* @arg OB_BOOT_LOCK_SEC: Boot Lock mode deactivated
* @arg OB_BOOT_LOCK_NS: Boot Lock mode activated
*
* @param BootLockConfig specifies the activation of the BOOT_LOCK.
* This parameter can be one of the following values:
* @arg OB_BOOT_LOCK_DISABLE: Boot Lock mode deactivated
* @arg OB_BOOT_LOCK_ENABLE: Boot Lock mode activated
*
* @retval None
*/
static void FLASH_OB_BootLockConfig(uint32_t BootOption, uint32_t BootLockConfig)
{
/* Check the parameters */
assert_param(IS_OB_BOOT_CONFIG(BootOption));
assert_param(IS_OB_BOOT_LOCK(BootLockConfig));
/* Configure the option bytes register */
if (BootOption == OB_BOOT_NS)
{
MODIFY_REG(FLASH->NSBOOTR_PRG, FLASH_BOOTR_BOOT_LOCK, BootLockConfig);
}
#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
else if (BootOption == OB_BOOT_SEC)
{
MODIFY_REG(FLASH->SECBOOTR_PRG, FLASH_BOOTR_BOOT_LOCK, BootLockConfig);
}
#endif /* __ARM_FEATURE_CMSE */
else
{
/* Empty statement (to be compliant MISRA 15.7) */
}
}
/**
* @brief Get the boot configuration
* @param[in] BootOption specifies the boot address option byte to be returned.
* This parameter can be one of the following values:
* @arg OB_BOOT_NS: Non-secure boot address
* @arg OB_BOOT_SEC: Secure boot address
*
* @param[out] BootAddress specifies the boot address value
*
* @param[out] BootLockConfig returns the activation of the BOOT_LOCK.
* This parameter can be one of the following values:
* @arg OB_BOOT_LOCK_DISABLE: Boot Lock mode deactivated
* @arg OB_BOOT_LOCK_ENABLE: Boot Lock mode activated
* @retval None
*/
static void FLASH_OB_GetBootConfig(uint32_t BootOption, uint32_t *BootAddress, uint32_t *BootLockConfig)
{
if (BootOption == OB_BOOT_NS)
{
*BootAddress = FLASH->NSBOOTR_CUR & FLASH_BOOTR_BOOTADD;
*BootLockConfig = FLASH->NSBOOTR_CUR & FLASH_BOOTR_BOOT_LOCK;
}
#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
else if (BootOption == OB_BOOT_SEC)
{
*BootAddress = (FLASH->SECBOOTR_CUR & FLASH_BOOTR_BOOTADD);
*BootLockConfig = (FLASH->SECBOOTR_CUR & FLASH_BOOTR_BOOT_LOCK);
}
#endif /* __ARM_FEATURE_CMSE */
else
{
/* Empty statement (to be compliant MISRA 15.7) */
}
}
/**
* @brief Configure the OTP Block Lock.
* @param OTP_Block specifies the OTP Block to lock.
* This parameter can be a value of @ref FLASH_OTP_Blocks
* @retval None
*/
static void FLASH_OB_OTP_LockConfig(uint32_t OTP_Block)
{
/* Configure the OTP Block lock in the option bytes register */
FLASH->OTPBLR_PRG |= OTP_Block;
}
/**
* @brief Get the OTP Block Lock.
* @retval OTP_Block specifies the OTP Block to lock.
* This return value can be a value of @ref FLASH_OTP_Blocks
*/
static uint32_t FLASH_OB_OTP_GetLock(void)
{
return (FLASH->OTPBLR_CUR);
}
#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
/**
* @brief Configure the watermark-based secure area.
*
* @param Banks specifies the bank where to apply Watermark protection
* This parameter can be one of the following values:
* @arg FLASH_BANK_1: configure Watermark on bank1
* @arg FLASH_BANK_2: configure Watermark on bank2
* @arg FLASH_BANK_BOTH: configure Watermark on both bank1 and bank2
*
* @param WMSecStartSector specifies the start sector of the secure area
* This parameter can be sector number between 0 and (max number of sectors in the bank - 1)
*
* @param WMSecEndSector specifies the end sector of the secure area
* This parameter can be sector number between WMSecStartSector and WMSecEndSector(max number of sectors
* in the bank - 1)
*
* @retval None
*/
static void FLASH_OB_WMSECConfig(uint32_t Banks, uint32_t WMSecStartSector, uint32_t WMSecEndSector)
{
/* Check the parameters */
assert_param(IS_FLASH_BANK(Banks));
assert_param(IS_FLASH_SECTOR(WMSecStartSector));
assert_param(IS_FLASH_SECTOR(WMSecEndSector));
/* Write SECWM registers */
if ((Banks & FLASH_BANK_1) == FLASH_BANK_1)
{
/* Configure Watermark Protection for bank 1 */
FLASH->SECWM1R_PRG = ((WMSecEndSector << FLASH_SECWMR_SECWM_END_Pos) | WMSecStartSector);
}
if ((Banks & FLASH_BANK_2) == FLASH_BANK_2)
{
/* Configure Watermark Protection for bank 2 */
FLASH->SECWM2R_PRG = ((WMSecEndSector << FLASH_SECWMR_SECWM_END_Pos) | WMSecStartSector);
}
}
/**
* @brief Return the watermark-based secure area configuration.
*
* @param Bank [in] specifies the bank where to get the watermark protection.
* This parameter can be exclusively one of the following values:
* @arg FLASH_BANK_1: Get bank1 watermark configuration
* @arg FLASH_BANK_2: Get bank2 watermark configuration
*
* @param WMSecStartSector [out] specifies the start sector of the secure area
*
* @param WMSecEndSector [out] specifies the end sector of the secure area
*
* @retval None
*/
static void FLASH_OB_GetWMSEC(uint32_t Bank, uint32_t *WMSecStartSector, uint32_t *WMSecEndSector)
{
uint32_t regvalue = 0U;
/* Read SECWM register */
if (Bank == FLASH_BANK_1)
{
regvalue = FLASH->SECWM1R_CUR;
}
if (Bank == FLASH_BANK_2)
{
regvalue = FLASH->SECWM2R_CUR;
}
/* Get configuration of secure area */
*WMSecStartSector = (regvalue & FLASH_SECWMR_SECWM_STRT);
*WMSecEndSector = ((regvalue & FLASH_SECWMR_SECWM_END) >> FLASH_SECWMR_SECWM_END_Pos);
}
#endif /* __ARM_FEATURE_CMSE */
/**
* @brief Configure the hide protection area.
*
* @param Banks specifies the bank where to apply hide protection
* This parameter can be one of the following values:
* @arg FLASH_BANK_1: configure HDP on bank1
* @arg FLASH_BANK_2: configure HDP on bank2
* @arg FLASH_BANK_BOTH: configure HDP on both bank1 and bank2
*
* @param HDPStartSector specifies the start sector of the hide protection area
* This parameter can be sector number between 0 and (max number of sectors in the bank - 1)
*
* @param HDPEndSector specifies the end sector of the hide protection area
* This parameter can be sector number between HDPStartSector and HDPEndSector (max number of sectors
* in the bank - 1)
*
* @retval None
*/
static void FLASH_OB_HDPConfig(uint32_t Banks, uint32_t HDPStartSector, uint32_t HDPEndSector)
{
/* Check the parameters */
assert_param(IS_FLASH_BANK(Banks));
assert_param(IS_FLASH_SECTOR(HDPStartSector));
assert_param(IS_FLASH_SECTOR(HDPEndSector));
/* Write HDP registers */
if ((Banks & FLASH_BANK_1) == FLASH_BANK_1)
{
/* Configure hide Protection for bank 1 */
FLASH->HDP1R_PRG = ((HDPEndSector << FLASH_HDPR_HDP_END_Pos) | HDPStartSector);
}
if ((Banks & FLASH_BANK_2) == FLASH_BANK_2)
{
/* Configure hide Protection for bank 2 */
FLASH->HDP2R_PRG = ((HDPEndSector << FLASH_HDPR_HDP_END_Pos) | HDPStartSector);
}
}
/**
* @brief Return the hide protection area configuration.
*
* @param Bank [in] specifies the bank where to get the HDP protection.
* This parameter can be exclusively one of the following values:
* @arg FLASH_BANK_1: Get bank1 HDP configuration
* @arg FLASH_BANK_2: Get bank2 HDP configuration
*
* @param HDPStartSector [out] specifies the start sector of the HDP area
*
* @param HDPEndSector [out] specifies the end sector of the HDP area
*
* @retval None
*/
static void FLASH_OB_GetHDP(uint32_t Bank, uint32_t *HDPStartSector, uint32_t *HDPEndSector)
{
uint32_t regvalue = 0U;
/* Read SECWM register */
if (Bank == FLASH_BANK_1)
{
regvalue = FLASH->HDP1R_CUR;
}
if (Bank == FLASH_BANK_2)
{
regvalue = FLASH->HDP2R_CUR;
}
/* Get configuration of HDP area */
*HDPStartSector = (regvalue & FLASH_HDPR_HDP_STRT);
*HDPEndSector = ((regvalue & FLASH_HDPR_HDP_END) >> FLASH_HDPR_HDP_END_Pos);
}
#if defined(FLASH_EDATAR_EDATA_EN)
/**
* @brief Configure the Flash high-cycle area.
*
* @param Banks specifies the bank where to apply Flash high-cycle data area
* This parameter can be one of the following values:
* @arg FLASH_BANK_1: configure Flash high-cycle area on bank1
* @arg FLASH_BANK_2: configure Flash high-cycle area on bank2
* @arg FLASH_BANK_BOTH: configure Flash high-cycle area on both bank1 and bank2
*
* @param EDATASize specifies the size (in sectors) of the Flash high-cycle data area
* This parameter can be sectors number between 0 and 8
* 0: Disable all EDATA sectors.
* 1: The last sector is reserved for flash high-cycle data.
* 2: The two last sectors are reserved for flash high-cycle data.
* 3: The three last sectors are reserved for flash high-cycle data
* 4: The four last sectors is reserved for flash high-cycle data.
* 5: The five last sectors are reserved for flash high-cycle data.
* 6: The six last sectors are reserved for flash high-cycle data.
* 7: The seven last sectors are reserved for flash high-cycle data.
* 8: The eight last sectors are reserved for flash high-cycle data.
*
* @retval None
*/
static void FLASH_OB_EDATAConfig(uint32_t Banks, uint32_t EDATASize)
{
/* Check the parameters */
assert_param(IS_FLASH_BANK(Banks));
assert_param(IS_FLASH_EDATA_SIZE(EDATASize));
if (EDATASize != 0U)
{
/* Write EDATA registers */
if ((Banks & FLASH_BANK_1) == FLASH_BANK_1)
{
/* Configure Flash high-cycle data for bank 1 */
FLASH->EDATA1R_PRG = (FLASH_EDATAR_EDATA_EN | (EDATASize - 1U));
}
if ((Banks & FLASH_BANK_2) == FLASH_BANK_2)
{
/* Configure Flash high-cycle data for bank 2 */
FLASH->EDATA2R_PRG = (FLASH_EDATAR_EDATA_EN | (EDATASize - 1U));
}
}
else
{
/* Write EDATA registers */
if ((Banks & FLASH_BANK_1) == FLASH_BANK_1)
{
/* Disable Flash high-cycle data for bank 1 */
FLASH->EDATA1R_PRG = 0U;
}
if ((Banks & FLASH_BANK_2) == FLASH_BANK_2)
{
/* Disable Flash high-cycle data for bank 2 */
FLASH->EDATA2R_PRG = 0U;
}
}
}
/**
* @brief Return the Flash high-cycle data area configuration.
*
* @param Bank [in] specifies the bank where to get the Flash high-cycle data configuration.
* This parameter can be exclusively one of the following values:
* @arg FLASH_BANK_1: Get bank1 Flash high-cycle data configuration
* @arg FLASH_BANK_2: Get bank2 Flash high-cycle data configuration
*
* @param EDATASize [out] specifies the size (in sectors) of the Flash high-cycle data area
*
* @retval None
*/
static void FLASH_OB_GetEDATA(uint32_t Bank, uint32_t *EDATASize)
{
uint32_t regvalue = 0U;
/* Read SECWM register */
if (Bank == FLASH_BANK_1)
{
regvalue = FLASH->EDATA1R_CUR;
}
if (Bank == FLASH_BANK_2)
{
regvalue = FLASH->EDATA2R_CUR;
}
/* Get configuration of secure area */
if ((regvalue & FLASH_EDATAR_EDATA_EN) != 0U)
{
/* Encoding of Edata Area size is register value + 1 */
*EDATASize = (regvalue & FLASH_EDATAR_EDATA_STRT) + 1U;
}
else
{
/* No defined Edata area */
*EDATASize = 0U;
}
}
#endif /* FLASH_EDATAR_EDATA_EN */
/**
* @}
*/
/** @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
* @param None
* @retval None
*/
void HAL_FLASHEx_EnableEccCorrectionInterrupt(void)
{
__HAL_FLASH_ENABLE_IT(FLASH_IT_ECCC);
}
/**
* @brief Disable ECC correction interrupt
* @param None
* @retval None
*/
void HAL_FLASHEx_DisableEccCorrectionInterrupt(void)
{
__HAL_FLASH_DISABLE_IT(FLASH_IT_ECCC);
}
/**
* @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)
{
uint32_t correction_reg = FLASH->ECCCORR;
uint32_t detection_reg = FLASH->ECCDETR;
uint32_t data_reg = FLASH->ECCDR;
uint32_t addr_reg = 0xFFFFFFFFU;
/* Check if the operation is a correction or a detection*/
if ((correction_reg & FLASH_ECCR_ECCC) != 0U)
{
/* Get area and offset address values from ECCCORR register*/
pData->Area = correction_reg & (~(FLASH_ECCR_ECCIE | FLASH_ECCR_ADDR_ECC | FLASH_ECCR_ECCC));
addr_reg = (correction_reg & FLASH_ECCR_ADDR_ECC);
}
else if ((detection_reg & FLASH_ECCR_ECCD) != 0U)
{
/* Get area and offset address values from ECCDETR register */
pData->Area = detection_reg & (~(FLASH_ECCR_ADDR_ECC | FLASH_ECCR_ECCD));
addr_reg = (detection_reg & FLASH_ECCR_ADDR_ECC);
}
else
{
/* Do nothing */
}
/* Check that an ECC single or double error has occurred to continue the calculation of area address */
if (addr_reg != 0xFFFFFFFFU)
{
/* Get address value according to area value*/
switch (pData->Area)
{
case FLASH_ECC_AREA_USER_BANK1:
/*
* One error detection/correction or two error detections per 128-bit flash word
* Therefore, the address returned by ECC registers in bank1 represents 128-bit flash word,
* to get the correct address value, we must do a shift by 4 bits
*/
addr_reg = addr_reg << 4U;
pData->Address = FLASH_BASE + addr_reg;
break;
case FLASH_ECC_AREA_USER_BANK2:
/*
* One error detection/correction or two error detections per 128-bit flash word
* Therefore, the address returned by ECC registers in bank2 represents 128-bit flash word,
* to get the correct address value, we must do a shift by 4 bits
*/
addr_reg = addr_reg << 4U;
pData->Address = FLASH_BASE + FLASH_BANK_SIZE + addr_reg;
break;
case FLASH_ECC_AREA_SYSTEM:
/* check system flash bank */
if ((correction_reg & FLASH_ECCR_BK_ECC) == FLASH_ECCR_BK_ECC)
{
pData->Address = FLASH_SYSTEM_BASE + FLASH_SYSTEM_SIZE + addr_reg;
}
else
{
pData->Address = FLASH_SYSTEM_BASE + addr_reg;
}
break;
#if defined (FLASH_SR_OBKERR)
case FLASH_ECC_AREA_OBK:
pData->Address = FLASH_OBK_BASE + addr_reg;
break;
#endif /* FLASH_SR_OBKERR */
#if defined (FLASH_EDATAR_EDATA_EN)
case FLASH_ECC_AREA_EDATA:
/* check flash high-cycle data bank */
if ((correction_reg & FLASH_ECCR_BK_ECC) == FLASH_ECCR_BK_ECC)
{
/*
* addr_reg is the address returned by the ECC register along with an offset value depends on area
* To calculate the exact address set by user while an ECC occurred, we must subtract the offset value,
* In addition, the address returned by ECC registers represents 128-bit flash word (multiply by 4),
*/
pData->Address = FLASH_EDATA_BASE + FLASH_BANK_SIZE + ((addr_reg - FLASH_ADDRESS_OFFSET_EDATA) * 4U);
}
else
{
pData->Address = FLASH_EDATA_BASE + ((addr_reg - FLASH_ADDRESS_OFFSET_EDATA) * 4U);
}
break;
#endif /* FLASH_EDATAR_EDATA_EN */
case FLASH_ECC_AREA_OTP:
/* Address returned by the ECC is an halfword, multiply by 4 to get the exact address*/
pData->Address = FLASH_OTP_BASE + ((addr_reg - FLASH_ADDRESS_OFFSET_OTP) * 4U);
break;
default:
/* Do nothing */
break;
}
}
pData->Data = data_reg & FLASH_ECCR_ADDR_ECC;
}
/**
* @brief Handle Flash ECC Detection interrupt request.
* @retval None
*/
void HAL_FLASHEx_ECCD_IRQHandler(void)
{
/* Check if the ECC double error occurred*/
if (READ_BIT(FLASH->ECCDETR, FLASH_ECCR_ECCD) != 0U)
{
/* FLASH ECC detection user callback */
HAL_FLASHEx_EccDetectionCallback();
/* Clear ECCD flag
note : this step will clear all the information related to the flash ecc detection
*/
SET_BIT(FLASH->ECCDETR, FLASH_ECCR_ECCD);
}
}
/**
* @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
*/
}
/**
* @}
*/
/**
* @}
*/
#endif /* HAL_FLASH_MODULE_ENABLED */
/**
* @}
*/
/**
* @}
*/