| /** |
| ****************************************************************************** |
| * @file stm32l5xx_hal_flash.c |
| * @author MCD Application Team |
| * @brief FLASH HAL module driver. |
| * This file provides firmware functions to manage the following |
| * functionalities of the internal FLASH memory: |
| * + Program operations functions |
| * + Memory Control functions |
| * + Peripheral Errors functions |
| * |
| ****************************************************************************** |
| * @attention |
| * |
| * Copyright (c) 2019 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 peripheral features ##### |
| ============================================================================== |
| |
| [..] The Flash memory interface manages CPU AHB C-Bus accesses |
| to the Flash memory. It implements the erase and program Flash memory operations |
| and the read and write protection mechanisms. |
| |
| [..] The Flash memory interface implements the TrustZone security features (TZ) supported |
| by ARM Cortex-M33 core (CM33). |
| |
| [..] The FLASH main features are: |
| (+) Flash memory read operations |
| (+) Flash memory program/erase operations |
| (+) Read / write protections |
| (+) Option bytes programming |
| (+) TrustZone aware |
| (+) Watermark-based area protection including secure hide area |
| (+) Block-based page protection |
| (+) Error code correction (ECC) : Data in flash are 72-bits word |
| (8 bits added per double word) |
| |
| ##### How to use this driver ##### |
| ============================================================================== |
| [..] |
| This driver provides functions and macros to configure and program the FLASH |
| memory of all STM32L5xx devices. |
| |
| (#) Flash Memory IO Programming functions: |
| (++) Lock and Unlock the FLASH interface using HAL_FLASH_Unlock() and |
| HAL_FLASH_Lock() functions |
| (++) Program functions: double word |
| (++) There Two modes of programming : |
| (+++) Polling mode using HAL_FLASH_Program() function |
| (+++) Interrupt mode using HAL_FLASH_Program_IT() function |
| |
| (#) Interrupts and flags management functions : |
| (++) Handle FLASH interrupts by calling HAL_FLASH_IRQHandler() |
| (++) Callback functions are called when the flash operations are finished : |
| HAL_FLASH_EndOfOperationCallback() when everything is ok, otherwise |
| HAL_FLASH_OperationErrorCallback() |
| (++) Get error flag status by calling HAL_GetError() |
| |
| (#) Option bytes management functions : |
| (++) Lock and Unlock the option bytes using HAL_FLASH_OB_Unlock() and |
| HAL_FLASH_OB_Lock() functions |
| (++) Launch the reload of the option bytes using HAL_FLASH_Launch() function. |
| In this case, a reset is generated |
| |
| [..] |
| In addition to these functions, this driver includes a set of macros allowing |
| to handle the following operations: |
| (+) Set the latency |
| (+) Enable/Disable the Flash power-down during low-power run and sleep modes |
| (+) Enable/Disable the Flash interrupts |
| (+) Monitor the Flash flags status |
| |
| @endverbatim |
| ****************************************************************************** |
| */ |
| |
| /* Includes ------------------------------------------------------------------*/ |
| #include "stm32l5xx_hal.h" |
| |
| /** @addtogroup STM32L5xx_HAL_Driver |
| * @{ |
| */ |
| |
| /** @defgroup FLASH FLASH |
| * @brief FLASH HAL module driver |
| * @{ |
| */ |
| |
| #ifdef HAL_FLASH_MODULE_ENABLED |
| |
| /* Private typedef -----------------------------------------------------------*/ |
| /* Private defines -----------------------------------------------------------*/ |
| /* Private macros ------------------------------------------------------------*/ |
| /* Private variables ---------------------------------------------------------*/ |
| /** @defgroup FLASH_Private_Variables FLASH Private Variables |
| * @{ |
| */ |
| /** |
| * @brief Variable used for Program/Erase sectors under interruption |
| */ |
| FLASH_ProcessTypeDef pFlash = {.Lock = HAL_UNLOCKED, \ |
| .ErrorCode = HAL_FLASH_ERROR_NONE, \ |
| .ProcedureOnGoing = 0U, \ |
| .Address = 0U, \ |
| .Bank = FLASH_BANK_1, \ |
| .Page = 0U, \ |
| .NbPagesToErase = 0U}; |
| /** |
| * @} |
| */ |
| |
| /* Private function prototypes -----------------------------------------------*/ |
| /** @defgroup FLASH_Private_Functions FLASH Private Functions |
| * @{ |
| */ |
| static void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data); |
| /** |
| * @} |
| */ |
| |
| /* Exported functions --------------------------------------------------------*/ |
| /** @defgroup FLASH_Exported_Functions FLASH Exported Functions |
| * @{ |
| */ |
| |
| /** @defgroup FLASH_Exported_Functions_Group1 Programming Operation functions |
| * @brief Programming Operation functions |
| * |
| @verbatim |
| =============================================================================== |
| ##### Programming Operation functions ##### |
| =============================================================================== |
| [..] |
| This subsection provides a set of functions allowing to manage the FLASH |
| program operations. |
| |
| @endverbatim |
| * @{ |
| */ |
| |
| /** |
| * @brief Program double word at a specified address. |
| * @param TypeProgram Indicate the way to program at a specified address. |
| * This parameter can be a value of @ref FLASH_Type_Program |
| * @param Address specifies the address to be programmed. |
| * @param Data specifies the data to be programmed |
| * This parameter is the data for the double word program |
| * |
| * @retval HAL_StatusTypeDef HAL Status |
| */ |
| HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data) |
| { |
| HAL_StatusTypeDef status; |
| __IO uint32_t *reg; |
| |
| /* Check the parameters */ |
| assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram)); |
| |
| /* 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) |
| { |
| pFlash.ProcedureOnGoing = TypeProgram; |
| reg = IS_FLASH_SECURE_OPERATION() ? &(FLASH->SECCR) : &(FLASH_NS->NSCR); |
| |
| /* Program double-word (64-bit) at a specified address */ |
| FLASH_Program_DoubleWord(Address, Data); |
| |
| /* Wait for last operation to be completed */ |
| status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE); |
| |
| /* If the program operation is completed, disable the PG Bit */ |
| CLEAR_BIT((*reg), (pFlash.ProcedureOnGoing & ~(FLASH_NON_SECURE_MASK))); |
| } |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(&pFlash); |
| |
| return status; |
| } |
| |
| /** |
| * @brief Program double word at a specified address with interrupt enabled. |
| * @param TypeProgram Indicate the way to program at a specified address. |
| * This parameter can be a value of @ref FLASH_Type_Program |
| * @param Address specifies the address to be programmed. |
| * @param Data specifies the data to be programmed |
| * This parameter is the data for the double word program |
| * |
| * @retval HAL Status |
| */ |
| HAL_StatusTypeDef HAL_FLASH_Program_IT(uint32_t TypeProgram, uint32_t Address, uint64_t Data) |
| { |
| HAL_StatusTypeDef status; |
| __IO uint32_t *reg_cr; |
| |
| /* Check the parameters */ |
| assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram)); |
| |
| /* Process Locked */ |
| __HAL_LOCK(&pFlash); |
| |
| /* Reset error code */ |
| pFlash.ErrorCode = HAL_FLASH_ERROR_NONE; |
| |
| /* Wait for last operation to be completed */ |
| status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE); |
| |
| if (status != HAL_OK) |
| { |
| /* Process Unlocked */ |
| __HAL_UNLOCK(&pFlash); |
| } |
| else |
| { |
| /* Set internal variables used by the IRQ handler */ |
| pFlash.ProcedureOnGoing = TypeProgram; |
| pFlash.Address = Address; |
| |
| /* Access to SECCR or NSCR depends on operation type */ |
| reg_cr = IS_FLASH_SECURE_OPERATION() ? &(FLASH->SECCR) : &(FLASH_NS->NSCR); |
| |
| /* Enable End of Operation and Error interrupts */ |
| (*reg_cr) |= (FLASH_IT_EOP | FLASH_IT_OPERR); |
| |
| /* Program double-word (64-bit) at a specified address */ |
| FLASH_Program_DoubleWord(Address, Data); |
| } |
| |
| return status; |
| } |
| |
| /** |
| * @brief Handle FLASH interrupt request. |
| * @retval None |
| */ |
| void HAL_FLASH_IRQHandler(void) |
| { |
| uint32_t param = 0U; |
| uint32_t error, type; |
| __IO uint32_t *reg; |
| __IO uint32_t *reg_sr; |
| |
| type = (pFlash.ProcedureOnGoing & ~(FLASH_NON_SECURE_MASK)); |
| reg = IS_FLASH_SECURE_OPERATION() ? &(FLASH->SECCR) : &(FLASH_NS->NSCR); |
| reg_sr = IS_FLASH_SECURE_OPERATION() ? &(FLASH->SECSR) : &(FLASH_NS->NSSR); |
| |
| /* Save Flash errors */ |
| error = (*reg_sr) & FLASH_FLAG_SR_ERRORS; |
| #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) |
| error |= (FLASH->NSSR & FLASH_FLAG_OPTWERR); |
| #endif /* __ARM_FEATURE_CMSE */ |
| |
| /* Set parameter of the callback */ |
| if(type == FLASH_TYPEERASE_PAGES) |
| { |
| param = pFlash.Page; |
| } |
| else if(type == FLASH_TYPEERASE_MASSERASE) |
| { |
| param = pFlash.Bank; |
| } |
| else if(type == FLASH_TYPEPROGRAM_DOUBLEWORD) |
| { |
| param = pFlash.Address; |
| } |
| else |
| { |
| /* Empty statement (to be compliant MISRA 15.7) */ |
| } |
| |
| /* Clear bit on the on-going procedure */ |
| CLEAR_BIT((*reg), type); |
| |
| /* Check FLASH operation error flags */ |
| if(error != 0U) |
| { |
| /* Save the error code */ |
| pFlash.ErrorCode |= error; |
| |
| /* Clear error programming flags */ |
| (*reg_sr) = error; |
| #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) |
| if ((error & FLASH_FLAG_OPTWERR) != 0U) |
| { |
| FLASH->NSSR = FLASH_FLAG_OPTWERR; |
| } |
| #endif /* __ARM_FEATURE_CMSE */ |
| |
| /* Stop the procedure ongoing */ |
| pFlash.ProcedureOnGoing = 0U; |
| |
| /* FLASH error interrupt user callback */ |
| HAL_FLASH_OperationErrorCallback(param); |
| } |
| |
| /* Check FLASH End of Operation flag */ |
| if (((*reg_sr) & FLASH_FLAG_EOP) != 0U) |
| { |
| /* Clear FLASH End of Operation pending bit */ |
| (*reg_sr) = FLASH_FLAG_EOP; |
| |
| if(type == FLASH_TYPEERASE_PAGES) |
| { |
| /* Nb of pages to erased can be decreased */ |
| pFlash.NbPagesToErase--; |
| |
| /* Check if there are still pages to erase*/ |
| if(pFlash.NbPagesToErase != 0U) |
| { |
| /* Increment page number */ |
| pFlash.Page++; |
| FLASH_PageErase(pFlash.Page, pFlash.Bank); |
| } |
| else |
| { |
| /* No more pages to Erase */ |
| pFlash.ProcedureOnGoing = 0U; |
| param = 0xFFFFFFFFU; |
| } |
| } |
| else |
| { |
| /*Clear the procedure ongoing*/ |
| pFlash.ProcedureOnGoing = 0U; |
| } |
| |
| /* FLASH EOP interrupt user callback */ |
| HAL_FLASH_EndOfOperationCallback(param); |
| } |
| |
| if(pFlash.ProcedureOnGoing == 0U) |
| { |
| /* Disable End of Operation and Error interrupts */ |
| (*reg) &= ~(FLASH_IT_EOP | FLASH_IT_OPERR); |
| |
| /* Process Unlocked */ |
| __HAL_UNLOCK(&pFlash); |
| } |
| } |
| |
| /** |
| * @brief FLASH end of operation interrupt callback. |
| * @param ReturnValue The value saved in this parameter depends on the ongoing procedure : |
| * @arg Mass Erase: Bank number which has been requested to erase |
| * @arg Page Erase: Page which has been erased |
| * (if 0xFFFFFFFF, it means that all the selected pages have been erased) |
| * @arg Program: Address which was selected for data program |
| * @retval None |
| */ |
| __weak void HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue) |
| { |
| /* Prevent unused argument(s) compilation warning */ |
| UNUSED(ReturnValue); |
| |
| /* NOTE : This function should not be modified, when the callback is needed, |
| the HAL_FLASH_EndOfOperationCallback could be implemented in the user file |
| */ |
| } |
| |
| /** |
| * @brief FLASH operation error interrupt callback. |
| * @param ReturnValue The value saved in this parameter depends on the ongoing procedure : |
| * @arg Mass Erase: Bank number which has been requested to erase |
| * @arg Page Erase: Page number which returned an error |
| * @arg Program: Address which was selected for data program |
| * @retval None |
| */ |
| __weak void HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue) |
| { |
| /* Prevent unused argument(s) compilation warning */ |
| UNUSED(ReturnValue); |
| |
| /* NOTE : This function should not be modified, when the callback is needed, |
| the HAL_FLASH_OperationErrorCallback could be implemented in the user file |
| */ |
| } |
| |
| /** |
| * @} |
| */ |
| |
| /** @defgroup FLASH_Exported_Functions_Group2 Peripheral Control functions |
| * @brief Management functions |
| * |
| @verbatim |
| =============================================================================== |
| ##### Peripheral Control functions ##### |
| =============================================================================== |
| [..] |
| This subsection provides a set of functions allowing to control the FLASH |
| memory operations. |
| |
| @endverbatim |
| * @{ |
| */ |
| |
| /** |
| * @brief Unlock the FLASH control register access. |
| * @retval HAL Status |
| */ |
| HAL_StatusTypeDef HAL_FLASH_Unlock(void) |
| { |
| HAL_StatusTypeDef status = HAL_OK; |
| |
| if(READ_BIT(FLASH->NSCR, FLASH_NSCR_NSLOCK) != 0u) |
| { |
| /* Authorize the FLASH Registers access */ |
| WRITE_REG(FLASH->NSKEYR, FLASH_KEY1); |
| WRITE_REG(FLASH->NSKEYR, FLASH_KEY2); |
| |
| /* verify Flash is unlocked */ |
| if (READ_BIT(FLASH->NSCR, FLASH_NSCR_NSLOCK) != 0u) |
| { |
| status = HAL_ERROR; |
| } |
| } |
| |
| #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) |
| if (status == HAL_OK) |
| { |
| if(READ_BIT(FLASH->SECCR, FLASH_SECCR_SECLOCK) != 0u) |
| { |
| /* Authorize the FLASH Registers access */ |
| WRITE_REG(FLASH->SECKEYR, FLASH_KEY1); |
| WRITE_REG(FLASH->SECKEYR, FLASH_KEY2); |
| |
| /* verify Flash is unlocked */ |
| if (READ_BIT(FLASH->SECCR, FLASH_SECCR_SECLOCK) != 0u) |
| { |
| status = HAL_ERROR; |
| } |
| } |
| } |
| #endif |
| |
| return status; |
| } |
| |
| /** |
| * @brief Lock the FLASH control register access. |
| * @retval HAL Status |
| */ |
| HAL_StatusTypeDef HAL_FLASH_Lock(void) |
| { |
| HAL_StatusTypeDef status = HAL_ERROR; |
| |
| /* Set the LOCK Bit to lock the FLASH Registers access */ |
| SET_BIT(FLASH->NSCR, FLASH_NSCR_NSLOCK); |
| |
| /* verify Flash is locked */ |
| if (READ_BIT(FLASH->NSCR, FLASH_NSCR_NSLOCK) != 0u) |
| { |
| status = HAL_OK; |
| } |
| |
| #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) |
| if (status == HAL_OK) |
| { |
| SET_BIT(FLASH->SECCR, FLASH_SECCR_SECLOCK); |
| |
| /* verify Flash is locked */ |
| if (READ_BIT(FLASH->SECCR, FLASH_SECCR_SECLOCK) != 0u) |
| { |
| status = HAL_OK; |
| } |
| } |
| #endif |
| |
| return status; |
| } |
| |
| /** |
| * @brief Unlock the FLASH Option Bytes Registers access. |
| * @retval HAL Status |
| */ |
| HAL_StatusTypeDef HAL_FLASH_OB_Unlock(void) |
| { |
| if(READ_BIT(FLASH->NSCR, FLASH_NSCR_OPTLOCK) != 0u) |
| { |
| /* Authorizes the Option Byte register programming */ |
| WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY1); |
| WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY2); |
| |
| /* Verify that the Option Bytes are unlocked */ |
| if (READ_BIT(FLASH->NSCR, FLASH_NSCR_OPTLOCK) != 0u) |
| { |
| return HAL_ERROR; |
| } |
| } |
| |
| return HAL_OK; |
| } |
| |
| /** |
| * @brief Lock the FLASH Option Bytes Registers access. |
| * @retval HAL Status |
| */ |
| HAL_StatusTypeDef HAL_FLASH_OB_Lock(void) |
| { |
| /* Set the OPTLOCK Bit to lock the FLASH Option Byte Registers access */ |
| SET_BIT(FLASH->NSCR, FLASH_NSCR_OPTLOCK); |
| |
| /* Verify that the Option Bytes are locked */ |
| if (READ_BIT(FLASH->NSCR, FLASH_NSCR_OPTLOCK) != 0u) |
| { |
| return HAL_OK; |
| } |
| |
| return HAL_ERROR; |
| } |
| |
| /** |
| * @brief Launch the option byte loading. |
| * @retval HAL Status |
| */ |
| HAL_StatusTypeDef HAL_FLASH_OB_Launch(void) |
| { |
| /* Set the bit to force the option byte reloading */ |
| SET_BIT(FLASH->NSCR, FLASH_NSCR_OBL_LAUNCH); |
| |
| /* We should not reach here : Option byte launch generates Option byte reset |
| so return error */ |
| return HAL_ERROR; |
| } |
| |
| /** |
| * @} |
| */ |
| |
| /** @defgroup FLASH_Exported_Functions_Group3 Peripheral State and Errors functions |
| * @brief Peripheral Errors functions |
| * |
| @verbatim |
| =============================================================================== |
| ##### Peripheral Errors functions ##### |
| =============================================================================== |
| [..] |
| This subsection permits to get in run-time Errors of the FLASH peripheral. |
| |
| @endverbatim |
| * @{ |
| */ |
| |
| /** |
| * @brief Get the specific FLASH error flag. |
| * @retval FLASH_ErrorCode The returned value can be: |
| * @arg HAL_FLASH_ERROR_NONE: No error set |
| * @arg HAL_FLASH_ERROR_OP: FLASH Operation error |
| * @arg HAL_FLASH_ERROR_PROG: FLASH Programming error |
| * @arg HAL_FLASH_ERROR_WRP: FLASH Write protection error |
| * @arg HAL_FLASH_ERROR_PGA: FLASH Programming alignment error |
| * @arg HAL_FLASH_ERROR_SIZ: FLASH Size error |
| * @arg HAL_FLASH_ERROR_PGS: FLASH Programming sequence error |
| * @arg HAL_FLASH_ERROR_OPTW: FLASH Option modification error |
| */ |
| uint32_t HAL_FLASH_GetError(void) |
| { |
| return pFlash.ErrorCode; |
| } |
| |
| /** |
| * @} |
| */ |
| |
| /** |
| * @} |
| */ |
| |
| /* Private functions ---------------------------------------------------------*/ |
| |
| /** @addtogroup FLASH_Private_Functions |
| * @{ |
| */ |
| |
| /** |
| * @brief Wait for a FLASH operation to complete. |
| * @param Timeout maximum flash operation timeout |
| * @retval HAL_StatusTypeDef HAL Status |
| */ |
| HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout) |
| { |
| /* Wait for the FLASH operation to complete by polling on BUSY flag to be reset. |
| Even if the FLASH operation fails, the BUSY flag will be reset and an error |
| flag will be set */ |
| |
| uint32_t timeout = HAL_GetTick() + Timeout; |
| uint32_t error; |
| __IO uint32_t *reg_sr; |
| |
| while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) |
| { |
| if(Timeout != HAL_MAX_DELAY) |
| { |
| if(HAL_GetTick() >= timeout) |
| { |
| return HAL_TIMEOUT; |
| } |
| } |
| } |
| |
| /* Access to SECSR or NSSR registers depends on operation type */ |
| reg_sr = IS_FLASH_SECURE_OPERATION() ? &(FLASH->SECSR) : &(FLASH_NS->NSSR); |
| |
| /* Check FLASH operation error flags */ |
| error = ((*reg_sr) & FLASH_FLAG_SR_ERRORS); |
| #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) |
| error |= (FLASH->NSSR & FLASH_FLAG_OPTWERR); |
| #endif /* __ARM_FEATURE_CMSE */ |
| |
| if(error != 0u) |
| { |
| /*Save the error code*/ |
| pFlash.ErrorCode |= error; |
| |
| /* Clear error programming flags */ |
| (*reg_sr) = error; |
| #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) |
| if ((error & FLASH_FLAG_OPTWERR) != 0U) |
| { |
| FLASH->NSSR = FLASH_FLAG_OPTWERR; |
| } |
| #endif /* __ARM_FEATURE_CMSE */ |
| |
| return HAL_ERROR; |
| } |
| |
| /* Check FLASH End of Operation flag */ |
| if (((*reg_sr) & FLASH_FLAG_EOP) != 0U) |
| { |
| /* Clear FLASH End of Operation pending bit */ |
| (*reg_sr) = FLASH_FLAG_EOP; |
| } |
| |
| /* If there is an error flag set */ |
| return HAL_OK; |
| } |
| |
| /** |
| * @brief Program double-word (64-bit) at a specified address. |
| * @param Address specifies the address to be programmed. |
| * @param Data specifies the data to be programmed. |
| * @retval None |
| */ |
| static void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data) |
| { |
| uint32_t primask_bit; |
| __IO uint32_t *reg; |
| /* Check the parameters */ |
| assert_param(IS_FLASH_PROGRAM_ADDRESS(Address)); |
| |
| /* Access to SECCR or NSCR registers depends on operation type */ |
| reg = IS_FLASH_SECURE_OPERATION() ? &(FLASH->SECCR) : &(FLASH_NS->NSCR); |
| |
| /* Disable interrupts to avoid any interruption during the double word programming */ |
| primask_bit = __get_PRIMASK(); |
| __disable_irq(); |
| |
| /* Set PG bit */ |
| SET_BIT((*reg), FLASH_NSCR_NSPG); |
| |
| /* Program first word */ |
| *(uint32_t*)Address = (uint32_t)Data; |
| |
| /* Barrier to ensure programming is performed in 2 steps, in right order |
| (independently of compiler optimization behavior) */ |
| __ISB(); |
| |
| /* Program second word */ |
| *(uint32_t*)(Address+4U) = (uint32_t)(Data >> 32U); |
| |
| /* Re-enable the interrupts */ |
| __set_PRIMASK(primask_bit); |
| } |
| |
| /** |
| * @} |
| */ |
| |
| #endif /* HAL_FLASH_MODULE_ENABLED */ |
| |
| /** |
| * @} |
| */ |
| |
| /** |
| * @} |
| */ |