generated from Template/H563ZI-HAL-CMake-Template
2048 lines
67 KiB
C
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 */
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
/**
|
|
* @}
|
|
*/
|