]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/CORTEX_MPU_STM32L4_Discovery_GCC_IAR_Keil/ST_Code/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ex.c
Rename STM32Cube to GCC for STM32L4 Discovery projects as GCC is
[freertos] / FreeRTOS / Demo / CORTEX_MPU_STM32L4_Discovery_GCC_IAR_Keil / ST_Code / Drivers / STM32L4xx_HAL_Driver / Src / stm32l4xx_hal_flash_ex.c
diff --git a/FreeRTOS/Demo/CORTEX_MPU_STM32L4_Discovery_GCC_IAR_Keil/ST_Code/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ex.c b/FreeRTOS/Demo/CORTEX_MPU_STM32L4_Discovery_GCC_IAR_Keil/ST_Code/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ex.c
new file mode 100644 (file)
index 0000000..5a30708
--- /dev/null
@@ -0,0 +1,1308 @@
+/**\r
+  ******************************************************************************\r
+  * @file    stm32l4xx_hal_flash_ex.c\r
+  * @author  MCD Application Team\r
+  * @brief   Extended FLASH HAL module driver.\r
+  *          This file provides firmware functions to manage the following\r
+  *          functionalities of the FLASH extended peripheral:\r
+  *           + Extended programming operations functions\r
+  *\r
+ @verbatim\r
+ ==============================================================================\r
+                   ##### Flash Extended features #####\r
+  ==============================================================================\r
+\r
+  [..] Comparing to other previous devices, the FLASH interface for STM32L4xx\r
+       devices contains the following additional features\r
+\r
+       (+) Capacity up to 2 Mbyte with dual bank architecture supporting read-while-write\r
+           capability (RWW)\r
+       (+) Dual bank memory organization\r
+       (+) PCROP protection for all banks\r
+\r
+                        ##### How to use this driver #####\r
+ ==============================================================================\r
+  [..] This driver provides functions to configure and program the FLASH memory\r
+       of all STM32L4xx devices. It includes\r
+      (#) Flash Memory Erase functions:\r
+           (++) Lock and Unlock the FLASH interface using HAL_FLASH_Unlock() and\r
+                HAL_FLASH_Lock() functions\r
+           (++) Erase function: Erase page, erase all sectors\r
+           (++) There are two modes of erase :\r
+             (+++) Polling Mode using HAL_FLASHEx_Erase()\r
+             (+++) Interrupt Mode using HAL_FLASHEx_Erase_IT()\r
+\r
+      (#) Option Bytes Programming function: Use HAL_FLASHEx_OBProgram() to :\r
+        (++) Set/Reset the write protection\r
+        (++) Set the Read protection Level\r
+        (++) Program the user Option Bytes\r
+        (++) Configure the PCROP protection\r
+\r
+      (#) Get Option Bytes Configuration function: Use HAL_FLASHEx_OBGetConfig() to :\r
+        (++) Get the value of a write protection area\r
+        (++) Know if the read protection is activated\r
+        (++) Get the value of the user Option Bytes\r
+        (++) Get the value of a PCROP area\r
+\r
+ @endverbatim\r
+  ******************************************************************************\r
+  * @attention\r
+  *\r
+  * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.\r
+  * All rights reserved.</center></h2>\r
+  *\r
+  * This software component is licensed by ST under BSD 3-Clause license,\r
+  * the "License"; You may not use this file except in compliance with the\r
+  * License. You may obtain a copy of the License at:\r
+  *                       opensource.org/licenses/BSD-3-Clause\r
+  *\r
+  ******************************************************************************\r
+  */\r
+\r
+/* Includes ------------------------------------------------------------------*/\r
+#include "stm32l4xx_hal.h"\r
+\r
+/** @addtogroup STM32L4xx_HAL_Driver\r
+  * @{\r
+  */\r
+\r
+/** @defgroup FLASHEx FLASHEx\r
+  * @brief FLASH Extended HAL module driver\r
+  * @{\r
+  */\r
+\r
+#ifdef HAL_FLASH_MODULE_ENABLED\r
+\r
+/* Private typedef -----------------------------------------------------------*/\r
+/* Private define ------------------------------------------------------------*/\r
+/* Private macro -------------------------------------------------------------*/\r
+/* Private variables ---------------------------------------------------------*/\r
+/* Private function prototypes -----------------------------------------------*/\r
+/** @defgroup FLASHEx_Private_Functions FLASHEx Private Functions\r
+ * @{\r
+ */\r
+static void              FLASH_MassErase(uint32_t Banks);\r
+static HAL_StatusTypeDef FLASH_OB_WRPConfig(uint32_t WRPArea, uint32_t WRPStartOffset, uint32_t WRDPEndOffset);\r
+static HAL_StatusTypeDef FLASH_OB_RDPConfig(uint32_t RDPLevel);\r
+static HAL_StatusTypeDef FLASH_OB_UserConfig(uint32_t UserType, uint32_t UserConfig);\r
+static HAL_StatusTypeDef FLASH_OB_PCROPConfig(uint32_t PCROPConfig, uint32_t PCROPStartAddr, uint32_t PCROPEndAddr);\r
+static void              FLASH_OB_GetWRP(uint32_t WRPArea, uint32_t * WRPStartOffset, uint32_t * WRDPEndOffset);\r
+static uint32_t          FLASH_OB_GetRDP(void);\r
+static uint32_t          FLASH_OB_GetUser(void);\r
+static void              FLASH_OB_GetPCROP(uint32_t * PCROPConfig, uint32_t * PCROPStartAddr, uint32_t * PCROPEndAddr);\r
+/**\r
+  * @}\r
+  */\r
+\r
+/* Exported functions -------------------------------------------------------*/\r
+/** @defgroup FLASHEx_Exported_Functions FLASHEx Exported Functions\r
+  * @{\r
+  */\r
+\r
+/** @defgroup FLASHEx_Exported_Functions_Group1 Extended IO operation functions\r
+ *  @brief   Extended IO operation functions\r
+ *\r
+@verbatim\r
+ ===============================================================================\r
+                ##### Extended programming operation functions #####\r
+ ===============================================================================\r
+    [..]\r
+    This subsection provides a set of functions allowing to manage the Extended FLASH\r
+    programming operations Operations.\r
+\r
+@endverbatim\r
+  * @{\r
+  */\r
+/**\r
+  * @brief  Perform a mass erase or erase the specified FLASH memory pages.\r
+  * @param[in]  pEraseInit: pointer to an FLASH_EraseInitTypeDef structure that\r
+  *         contains the configuration information for the erasing.\r
+  *\r
+  * @param[out]  PageError  : pointer to variable that contains the configuration\r
+  *         information on faulty page in case of error (0xFFFFFFFF means that all\r
+  *         the pages have been correctly erased)\r
+  *\r
+  * @retval HAL Status\r
+  */\r
+HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *PageError)\r
+{\r
+  HAL_StatusTypeDef status;\r
+  uint32_t page_index;\r
+\r
+  /* Process Locked */\r
+  __HAL_LOCK(&pFlash);\r
+\r
+  /* Check the parameters */\r
+  assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase));\r
+\r
+  /* Wait for last operation to be completed */\r
+  status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);\r
+\r
+  if (status == HAL_OK)\r
+  {\r
+    pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;\r
+\r
+    /* Deactivate the cache if they are activated to avoid data misbehavior */\r
+    if(READ_BIT(FLASH->ACR, FLASH_ACR_ICEN) != 0U)\r
+    {\r
+      /* Disable instruction cache  */\r
+      __HAL_FLASH_INSTRUCTION_CACHE_DISABLE();\r
+\r
+      if(READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != 0U)\r
+      {\r
+        /* Disable data cache  */\r
+        __HAL_FLASH_DATA_CACHE_DISABLE();\r
+        pFlash.CacheToReactivate = FLASH_CACHE_ICACHE_DCACHE_ENABLED;\r
+      }\r
+      else\r
+      {\r
+        pFlash.CacheToReactivate = FLASH_CACHE_ICACHE_ENABLED;\r
+      }\r
+    }\r
+    else if(READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != 0U)\r
+    {\r
+      /* Disable data cache  */\r
+      __HAL_FLASH_DATA_CACHE_DISABLE();\r
+      pFlash.CacheToReactivate = FLASH_CACHE_DCACHE_ENABLED;\r
+    }\r
+    else\r
+    {\r
+      pFlash.CacheToReactivate = FLASH_CACHE_DISABLED;\r
+    }\r
+\r
+    if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE)\r
+    {\r
+      /* Mass erase to be done */\r
+      FLASH_MassErase(pEraseInit->Banks);\r
+\r
+      /* Wait for last operation to be completed */\r
+      status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);\r
+\r
+#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \\r
+    defined (STM32L496xx) || defined (STM32L4A6xx) || \\r
+    defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)\r
+      /* If the erase operation is completed, disable the MER1 and MER2 Bits */\r
+      CLEAR_BIT(FLASH->CR, (FLASH_CR_MER1 | FLASH_CR_MER2));\r
+#else\r
+      /* If the erase operation is completed, disable the MER1 Bit */\r
+      CLEAR_BIT(FLASH->CR, (FLASH_CR_MER1));\r
+#endif\r
+    }\r
+    else\r
+    {\r
+      /*Initialization of PageError variable*/\r
+      *PageError = 0xFFFFFFFFU;\r
+\r
+      for(page_index = pEraseInit->Page; page_index < (pEraseInit->Page + pEraseInit->NbPages); page_index++)\r
+      {\r
+        FLASH_PageErase(page_index, pEraseInit->Banks);\r
+\r
+        /* Wait for last operation to be completed */\r
+        status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);\r
+\r
+        /* If the erase operation is completed, disable the PER Bit */\r
+        CLEAR_BIT(FLASH->CR, (FLASH_CR_PER | FLASH_CR_PNB));\r
+\r
+        if (status != HAL_OK)\r
+        {\r
+          /* In case of error, stop erase procedure and return the faulty address */\r
+          *PageError = page_index;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+\r
+    /* Flush the caches to be sure of the data consistency */\r
+    FLASH_FlushCaches();\r
+  }\r
+\r
+  /* Process Unlocked */\r
+  __HAL_UNLOCK(&pFlash);\r
+\r
+  return status;\r
+}\r
+\r
+/**\r
+  * @brief  Perform a mass erase or erase the specified FLASH memory pages with interrupt enabled.\r
+  * @param  pEraseInit: pointer to an FLASH_EraseInitTypeDef structure that\r
+  *         contains the configuration information for the erasing.\r
+  *\r
+  * @retval HAL Status\r
+  */\r
+HAL_StatusTypeDef HAL_FLASHEx_Erase_IT(FLASH_EraseInitTypeDef *pEraseInit)\r
+{\r
+  HAL_StatusTypeDef status = HAL_OK;\r
+\r
+  /* Process Locked */\r
+  __HAL_LOCK(&pFlash);\r
+\r
+  /* Check the parameters */\r
+  assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase));\r
+\r
+  pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;\r
+\r
+  /* Deactivate the cache if they are activated to avoid data misbehavior */\r
+  if(READ_BIT(FLASH->ACR, FLASH_ACR_ICEN) != 0U)\r
+  {\r
+    /* Disable instruction cache  */\r
+    __HAL_FLASH_INSTRUCTION_CACHE_DISABLE();\r
+\r
+    if(READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != 0U)\r
+    {\r
+      /* Disable data cache  */\r
+      __HAL_FLASH_DATA_CACHE_DISABLE();\r
+      pFlash.CacheToReactivate = FLASH_CACHE_ICACHE_DCACHE_ENABLED;\r
+    }\r
+    else\r
+    {\r
+      pFlash.CacheToReactivate = FLASH_CACHE_ICACHE_ENABLED;\r
+    }\r
+  }\r
+  else if(READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != 0U)\r
+  {\r
+    /* Disable data cache  */\r
+    __HAL_FLASH_DATA_CACHE_DISABLE();\r
+    pFlash.CacheToReactivate = FLASH_CACHE_DCACHE_ENABLED;\r
+  }\r
+  else\r
+  {\r
+    pFlash.CacheToReactivate = FLASH_CACHE_DISABLED;\r
+  }\r
+\r
+  /* Enable End of Operation and Error interrupts */\r
+  __HAL_FLASH_ENABLE_IT(FLASH_IT_EOP | FLASH_IT_OPERR);\r
+\r
+  pFlash.Bank = pEraseInit->Banks;\r
+\r
+  if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE)\r
+  {\r
+    /* Mass erase to be done */\r
+    pFlash.ProcedureOnGoing = FLASH_PROC_MASS_ERASE;\r
+    FLASH_MassErase(pEraseInit->Banks);\r
+  }\r
+  else\r
+  {\r
+    /* Erase by page to be done */\r
+    pFlash.ProcedureOnGoing = FLASH_PROC_PAGE_ERASE;\r
+    pFlash.NbPagesToErase = pEraseInit->NbPages;\r
+    pFlash.Page = pEraseInit->Page;\r
+\r
+    /*Erase 1st page and wait for IT */\r
+    FLASH_PageErase(pEraseInit->Page, pEraseInit->Banks);\r
+  }\r
+\r
+  return status;\r
+}\r
+\r
+/**\r
+  * @brief  Program Option bytes.\r
+  * @param  pOBInit: pointer to an FLASH_OBInitStruct structure that\r
+  *         contains the configuration information for the programming.\r
+  *\r
+  * @retval HAL Status\r
+  */\r
+HAL_StatusTypeDef HAL_FLASHEx_OBProgram(FLASH_OBProgramInitTypeDef *pOBInit)\r
+{\r
+  HAL_StatusTypeDef status = HAL_OK;\r
+\r
+  /* Process Locked */\r
+  __HAL_LOCK(&pFlash);\r
+\r
+  /* Check the parameters */\r
+  assert_param(IS_OPTIONBYTE(pOBInit->OptionType));\r
+\r
+  pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;\r
+\r
+  /* Write protection configuration */\r
+  if((pOBInit->OptionType & OPTIONBYTE_WRP) != 0U)\r
+  {\r
+    /* Configure of Write protection on the selected area */\r
+    if(FLASH_OB_WRPConfig(pOBInit->WRPArea, pOBInit->WRPStartOffset, pOBInit->WRPEndOffset) != HAL_OK)\r
+    {\r
+      status = HAL_ERROR;\r
+    }\r
+\r
+  }\r
+\r
+  /* Read protection configuration */\r
+  if((pOBInit->OptionType & OPTIONBYTE_RDP) != 0U)\r
+  {\r
+    /* Configure the Read protection level */\r
+    if(FLASH_OB_RDPConfig(pOBInit->RDPLevel) != HAL_OK)\r
+    {\r
+      status = HAL_ERROR;\r
+    }\r
+  }\r
+\r
+  /* User Configuration */\r
+  if((pOBInit->OptionType & OPTIONBYTE_USER) != 0U)\r
+  {\r
+    /* Configure the user option bytes */\r
+    if(FLASH_OB_UserConfig(pOBInit->USERType, pOBInit->USERConfig) != HAL_OK)\r
+    {\r
+      status = HAL_ERROR;\r
+    }\r
+  }\r
+\r
+  /* PCROP Configuration */\r
+  if((pOBInit->OptionType & OPTIONBYTE_PCROP) != 0U)\r
+  {\r
+    if (pOBInit->PCROPStartAddr != pOBInit->PCROPEndAddr)\r
+    {\r
+      /* Configure the Proprietary code readout protection */\r
+      if(FLASH_OB_PCROPConfig(pOBInit->PCROPConfig, pOBInit->PCROPStartAddr, pOBInit->PCROPEndAddr) != HAL_OK)\r
+      {\r
+        status = HAL_ERROR;\r
+      }\r
+    }\r
+  }\r
+\r
+  /* Process Unlocked */\r
+  __HAL_UNLOCK(&pFlash);\r
+\r
+  return status;\r
+}\r
+\r
+/**\r
+  * @brief  Get the Option bytes configuration.\r
+  * @param  pOBInit: pointer to an FLASH_OBInitStruct structure that contains the\r
+  *                  configuration information.\r
+  * @note   The fields pOBInit->WRPArea and pOBInit->PCROPConfig should indicate\r
+  *         which area is requested for the WRP and PCROP, else no information will be returned\r
+  *\r
+  * @retval None\r
+  */\r
+void HAL_FLASHEx_OBGetConfig(FLASH_OBProgramInitTypeDef *pOBInit)\r
+{\r
+  pOBInit->OptionType = (OPTIONBYTE_RDP | OPTIONBYTE_USER);\r
+\r
+#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \\r
+    defined (STM32L496xx) || defined (STM32L4A6xx) || \\r
+    defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)\r
+  if((pOBInit->WRPArea == OB_WRPAREA_BANK1_AREAA) || (pOBInit->WRPArea == OB_WRPAREA_BANK1_AREAB) ||\r
+     (pOBInit->WRPArea == OB_WRPAREA_BANK2_AREAA) || (pOBInit->WRPArea == OB_WRPAREA_BANK2_AREAB))\r
+#else\r
+  if((pOBInit->WRPArea == OB_WRPAREA_BANK1_AREAA) || (pOBInit->WRPArea == OB_WRPAREA_BANK1_AREAB))\r
+#endif\r
+  {\r
+    pOBInit->OptionType |= OPTIONBYTE_WRP;\r
+    /* Get write protection on the selected area */\r
+    FLASH_OB_GetWRP(pOBInit->WRPArea, &(pOBInit->WRPStartOffset), &(pOBInit->WRPEndOffset));\r
+  }\r
+\r
+  /* Get Read protection level */\r
+  pOBInit->RDPLevel = FLASH_OB_GetRDP();\r
+\r
+  /* Get the user option bytes */\r
+  pOBInit->USERConfig = FLASH_OB_GetUser();\r
+\r
+#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \\r
+    defined (STM32L496xx) || defined (STM32L4A6xx) || \\r
+    defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)\r
+  if((pOBInit->PCROPConfig == FLASH_BANK_1) || (pOBInit->PCROPConfig == FLASH_BANK_2))\r
+#else\r
+  if(pOBInit->PCROPConfig == FLASH_BANK_1)\r
+#endif\r
+  {\r
+    pOBInit->OptionType |= OPTIONBYTE_PCROP;\r
+    /* Get the Proprietary code readout protection */\r
+    FLASH_OB_GetPCROP(&(pOBInit->PCROPConfig), &(pOBInit->PCROPStartAddr), &(pOBInit->PCROPEndAddr));\r
+  }\r
+}\r
+\r
+/**\r
+  * @}\r
+  */\r
+\r
+#if defined (FLASH_CFGR_LVEN)\r
+/** @defgroup FLASHEx_Exported_Functions_Group2 Extended specific configuration functions\r
+ *  @brief   Extended specific configuration functions\r
+ *\r
+@verbatim\r
+ ===============================================================================\r
+                ##### Extended specific configuration functions #####\r
+ ===============================================================================\r
+    [..]\r
+    This subsection provides a set of functions allowing to manage the Extended FLASH\r
+    specific configurations.\r
+\r
+@endverbatim\r
+  * @{\r
+  */\r
+\r
+/**\r
+  * @brief  Configuration of the LVE pin of the Flash (managed by power controller\r
+  *         or forced to low in order to use an external SMPS)\r
+  * @param  ConfigLVE: Configuration of the LVE pin,\r
+  *              This parameter can be one of the following values:\r
+  *                @arg FLASH_LVE_PIN_CTRL: LVE FLASH pin controlled by power controller\r
+  *                @arg FLASH_LVE_PIN_FORCED: LVE FLASH pin enforced to low (external SMPS used)\r
+  *\r
+  * @note   Before enforcing the LVE pin to low, the SOC should be in low voltage\r
+  *         range 2 and the voltage VDD12 should be higher than 1.08V and SMPS is ON.\r
+  *\r
+  * @retval HAL Status\r
+  */\r
+HAL_StatusTypeDef HAL_FLASHEx_ConfigLVEPin(uint32_t ConfigLVE)\r
+{\r
+  HAL_StatusTypeDef status;\r
+\r
+  /* Process Locked */\r
+  __HAL_LOCK(&pFlash);\r
+\r
+  /* Check the parameters */\r
+  assert_param(IS_FLASH_LVE_PIN(ConfigLVE));\r
+\r
+  /* Wait for last operation to be completed */\r
+  status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);\r
+\r
+  if (status == HAL_OK)\r
+  {\r
+    /* Check that the voltage scaling is range 2 */\r
+    if (HAL_PWREx_GetVoltageRange() == PWR_REGULATOR_VOLTAGE_SCALE2)\r
+    {\r
+      /* Configure the LVEN bit */\r
+      MODIFY_REG(FLASH->CFGR, FLASH_CFGR_LVEN, ConfigLVE);\r
+\r
+      /* Check that the bit has been correctly configured */\r
+      if (READ_BIT(FLASH->CFGR, FLASH_CFGR_LVEN) != ConfigLVE)\r
+      {\r
+        status = HAL_ERROR;\r
+      }\r
+    }\r
+    else\r
+    {\r
+      /* Not allow to force Flash LVE pin if not in voltage range 2 */\r
+      status = HAL_ERROR;\r
+    }\r
+  }\r
+\r
+  /* Process Unlocked */\r
+  __HAL_UNLOCK(&pFlash);\r
+\r
+  return status;\r
+}\r
+\r
+/**\r
+  * @}\r
+  */\r
+#endif /* FLASH_CFGR_LVEN */\r
+\r
+/**\r
+  * @}\r
+  */\r
+\r
+/* Private functions ---------------------------------------------------------*/\r
+\r
+/** @addtogroup FLASHEx_Private_Functions\r
+  * @{\r
+  */\r
+/**\r
+  * @brief  Mass erase of FLASH memory.\r
+  * @param  Banks: Banks to be erased\r
+  *          This parameter can be one of the following values:\r
+  *            @arg FLASH_BANK_1: Bank1 to be erased\r
+  *            @arg FLASH_BANK_2: Bank2 to be erased\r
+  *            @arg FLASH_BANK_BOTH: Bank1 and Bank2 to be erased\r
+  * @retval None\r
+  */\r
+static void FLASH_MassErase(uint32_t Banks)\r
+{\r
+#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)\r
+  if (READ_BIT(FLASH->OPTR, FLASH_OPTR_DBANK) != 0U)\r
+#endif\r
+  {\r
+    /* Check the parameters */\r
+    assert_param(IS_FLASH_BANK(Banks));\r
+\r
+    /* Set the Mass Erase Bit for the bank 1 if requested */\r
+    if((Banks & FLASH_BANK_1) != 0U)\r
+    {\r
+      SET_BIT(FLASH->CR, FLASH_CR_MER1);\r
+    }\r
+\r
+#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \\r
+    defined (STM32L496xx) || defined (STM32L4A6xx) || \\r
+    defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)\r
+    /* Set the Mass Erase Bit for the bank 2 if requested */\r
+    if((Banks & FLASH_BANK_2) != 0U)\r
+    {\r
+      SET_BIT(FLASH->CR, FLASH_CR_MER2);\r
+    }\r
+#endif\r
+  }\r
+#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)\r
+  else\r
+  {\r
+    SET_BIT(FLASH->CR, (FLASH_CR_MER1 | FLASH_CR_MER2));\r
+  }\r
+#endif\r
+\r
+  /* Proceed to erase all sectors */\r
+  SET_BIT(FLASH->CR, FLASH_CR_STRT);\r
+}\r
+\r
+/**\r
+  * @brief  Erase the specified FLASH memory page.\r
+  * @param  Page: FLASH page to erase\r
+  *         This parameter must be a value between 0 and (max number of pages in the bank - 1)\r
+  * @param  Banks: Bank(s) where the page will be erased\r
+  *          This parameter can be one of the following values:\r
+  *            @arg FLASH_BANK_1: Page in bank 1 to be erased\r
+  *            @arg FLASH_BANK_2: Page in bank 2 to be erased\r
+  * @retval None\r
+  */\r
+void FLASH_PageErase(uint32_t Page, uint32_t Banks)\r
+{\r
+  /* Check the parameters */\r
+  assert_param(IS_FLASH_PAGE(Page));\r
+\r
+#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \\r
+    defined (STM32L496xx) || defined (STM32L4A6xx) || \\r
+    defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)\r
+#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)\r
+  if(READ_BIT(FLASH->OPTR, FLASH_OPTR_DBANK) == 0U)\r
+  {\r
+    CLEAR_BIT(FLASH->CR, FLASH_CR_BKER);\r
+  }\r
+  else\r
+#endif\r
+  {\r
+    assert_param(IS_FLASH_BANK_EXCLUSIVE(Banks));\r
+\r
+    if((Banks & FLASH_BANK_1) != 0U)\r
+    {\r
+      CLEAR_BIT(FLASH->CR, FLASH_CR_BKER);\r
+    }\r
+    else\r
+    {\r
+      SET_BIT(FLASH->CR, FLASH_CR_BKER);\r
+    }\r
+  }\r
+#else\r
+  /* Prevent unused argument(s) compilation warning */\r
+  UNUSED(Banks);\r
+#endif\r
+\r
+  /* Proceed to erase the page */\r
+  MODIFY_REG(FLASH->CR, FLASH_CR_PNB, ((Page & 0xFFU) << FLASH_CR_PNB_Pos));\r
+  SET_BIT(FLASH->CR, FLASH_CR_PER);\r
+  SET_BIT(FLASH->CR, FLASH_CR_STRT);\r
+}\r
+\r
+/**\r
+  * @brief  Flush the instruction and data caches.\r
+  * @retval None\r
+  */\r
+void FLASH_FlushCaches(void)\r
+{\r
+  FLASH_CacheTypeDef cache = pFlash.CacheToReactivate;\r
+\r
+  /* Flush instruction cache  */\r
+  if((cache == FLASH_CACHE_ICACHE_ENABLED) ||\r
+     (cache == FLASH_CACHE_ICACHE_DCACHE_ENABLED))\r
+  {\r
+    /* Reset instruction cache */\r
+    __HAL_FLASH_INSTRUCTION_CACHE_RESET();\r
+    /* Enable instruction cache */\r
+    __HAL_FLASH_INSTRUCTION_CACHE_ENABLE();\r
+  }\r
+\r
+  /* Flush data cache */\r
+  if((cache == FLASH_CACHE_DCACHE_ENABLED) ||\r
+     (cache == FLASH_CACHE_ICACHE_DCACHE_ENABLED))\r
+  {\r
+    /* Reset data cache */\r
+    __HAL_FLASH_DATA_CACHE_RESET();\r
+    /* Enable data cache */\r
+    __HAL_FLASH_DATA_CACHE_ENABLE();\r
+  }\r
+\r
+  /* Reset internal variable */\r
+  pFlash.CacheToReactivate = FLASH_CACHE_DISABLED;\r
+}\r
+\r
+/**\r
+  * @brief  Configure the write protection of the desired pages.\r
+  *\r
+  * @note   When the memory read protection level is selected (RDP level = 1),\r
+  *         it is not possible to program or erase Flash memory if the CPU debug\r
+  *         features are connected (JTAG or single wire) or boot code is being\r
+  *         executed from RAM or System flash, even if WRP is not activated.\r
+  * @note   To configure the WRP options, the option lock bit OPTLOCK must be\r
+  *         cleared with the call of the HAL_FLASH_OB_Unlock() function.\r
+  * @note   To validate the WRP options, the option bytes must be reloaded\r
+  *         through the call of the HAL_FLASH_OB_Launch() function.\r
+  *\r
+  * @param  WRPArea: specifies the area to be configured.\r
+  *          This parameter can be one of the following values:\r
+  *            @arg OB_WRPAREA_BANK1_AREAA: Flash Bank 1 Area A\r
+  *            @arg OB_WRPAREA_BANK1_AREAB: Flash Bank 1 Area B\r
+  *            @arg OB_WRPAREA_BANK2_AREAA: Flash Bank 2 Area A  (don't apply for STM32L43x/STM32L44x devices)\r
+  *            @arg OB_WRPAREA_BANK2_AREAB: Flash Bank 2 Area B  (don't apply for STM32L43x/STM32L44x devices)\r
+  *\r
+  * @param  WRPStartOffset: specifies the start page of the write protected area\r
+  *          This parameter can be page number between 0 and (max number of pages in the bank - 1)\r
+  *\r
+  * @param  WRDPEndOffset: specifies the end page of the write protected area\r
+  *          This parameter can be page number between WRPStartOffset and (max number of pages in the bank - 1)\r
+  *\r
+  * @retval HAL Status\r
+  */\r
+static HAL_StatusTypeDef FLASH_OB_WRPConfig(uint32_t WRPArea, uint32_t WRPStartOffset, uint32_t WRDPEndOffset)\r
+{\r
+  HAL_StatusTypeDef status;\r
+\r
+  /* Check the parameters */\r
+  assert_param(IS_OB_WRPAREA(WRPArea));\r
+  assert_param(IS_FLASH_PAGE(WRPStartOffset));\r
+  assert_param(IS_FLASH_PAGE(WRDPEndOffset));\r
+\r
+  /* Wait for last operation to be completed */\r
+  status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);\r
+\r
+  if(status == HAL_OK)\r
+  {\r
+    /* Configure the write protected area */\r
+    if(WRPArea == OB_WRPAREA_BANK1_AREAA)\r
+    {\r
+      MODIFY_REG(FLASH->WRP1AR, (FLASH_WRP1AR_WRP1A_STRT | FLASH_WRP1AR_WRP1A_END),\r
+                 (WRPStartOffset | (WRDPEndOffset << 16)));\r
+    }\r
+    else if(WRPArea == OB_WRPAREA_BANK1_AREAB)\r
+    {\r
+      MODIFY_REG(FLASH->WRP1BR, (FLASH_WRP1BR_WRP1B_STRT | FLASH_WRP1BR_WRP1B_END),\r
+                 (WRPStartOffset | (WRDPEndOffset << 16)));\r
+    }\r
+#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \\r
+    defined (STM32L496xx) || defined (STM32L4A6xx) || \\r
+    defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)\r
+    else if(WRPArea == OB_WRPAREA_BANK2_AREAA)\r
+    {\r
+      MODIFY_REG(FLASH->WRP2AR, (FLASH_WRP2AR_WRP2A_STRT | FLASH_WRP2AR_WRP2A_END),\r
+                 (WRPStartOffset | (WRDPEndOffset << 16)));\r
+    }\r
+    else if(WRPArea == OB_WRPAREA_BANK2_AREAB)\r
+    {\r
+      MODIFY_REG(FLASH->WRP2BR, (FLASH_WRP2BR_WRP2B_STRT | FLASH_WRP2BR_WRP2B_END),\r
+                 (WRPStartOffset | (WRDPEndOffset << 16)));\r
+    }\r
+#endif\r
+    else\r
+    {\r
+      /* Nothing to do */\r
+    }\r
+\r
+    /* Set OPTSTRT Bit */\r
+    SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);\r
+\r
+    /* Wait for last operation to be completed */\r
+    status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);\r
+\r
+    /* If the option byte program operation is completed, disable the OPTSTRT Bit */\r
+    CLEAR_BIT(FLASH->CR, FLASH_CR_OPTSTRT);\r
+  }\r
+\r
+  return status;\r
+}\r
+\r
+/**\r
+  * @brief  Set the read protection level.\r
+  *\r
+  * @note   To configure the RDP level, the option lock bit OPTLOCK must be\r
+  *         cleared with the call of the HAL_FLASH_OB_Unlock() function.\r
+  * @note   To validate the RDP level, the option bytes must be reloaded\r
+  *         through the call of the HAL_FLASH_OB_Launch() function.\r
+  * @note   !!! Warning : When enabling OB_RDP level 2 it's no more possible\r
+  *         to go back to level 1 or 0 !!!\r
+  *\r
+  * @param  RDPLevel: specifies the read protection level.\r
+  *         This parameter can be one of the following values:\r
+  *            @arg OB_RDP_LEVEL_0: No protection\r
+  *            @arg OB_RDP_LEVEL_1: Read protection of the memory\r
+  *            @arg OB_RDP_LEVEL_2: Full chip protection\r
+  *\r
+  * @retval HAL status\r
+  */\r
+static HAL_StatusTypeDef FLASH_OB_RDPConfig(uint32_t RDPLevel)\r
+{\r
+  HAL_StatusTypeDef status;\r
+\r
+  /* Check the parameters */\r
+  assert_param(IS_OB_RDP_LEVEL(RDPLevel));\r
+\r
+  /* Wait for last operation to be completed */\r
+  status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);\r
+\r
+  if(status == HAL_OK)\r
+  {\r
+    /* Configure the RDP level in the option bytes register */\r
+    MODIFY_REG(FLASH->OPTR, FLASH_OPTR_RDP, RDPLevel);\r
+\r
+    /* Set OPTSTRT Bit */\r
+    SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);\r
+\r
+    /* Wait for last operation to be completed */\r
+    status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);\r
+\r
+    /* If the option byte program operation is completed, disable the OPTSTRT Bit */\r
+    CLEAR_BIT(FLASH->CR, FLASH_CR_OPTSTRT);\r
+  }\r
+\r
+  return status;\r
+}\r
+\r
+/**\r
+  * @brief  Program the FLASH User Option Byte.\r
+  *\r
+  * @note   To configure the user option bytes, the option lock bit OPTLOCK must\r
+  *         be cleared with the call of the HAL_FLASH_OB_Unlock() function.\r
+  * @note   To validate the user option bytes, the option bytes must be reloaded\r
+  *         through the call of the HAL_FLASH_OB_Launch() function.\r
+  *\r
+  * @param  UserType: The FLASH User Option Bytes to be modified\r
+  * @param  UserConfig: The FLASH User Option Bytes values:\r
+  *         BOR_LEV(Bit8-10), nRST_STOP(Bit12), nRST_STDBY(Bit13), IWDG_SW(Bit16),\r
+  *         IWDG_STOP(Bit17), IWDG_STDBY(Bit18), WWDG_SW(Bit19), BFB2(Bit20),\r
+  *         DUALBANK(Bit21), nBOOT1(Bit23), SRAM2_PE(Bit24) and SRAM2_RST(Bit25).\r
+  *\r
+  * @retval HAL status\r
+  */\r
+static HAL_StatusTypeDef FLASH_OB_UserConfig(uint32_t UserType, uint32_t UserConfig)\r
+{\r
+  uint32_t optr_reg_val = 0;\r
+  uint32_t optr_reg_mask = 0;\r
+  HAL_StatusTypeDef status;\r
+\r
+  /* Check the parameters */\r
+  assert_param(IS_OB_USER_TYPE(UserType));\r
+\r
+  /* Wait for last operation to be completed */\r
+  status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);\r
+\r
+  if(status == HAL_OK)\r
+  {\r
+    if((UserType & OB_USER_BOR_LEV) != 0U)\r
+    {\r
+      /* BOR level option byte should be modified */\r
+      assert_param(IS_OB_USER_BOR_LEVEL(UserConfig & FLASH_OPTR_BOR_LEV));\r
+\r
+      /* Set value and mask for BOR level option byte */\r
+      optr_reg_val |= (UserConfig & FLASH_OPTR_BOR_LEV);\r
+      optr_reg_mask |= FLASH_OPTR_BOR_LEV;\r
+    }\r
+\r
+    if((UserType & OB_USER_nRST_STOP) != 0U)\r
+    {\r
+      /* nRST_STOP option byte should be modified */\r
+      assert_param(IS_OB_USER_STOP(UserConfig & FLASH_OPTR_nRST_STOP));\r
+\r
+      /* Set value and mask for nRST_STOP option byte */\r
+      optr_reg_val |= (UserConfig & FLASH_OPTR_nRST_STOP);\r
+      optr_reg_mask |= FLASH_OPTR_nRST_STOP;\r
+    }\r
+\r
+    if((UserType & OB_USER_nRST_STDBY) != 0U)\r
+    {\r
+      /* nRST_STDBY option byte should be modified */\r
+      assert_param(IS_OB_USER_STANDBY(UserConfig & FLASH_OPTR_nRST_STDBY));\r
+\r
+      /* Set value and mask for nRST_STDBY option byte */\r
+      optr_reg_val |= (UserConfig & FLASH_OPTR_nRST_STDBY);\r
+      optr_reg_mask |= FLASH_OPTR_nRST_STDBY;\r
+    }\r
+\r
+    if((UserType & OB_USER_nRST_SHDW) != 0U)\r
+    {\r
+      /* nRST_SHDW option byte should be modified */\r
+      assert_param(IS_OB_USER_SHUTDOWN(UserConfig & FLASH_OPTR_nRST_SHDW));\r
+\r
+      /* Set value and mask for nRST_SHDW option byte */\r
+      optr_reg_val |= (UserConfig & FLASH_OPTR_nRST_SHDW);\r
+      optr_reg_mask |= FLASH_OPTR_nRST_SHDW;\r
+    }\r
+\r
+    if((UserType & OB_USER_IWDG_SW) != 0U)\r
+    {\r
+      /* IWDG_SW option byte should be modified */\r
+      assert_param(IS_OB_USER_IWDG(UserConfig & FLASH_OPTR_IWDG_SW));\r
+\r
+      /* Set value and mask for IWDG_SW option byte */\r
+      optr_reg_val |= (UserConfig & FLASH_OPTR_IWDG_SW);\r
+      optr_reg_mask |= FLASH_OPTR_IWDG_SW;\r
+    }\r
+\r
+    if((UserType & OB_USER_IWDG_STOP) != 0U)\r
+    {\r
+      /* IWDG_STOP option byte should be modified */\r
+      assert_param(IS_OB_USER_IWDG_STOP(UserConfig & FLASH_OPTR_IWDG_STOP));\r
+\r
+      /* Set value and mask for IWDG_STOP option byte */\r
+      optr_reg_val |= (UserConfig & FLASH_OPTR_IWDG_STOP);\r
+      optr_reg_mask |= FLASH_OPTR_IWDG_STOP;\r
+    }\r
+\r
+    if((UserType & OB_USER_IWDG_STDBY) != 0U)\r
+    {\r
+      /* IWDG_STDBY option byte should be modified */\r
+      assert_param(IS_OB_USER_IWDG_STDBY(UserConfig & FLASH_OPTR_IWDG_STDBY));\r
+\r
+      /* Set value and mask for IWDG_STDBY option byte */\r
+      optr_reg_val |= (UserConfig & FLASH_OPTR_IWDG_STDBY);\r
+      optr_reg_mask |= FLASH_OPTR_IWDG_STDBY;\r
+    }\r
+\r
+    if((UserType & OB_USER_WWDG_SW) != 0U)\r
+    {\r
+      /* WWDG_SW option byte should be modified */\r
+      assert_param(IS_OB_USER_WWDG(UserConfig & FLASH_OPTR_WWDG_SW));\r
+\r
+      /* Set value and mask for WWDG_SW option byte */\r
+      optr_reg_val |= (UserConfig & FLASH_OPTR_WWDG_SW);\r
+      optr_reg_mask |= FLASH_OPTR_WWDG_SW;\r
+    }\r
+\r
+#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \\r
+    defined (STM32L496xx) || defined (STM32L4A6xx) || \\r
+    defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)\r
+    if((UserType & OB_USER_BFB2) != 0U)\r
+    {\r
+      /* BFB2 option byte should be modified */\r
+      assert_param(IS_OB_USER_BFB2(UserConfig & FLASH_OPTR_BFB2));\r
+\r
+      /* Set value and mask for BFB2 option byte */\r
+      optr_reg_val |= (UserConfig & FLASH_OPTR_BFB2);\r
+      optr_reg_mask |= FLASH_OPTR_BFB2;\r
+    }\r
+\r
+    if((UserType & OB_USER_DUALBANK) != 0U)\r
+    {\r
+#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)\r
+      /* DUALBANK option byte should be modified */\r
+      assert_param(IS_OB_USER_DUALBANK(UserConfig & FLASH_OPTR_DB1M));\r
+\r
+      /* Set value and mask for DUALBANK option byte */\r
+      optr_reg_val |= (UserConfig & FLASH_OPTR_DB1M);\r
+      optr_reg_mask |= FLASH_OPTR_DB1M;\r
+#else\r
+      /* DUALBANK option byte should be modified */\r
+      assert_param(IS_OB_USER_DUALBANK(UserConfig & FLASH_OPTR_DUALBANK));\r
+\r
+      /* Set value and mask for DUALBANK option byte */\r
+      optr_reg_val |= (UserConfig & FLASH_OPTR_DUALBANK);\r
+      optr_reg_mask |= FLASH_OPTR_DUALBANK;\r
+#endif\r
+    }\r
+#endif\r
+\r
+    if((UserType & OB_USER_nBOOT1) != 0U)\r
+    {\r
+      /* nBOOT1 option byte should be modified */\r
+      assert_param(IS_OB_USER_BOOT1(UserConfig & FLASH_OPTR_nBOOT1));\r
+\r
+      /* Set value and mask for nBOOT1 option byte */\r
+      optr_reg_val |= (UserConfig & FLASH_OPTR_nBOOT1);\r
+      optr_reg_mask |= FLASH_OPTR_nBOOT1;\r
+    }\r
+\r
+    if((UserType & OB_USER_SRAM2_PE) != 0U)\r
+    {\r
+      /* SRAM2_PE option byte should be modified */\r
+      assert_param(IS_OB_USER_SRAM2_PARITY(UserConfig & FLASH_OPTR_SRAM2_PE));\r
+\r
+      /* Set value and mask for SRAM2_PE option byte */\r
+      optr_reg_val |= (UserConfig & FLASH_OPTR_SRAM2_PE);\r
+      optr_reg_mask |= FLASH_OPTR_SRAM2_PE;\r
+    }\r
+\r
+    if((UserType & OB_USER_SRAM2_RST) != 0U)\r
+    {\r
+      /* SRAM2_RST option byte should be modified */\r
+      assert_param(IS_OB_USER_SRAM2_RST(UserConfig & FLASH_OPTR_SRAM2_RST));\r
+\r
+      /* Set value and mask for SRAM2_RST option byte */\r
+      optr_reg_val |= (UserConfig & FLASH_OPTR_SRAM2_RST);\r
+      optr_reg_mask |= FLASH_OPTR_SRAM2_RST;\r
+    }\r
+\r
+#if defined (STM32L412xx) || defined (STM32L422xx) || defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || \\r
+    defined (STM32L442xx) || defined (STM32L443xx) || defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || \\r
+    defined (STM32L496xx) || defined (STM32L4A6xx) || \\r
+    defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)\r
+    if((UserType & OB_USER_nSWBOOT0) != 0U)\r
+    {\r
+      /* nSWBOOT0 option byte should be modified */\r
+      assert_param(IS_OB_USER_SWBOOT0(UserConfig & FLASH_OPTR_nSWBOOT0));\r
+\r
+      /* Set value and mask for nSWBOOT0 option byte */\r
+      optr_reg_val |= (UserConfig & FLASH_OPTR_nSWBOOT0);\r
+      optr_reg_mask |= FLASH_OPTR_nSWBOOT0;\r
+    }\r
+\r
+    if((UserType & OB_USER_nBOOT0) != 0U)\r
+    {\r
+      /* nBOOT0 option byte should be modified */\r
+      assert_param(IS_OB_USER_BOOT0(UserConfig & FLASH_OPTR_nBOOT0));\r
+\r
+      /* Set value and mask for nBOOT0 option byte */\r
+      optr_reg_val |= (UserConfig & FLASH_OPTR_nBOOT0);\r
+      optr_reg_mask |= FLASH_OPTR_nBOOT0;\r
+    }\r
+#endif\r
+\r
+    /* Configure the option bytes register */\r
+    MODIFY_REG(FLASH->OPTR, optr_reg_mask, optr_reg_val);\r
+\r
+    /* Set OPTSTRT Bit */\r
+    SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);\r
+\r
+    /* Wait for last operation to be completed */\r
+    status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);\r
+\r
+    /* If the option byte program operation is completed, disable the OPTSTRT Bit */\r
+    CLEAR_BIT(FLASH->CR, FLASH_CR_OPTSTRT);\r
+  }\r
+\r
+  return status;\r
+}\r
+\r
+/**\r
+  * @brief  Configure the Proprietary code readout protection of the desired addresses.\r
+  *\r
+  * @note   To configure the PCROP options, the option lock bit OPTLOCK must be\r
+  *         cleared with the call of the HAL_FLASH_OB_Unlock() function.\r
+  * @note   To validate the PCROP options, the option bytes must be reloaded\r
+  *         through the call of the HAL_FLASH_OB_Launch() function.\r
+  *\r
+  * @param  PCROPConfig: specifies the configuration (Bank to be configured and PCROP_RDP option).\r
+  *          This parameter must be a combination of FLASH_BANK_1 or FLASH_BANK_2\r
+  *          with OB_PCROP_RDP_NOT_ERASE or OB_PCROP_RDP_ERASE\r
+  *\r
+  * @param  PCROPStartAddr: specifies the start address of the Proprietary code readout protection\r
+  *          This parameter can be an address between begin and end of the bank\r
+  *\r
+  * @param  PCROPEndAddr: specifies the end address of the Proprietary code readout protection\r
+  *          This parameter can be an address between PCROPStartAddr and end of the bank\r
+  *\r
+  * @retval HAL Status\r
+  */\r
+static HAL_StatusTypeDef FLASH_OB_PCROPConfig(uint32_t PCROPConfig, uint32_t PCROPStartAddr, uint32_t PCROPEndAddr)\r
+{\r
+  HAL_StatusTypeDef status;\r
+  uint32_t reg_value;\r
+  uint32_t bank1_addr;\r
+#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \\r
+    defined (STM32L496xx) || defined (STM32L4A6xx) || \\r
+    defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)\r
+  uint32_t bank2_addr;\r
+#endif\r
+\r
+  /* Check the parameters */\r
+  assert_param(IS_FLASH_BANK_EXCLUSIVE(PCROPConfig & FLASH_BANK_BOTH));\r
+  assert_param(IS_OB_PCROP_RDP(PCROPConfig & FLASH_PCROP1ER_PCROP_RDP));\r
+  assert_param(IS_FLASH_MAIN_MEM_ADDRESS(PCROPStartAddr));\r
+  assert_param(IS_FLASH_MAIN_MEM_ADDRESS(PCROPEndAddr));\r
+\r
+  /* Wait for last operation to be completed */\r
+  status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);\r
+\r
+  if(status == HAL_OK)\r
+  {\r
+#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \\r
+    defined (STM32L496xx) || defined (STM32L4A6xx) || \\r
+    defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)\r
+    /* Get the information about the bank swapping */\r
+    if (READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_FB_MODE) == 0U)\r
+    {\r
+      bank1_addr = FLASH_BASE;\r
+      bank2_addr = FLASH_BASE + FLASH_BANK_SIZE;\r
+    }\r
+    else\r
+    {\r
+      bank1_addr = FLASH_BASE + FLASH_BANK_SIZE;\r
+      bank2_addr = FLASH_BASE;\r
+    }\r
+#else\r
+    bank1_addr = FLASH_BASE;\r
+#endif\r
+\r
+#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)\r
+    if (READ_BIT(FLASH->OPTR, FLASH_OPTR_DBANK) == 0U)\r
+    {\r
+      /* Configure the Proprietary code readout protection */\r
+      if((PCROPConfig & FLASH_BANK_BOTH) == FLASH_BANK_1)\r
+      {\r
+        reg_value = ((PCROPStartAddr - FLASH_BASE) >> 4);\r
+        MODIFY_REG(FLASH->PCROP1SR, FLASH_PCROP1SR_PCROP1_STRT, reg_value);\r
+\r
+        reg_value = ((PCROPEndAddr - FLASH_BASE) >> 4);\r
+        MODIFY_REG(FLASH->PCROP1ER, FLASH_PCROP1ER_PCROP1_END, reg_value);\r
+      }\r
+      else if((PCROPConfig & FLASH_BANK_BOTH) == FLASH_BANK_2)\r
+      {\r
+        reg_value = ((PCROPStartAddr - FLASH_BASE) >> 4);\r
+        MODIFY_REG(FLASH->PCROP2SR, FLASH_PCROP2SR_PCROP2_STRT, reg_value);\r
+\r
+        reg_value = ((PCROPEndAddr - FLASH_BASE) >> 4);\r
+        MODIFY_REG(FLASH->PCROP2ER, FLASH_PCROP2ER_PCROP2_END, reg_value);\r
+      }\r
+      else\r
+      {\r
+        /* Nothing to do */\r
+      }\r
+    }\r
+    else\r
+#endif\r
+    {\r
+      /* Configure the Proprietary code readout protection */\r
+      if((PCROPConfig & FLASH_BANK_BOTH) == FLASH_BANK_1)\r
+      {\r
+        reg_value = ((PCROPStartAddr - bank1_addr) >> 3);\r
+        MODIFY_REG(FLASH->PCROP1SR, FLASH_PCROP1SR_PCROP1_STRT, reg_value);\r
+\r
+        reg_value = ((PCROPEndAddr - bank1_addr) >> 3);\r
+        MODIFY_REG(FLASH->PCROP1ER, FLASH_PCROP1ER_PCROP1_END, reg_value);\r
+      }\r
+#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \\r
+    defined (STM32L496xx) || defined (STM32L4A6xx) || \\r
+    defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)\r
+      else if((PCROPConfig & FLASH_BANK_BOTH) == FLASH_BANK_2)\r
+      {\r
+        reg_value = ((PCROPStartAddr - bank2_addr) >> 3);\r
+        MODIFY_REG(FLASH->PCROP2SR, FLASH_PCROP2SR_PCROP2_STRT, reg_value);\r
+\r
+        reg_value = ((PCROPEndAddr - bank2_addr) >> 3);\r
+        MODIFY_REG(FLASH->PCROP2ER, FLASH_PCROP2ER_PCROP2_END, reg_value);\r
+      }\r
+#endif\r
+      else\r
+      {\r
+        /* Nothing to do */\r
+      }\r
+    }\r
+\r
+    MODIFY_REG(FLASH->PCROP1ER, FLASH_PCROP1ER_PCROP_RDP, (PCROPConfig & FLASH_PCROP1ER_PCROP_RDP));\r
+\r
+    /* Set OPTSTRT Bit */\r
+    SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);\r
+\r
+    /* Wait for last operation to be completed */\r
+    status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);\r
+\r
+    /* If the option byte program operation is completed, disable the OPTSTRT Bit */\r
+    CLEAR_BIT(FLASH->CR, FLASH_CR_OPTSTRT);\r
+  }\r
+\r
+  return status;\r
+}\r
+\r
+/**\r
+  * @brief  Return the FLASH Write Protection Option Bytes value.\r
+  *\r
+  * @param[in]  WRPArea: specifies the area to be returned.\r
+  *          This parameter can be one of the following values:\r
+  *            @arg OB_WRPAREA_BANK1_AREAA: Flash Bank 1 Area A\r
+  *            @arg OB_WRPAREA_BANK1_AREAB: Flash Bank 1 Area B\r
+  *            @arg OB_WRPAREA_BANK2_AREAA: Flash Bank 2 Area A (don't apply to STM32L43x/STM32L44x devices)\r
+  *            @arg OB_WRPAREA_BANK2_AREAB: Flash Bank 2 Area B (don't apply to STM32L43x/STM32L44x devices)\r
+  *\r
+  * @param[out]  WRPStartOffset: specifies the address where to copied the start page\r
+  *                         of the write protected area\r
+  *\r
+  * @param[out]  WRDPEndOffset: specifies the address where to copied the end page of\r
+  *                        the write protected area\r
+  *\r
+  * @retval None\r
+  */\r
+static void FLASH_OB_GetWRP(uint32_t WRPArea, uint32_t * WRPStartOffset, uint32_t * WRDPEndOffset)\r
+{\r
+  /* Get the configuration of the write protected area */\r
+  if(WRPArea == OB_WRPAREA_BANK1_AREAA)\r
+  {\r
+    *WRPStartOffset = READ_BIT(FLASH->WRP1AR, FLASH_WRP1AR_WRP1A_STRT);\r
+    *WRDPEndOffset = (READ_BIT(FLASH->WRP1AR, FLASH_WRP1AR_WRP1A_END) >> 16);\r
+  }\r
+  else if(WRPArea == OB_WRPAREA_BANK1_AREAB)\r
+  {\r
+    *WRPStartOffset = READ_BIT(FLASH->WRP1BR, FLASH_WRP1BR_WRP1B_STRT);\r
+    *WRDPEndOffset = (READ_BIT(FLASH->WRP1BR, FLASH_WRP1BR_WRP1B_END) >> 16);\r
+  }\r
+#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \\r
+    defined (STM32L496xx) || defined (STM32L4A6xx) || \\r
+    defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)\r
+  else if(WRPArea == OB_WRPAREA_BANK2_AREAA)\r
+  {\r
+    *WRPStartOffset = READ_BIT(FLASH->WRP2AR, FLASH_WRP2AR_WRP2A_STRT);\r
+    *WRDPEndOffset = (READ_BIT(FLASH->WRP2AR, FLASH_WRP2AR_WRP2A_END) >> 16);\r
+  }\r
+  else if(WRPArea == OB_WRPAREA_BANK2_AREAB)\r
+  {\r
+    *WRPStartOffset = READ_BIT(FLASH->WRP2BR, FLASH_WRP2BR_WRP2B_STRT);\r
+    *WRDPEndOffset = (READ_BIT(FLASH->WRP2BR, FLASH_WRP2BR_WRP2B_END) >> 16);\r
+  }\r
+#endif\r
+  else\r
+  {\r
+    /* Nothing to do */\r
+  }\r
+}\r
+\r
+/**\r
+  * @brief  Return the FLASH Read Protection level.\r
+  * @retval FLASH ReadOut Protection Status:\r
+  *         This return value can be one of the following values:\r
+  *            @arg OB_RDP_LEVEL_0: No protection\r
+  *            @arg OB_RDP_LEVEL_1: Read protection of the memory\r
+  *            @arg OB_RDP_LEVEL_2: Full chip protection\r
+  */\r
+static uint32_t FLASH_OB_GetRDP(void)\r
+{\r
+  uint32_t rdp_level = READ_BIT(FLASH->OPTR, FLASH_OPTR_RDP);\r
+\r
+  if ((rdp_level != OB_RDP_LEVEL_0) && (rdp_level != OB_RDP_LEVEL_2))\r
+  {\r
+    return (OB_RDP_LEVEL_1);\r
+  }\r
+  else\r
+  {\r
+    return (READ_BIT(FLASH->OPTR, FLASH_OPTR_RDP));\r
+  }\r
+}\r
+\r
+/**\r
+  * @brief  Return the FLASH User Option Byte value.\r
+  * @retval The FLASH User Option Bytes values:\r
+  *      For STM32L47x/STM32L48x devices :\r
+  *         BOR_LEV(Bit8-10), nRST_STOP(Bit12), nRST_STDBY(Bit13), nRST_SHDW(Bit14),\r
+  *         IWDG_SW(Bit16), IWDG_STOP(Bit17), IWDG_STDBY(Bit18), WWDG_SW(Bit19),\r
+  *         BFB2(Bit20), DUALBANK(Bit21), nBOOT1(Bit23), SRAM2_PE(Bit24) and SRAM2_RST(Bit25).\r
+  *      For STM32L43x/STM32L44x devices :\r
+  *         BOR_LEV(Bit8-10), nRST_STOP(Bit12), nRST_STDBY(Bit13), nRST_SHDW(Bit14),\r
+  *         IWDG_SW(Bit16), IWDG_STOP(Bit17), IWDG_STDBY(Bit18), WWDG_SW(Bit19),\r
+  *         nBOOT1(Bit23), SRAM2_PE(Bit24), SRAM2_RST(Bit25), nSWBOOT0(Bit26) and nBOOT0(Bit27).\r
+  */\r
+static uint32_t FLASH_OB_GetUser(void)\r
+{\r
+  uint32_t user_config = READ_REG(FLASH->OPTR);\r
+  CLEAR_BIT(user_config, FLASH_OPTR_RDP);\r
+\r
+  return user_config;\r
+}\r
+\r
+/**\r
+  * @brief  Return the FLASH Write Protection Option Bytes value.\r
+  *\r
+  * @param PCROPConfig [inout]: specifies the configuration (Bank to be configured and PCROP_RDP option).\r
+  *          This parameter must be a combination of FLASH_BANK_1 or FLASH_BANK_2\r
+  *          with OB_PCROP_RDP_NOT_ERASE or OB_PCROP_RDP_ERASE\r
+  *\r
+  * @param PCROPStartAddr [out]: specifies the address where to copied the start address\r
+  *                         of the Proprietary code readout protection\r
+  *\r
+  * @param PCROPEndAddr [out]: specifies the address where to copied the end address of\r
+  *                       the Proprietary code readout protection\r
+  *\r
+  * @retval None\r
+  */\r
+static void FLASH_OB_GetPCROP(uint32_t * PCROPConfig, uint32_t * PCROPStartAddr, uint32_t * PCROPEndAddr)\r
+{\r
+  uint32_t reg_value;\r
+  uint32_t bank1_addr;\r
+#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \\r
+    defined (STM32L496xx) || defined (STM32L4A6xx) || \\r
+    defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)\r
+  uint32_t bank2_addr;\r
+#endif\r
+\r
+#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \\r
+    defined (STM32L496xx) || defined (STM32L4A6xx) || \\r
+    defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)\r
+  /* Get the information about the bank swapping */\r
+  if (READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_FB_MODE) == 0U)\r
+  {\r
+    bank1_addr = FLASH_BASE;\r
+    bank2_addr = FLASH_BASE + FLASH_BANK_SIZE;\r
+  }\r
+  else\r
+  {\r
+    bank1_addr = FLASH_BASE + FLASH_BANK_SIZE;\r
+    bank2_addr = FLASH_BASE;\r
+  }\r
+#else\r
+  bank1_addr = FLASH_BASE;\r
+#endif\r
+\r
+#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)\r
+  if (READ_BIT(FLASH->OPTR, FLASH_OPTR_DBANK) == 0U)\r
+  {\r
+    if(((*PCROPConfig) & FLASH_BANK_BOTH) == FLASH_BANK_1)\r
+    {\r
+      reg_value       = (READ_REG(FLASH->PCROP1SR) & FLASH_PCROP1SR_PCROP1_STRT);\r
+      *PCROPStartAddr = (reg_value << 4) + FLASH_BASE;\r
+\r
+      reg_value     = (READ_REG(FLASH->PCROP1ER) & FLASH_PCROP1ER_PCROP1_END);\r
+      *PCROPEndAddr = (reg_value << 4) + FLASH_BASE + 0xFU;\r
+    }\r
+    else if(((*PCROPConfig) & FLASH_BANK_BOTH) == FLASH_BANK_2)\r
+    {\r
+      reg_value       = (READ_REG(FLASH->PCROP2SR) & FLASH_PCROP2SR_PCROP2_STRT);\r
+      *PCROPStartAddr = (reg_value << 4) + FLASH_BASE;\r
+\r
+      reg_value     = (READ_REG(FLASH->PCROP2ER) & FLASH_PCROP2ER_PCROP2_END);\r
+      *PCROPEndAddr = (reg_value << 4) + FLASH_BASE + 0xFU;;\r
+    }\r
+    else\r
+    {\r
+      /* Nothing to do */\r
+    }\r
+  }\r
+  else\r
+#endif\r
+  {\r
+    if(((*PCROPConfig) & FLASH_BANK_BOTH) == FLASH_BANK_1)\r
+    {\r
+      reg_value       = (READ_REG(FLASH->PCROP1SR) & FLASH_PCROP1SR_PCROP1_STRT);\r
+      *PCROPStartAddr = (reg_value << 3) + bank1_addr;\r
+\r
+      reg_value     = (READ_REG(FLASH->PCROP1ER) & FLASH_PCROP1ER_PCROP1_END);\r
+      *PCROPEndAddr = (reg_value << 3) + bank1_addr + 0x7U;\r
+    }\r
+#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \\r
+    defined (STM32L496xx) || defined (STM32L4A6xx) || \\r
+    defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)\r
+    else if(((*PCROPConfig) & FLASH_BANK_BOTH) == FLASH_BANK_2)\r
+    {\r
+      reg_value       = (READ_REG(FLASH->PCROP2SR) & FLASH_PCROP2SR_PCROP2_STRT);\r
+      *PCROPStartAddr = (reg_value << 3) + bank2_addr;\r
+\r
+      reg_value     = (READ_REG(FLASH->PCROP2ER) & FLASH_PCROP2ER_PCROP2_END);\r
+      *PCROPEndAddr = (reg_value << 3) + bank2_addr + 0x7U;\r
+    }\r
+#endif\r
+    else\r
+    {\r
+      /* Nothing to do */\r
+    }\r
+  }\r
+\r
+  *PCROPConfig |= (READ_REG(FLASH->PCROP1ER) & FLASH_PCROP1ER_PCROP_RDP);\r
+}\r
+/**\r
+  * @}\r
+  */\r
+\r
+/**\r
+  * @}\r
+  */\r
+\r
+#endif /* HAL_FLASH_MODULE_ENABLED */\r
+\r
+/**\r
+  * @}\r
+  */\r
+\r
+/**\r
+  * @}\r
+  */\r
+\r
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/\r