1 /**
2   ******************************************************************************
3   * @file    stm32l5xx_hal_flash.c
4   * @author  MCD Application Team
5   * @brief   FLASH HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          functionalities of the internal FLASH memory:
8   *           + Program operations functions
9   *           + Memory Control functions
10   *           + Peripheral Errors functions
11   *
12  @verbatim
13   ==============================================================================
14                         ##### Flash peripheral features #####
15   ==============================================================================
16 
17   [..] The Flash memory interface manages CPU AHB C-Bus accesses
18        to the Flash memory. It implements the erase and program Flash memory operations
19        and the read and write protection mechanisms.
20 
21   [..] The Flash memory interface implements the TrustZone security features (TZ) supported
22        by ARM Cortex-M33 core (CM33).
23 
24   [..] The FLASH main features are:
25       (+) Flash memory read operations
26       (+) Flash memory program/erase operations
27       (+) Read / write protections
28       (+) Option bytes programming
29 	  (+) TrustZone aware
30 	  (+) Watermark-based area protection including secure hide area
31 	  (+) Block-based page protection
32       (+) Error code correction (ECC) : Data in flash are 72-bits word
33           (8 bits added per double word)
34 
35                         ##### How to use this driver #####
36  ==============================================================================
37     [..]
38       This driver provides functions and macros to configure and program the FLASH
39       memory of all STM32L5xx devices.
40 
41       (#) Flash Memory IO Programming functions:
42            (++) Lock and Unlock the FLASH interface using HAL_FLASH_Unlock() and
43                 HAL_FLASH_Lock() functions
44            (++) Program functions: double word
45            (++) There Two modes of programming :
46             (+++) Polling mode using HAL_FLASH_Program() function
47             (+++) Interrupt mode using HAL_FLASH_Program_IT() function
48 
49       (#) Interrupts and flags management functions :
50            (++) Handle FLASH interrupts by calling HAL_FLASH_IRQHandler()
51            (++) Callback functions are called when the flash operations are finished :
52                 HAL_FLASH_EndOfOperationCallback() when everything is ok, otherwise
53                 HAL_FLASH_OperationErrorCallback()
54            (++) Get error flag status by calling HAL_GetError()
55 
56       (#) Option bytes management functions :
57            (++) Lock and Unlock the option bytes using HAL_FLASH_OB_Unlock() and
58                 HAL_FLASH_OB_Lock() functions
59            (++) Launch the reload of the option bytes using HAL_FLASH_Launch() function.
60                 In this case, a reset is generated
61 
62     [..]
63       In addition to these functions, this driver includes a set of macros allowing
64       to handle the following operations:
65        (+) Set the latency
66        (+) Enable/Disable the Flash power-down during low-power run and sleep modes
67        (+) Enable/Disable the Flash interrupts
68        (+) Monitor the Flash flags status
69 
70  @endverbatim
71   ******************************************************************************
72   * @attention
73   *
74   * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
75   * All rights reserved.</center></h2>
76   *
77   * This software component is licensed by ST under BSD 3-Clause license,
78   * the "License"; You may not use this file except in compliance with the
79   * License. You may obtain a copy of the License at:
80   *                        opensource.org/licenses/BSD-3-Clause
81   *
82   ******************************************************************************
83   */
84 
85 /* Includes ------------------------------------------------------------------*/
86 #include "stm32l5xx_hal.h"
87 
88 /** @addtogroup STM32L5xx_HAL_Driver
89   * @{
90   */
91 
92 /** @defgroup FLASH FLASH
93   * @brief FLASH HAL module driver
94   * @{
95   */
96 
97 #ifdef HAL_FLASH_MODULE_ENABLED
98 
99 /* Private typedef -----------------------------------------------------------*/
100 /* Private defines -----------------------------------------------------------*/
101 /* Private macros ------------------------------------------------------------*/
102 /* Private variables ---------------------------------------------------------*/
103 /** @defgroup FLASH_Private_Variables FLASH Private Variables
104  * @{
105  */
106 /**
107   * @brief  Variable used for Program/Erase sectors under interruption
108   */
109 FLASH_ProcessTypeDef pFlash = {.Lock = HAL_UNLOCKED, \
110                                .ErrorCode = HAL_FLASH_ERROR_NONE, \
111                                .ProcedureOnGoing = 0U, \
112                                .Address = 0U, \
113                                .Bank = FLASH_BANK_1, \
114                                .Page = 0U, \
115                                .NbPagesToErase = 0U};
116 /**
117   * @}
118   */
119 
120 /* Private function prototypes -----------------------------------------------*/
121 /** @defgroup FLASH_Private_Functions FLASH Private Functions
122  * @{
123  */
124 static void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data);
125 /**
126   * @}
127   */
128 
129 /* Exported functions --------------------------------------------------------*/
130 /** @defgroup FLASH_Exported_Functions FLASH Exported Functions
131   * @{
132   */
133 
134 /** @defgroup FLASH_Exported_Functions_Group1 Programming Operation functions
135  *  @brief   Programming Operation functions
136  *
137 @verbatim
138  ===============================================================================
139                   ##### Programming Operation functions #####
140  ===============================================================================
141     [..]
142     This subsection provides a set of functions allowing to manage the FLASH
143     program operations.
144 
145 @endverbatim
146   * @{
147   */
148 
149 /**
150   * @brief  Program double word at a specified address.
151   * @param  TypeProgram  Indicate the way to program at a specified address.
152   *                           This parameter can be a value of @ref FLASH_Type_Program
153   * @param  Address  specifies the address to be programmed.
154   * @param  Data specifies the data to be programmed
155   *                This parameter is the data for the double word program
156   *
157   * @retval HAL_StatusTypeDef HAL Status
158   */
HAL_FLASH_Program(uint32_t TypeProgram,uint32_t Address,uint64_t Data)159 HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
160 {
161   HAL_StatusTypeDef status;
162   __IO uint32_t *reg;
163 
164   /* Check the parameters */
165   assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
166 
167   /* Process Locked */
168   __HAL_LOCK(&pFlash);
169 
170   /* Reset error code */
171   pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
172 
173   /* Wait for last operation to be completed */
174   status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
175 
176   if(status == HAL_OK)
177   {
178     pFlash.ProcedureOnGoing = TypeProgram;
179     reg = IS_FLASH_SECURE_OPERATION() ? &(FLASH->SECCR) : &(FLASH_NS->NSCR);
180 
181     /* Program double-word (64-bit) at a specified address */
182     FLASH_Program_DoubleWord(Address, Data);
183 
184     /* Wait for last operation to be completed */
185     status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
186 
187     /* If the program operation is completed, disable the PG Bit */
188     CLEAR_BIT((*reg), (pFlash.ProcedureOnGoing & ~(FLASH_NON_SECURE_MASK)));
189   }
190 
191   /* Process Unlocked */
192   __HAL_UNLOCK(&pFlash);
193 
194   return status;
195 }
196 
197 /**
198   * @brief  Program double word at a specified address with interrupt enabled.
199   * @param  TypeProgram  Indicate the way to program at a specified address.
200   *                           This parameter can be a value of @ref FLASH_Type_Program
201   * @param  Address  specifies the address to be programmed.
202   * @param  Data specifies the data to be programmed
203   *                This parameter is the data for the double word program
204   *
205   * @retval HAL Status
206   */
HAL_FLASH_Program_IT(uint32_t TypeProgram,uint32_t Address,uint64_t Data)207 HAL_StatusTypeDef HAL_FLASH_Program_IT(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
208 {
209   HAL_StatusTypeDef status;
210   __IO uint32_t *reg_cr;
211 
212   /* Check the parameters */
213   assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
214 
215   /* Process Locked */
216   __HAL_LOCK(&pFlash);
217 
218   /* Reset error code */
219   pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
220 
221   /* Wait for last operation to be completed */
222   status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
223 
224   if (status != HAL_OK)
225   {
226     /* Process Unlocked */
227     __HAL_UNLOCK(&pFlash);
228   }
229   else
230   {
231     /* Set internal variables used by the IRQ handler */
232     pFlash.ProcedureOnGoing = TypeProgram;
233     pFlash.Address = Address;
234 
235     /* Access to SECCR or NSCR depends on operation type */
236     reg_cr = IS_FLASH_SECURE_OPERATION() ? &(FLASH->SECCR) : &(FLASH_NS->NSCR);
237 
238     /* Enable End of Operation and Error interrupts */
239     (*reg_cr) |= (FLASH_IT_EOP | FLASH_IT_OPERR);
240 
241     /* Program double-word (64-bit) at a specified address */
242     FLASH_Program_DoubleWord(Address, Data);
243   }
244 
245   return status;
246 }
247 
248 /**
249   * @brief Handle FLASH interrupt request.
250   * @retval None
251   */
HAL_FLASH_IRQHandler(void)252 void HAL_FLASH_IRQHandler(void)
253 {
254   uint32_t param = 0U;
255   uint32_t error, type;
256   __IO uint32_t *reg;
257   __IO uint32_t *reg_sr;
258 
259   type = (pFlash.ProcedureOnGoing & ~(FLASH_NON_SECURE_MASK));
260   reg = IS_FLASH_SECURE_OPERATION() ? &(FLASH->SECCR) : &(FLASH_NS->NSCR);
261   reg_sr = IS_FLASH_SECURE_OPERATION() ? &(FLASH->SECSR) : &(FLASH_NS->NSSR);
262 
263   /* Save Flash errors */
264   error = (*reg_sr) & FLASH_FLAG_SR_ERRORS;
265 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
266   error |= (FLASH->NSSR & FLASH_FLAG_OPTWERR);
267 #endif /* __ARM_FEATURE_CMSE */
268 
269   /* Set parameter of the callback */
270   if(type == FLASH_TYPEERASE_PAGES)
271   {
272     param = pFlash.Page;
273   }
274   else if(type == FLASH_TYPEERASE_MASSERASE)
275   {
276     param = pFlash.Bank;
277   }
278   else if(type == FLASH_TYPEPROGRAM_DOUBLEWORD)
279   {
280     param = pFlash.Address;
281   }
282   else
283   {
284     /* Empty statement (to be compliant MISRA 15.7) */
285   }
286 
287   /* Clear bit on the on-going procedure */
288   CLEAR_BIT((*reg), type);
289 
290   /* Check FLASH operation error flags */
291   if(error != 0U)
292   {
293     /* Save the error code */
294     pFlash.ErrorCode |= error;
295 
296     /* Clear error programming flags */
297     (*reg_sr) = error;
298 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
299     if ((error & FLASH_FLAG_OPTWERR) != 0U)
300     {
301       FLASH->NSSR = FLASH_FLAG_OPTWERR;
302     }
303 #endif /* __ARM_FEATURE_CMSE */
304 
305     /* Stop the procedure ongoing */
306     pFlash.ProcedureOnGoing = 0U;
307 
308     /* FLASH error interrupt user callback */
309     HAL_FLASH_OperationErrorCallback(param);
310   }
311 
312   /* Check FLASH End of Operation flag  */
313   if (((*reg_sr) & FLASH_FLAG_EOP) != 0U)
314   {
315     /* Clear FLASH End of Operation pending bit */
316     (*reg_sr) = FLASH_FLAG_EOP;
317 
318     if(type == FLASH_TYPEERASE_PAGES)
319     {
320       /* Nb of pages to erased can be decreased */
321       pFlash.NbPagesToErase--;
322 
323       /* Check if there are still pages to erase*/
324       if(pFlash.NbPagesToErase != 0U)
325       {
326         /* Increment page number */
327         pFlash.Page++;
328         FLASH_PageErase(pFlash.Page, pFlash.Bank);
329       }
330       else
331       {
332         /* No more pages to Erase */
333         pFlash.ProcedureOnGoing = 0U;
334         param = 0xFFFFFFFFU;
335       }
336     }
337     else
338     {
339       /*Clear the procedure ongoing*/
340       pFlash.ProcedureOnGoing = 0U;
341     }
342 
343     /* FLASH EOP interrupt user callback */
344     HAL_FLASH_EndOfOperationCallback(param);
345   }
346 
347   if(pFlash.ProcedureOnGoing == 0U)
348   {
349     /* Disable End of Operation and Error interrupts */
350     (*reg) &= ~(FLASH_IT_EOP | FLASH_IT_OPERR);
351 
352     /* Process Unlocked */
353     __HAL_UNLOCK(&pFlash);
354   }
355 }
356 
357 /**
358   * @brief  FLASH end of operation interrupt callback.
359   * @param  ReturnValue The value saved in this parameter depends on the ongoing procedure :
360   *                  @arg Mass Erase: Bank number which has been requested to erase
361   *                  @arg Page Erase: Page which has been erased
362   *                       (if 0xFFFFFFFF, it means that all the selected pages have been erased)
363   *                  @arg Program: Address which was selected for data program
364   * @retval None
365   */
HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue)366 __weak void HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue)
367 {
368   /* Prevent unused argument(s) compilation warning */
369   UNUSED(ReturnValue);
370 
371   /* NOTE : This function should not be modified, when the callback is needed,
372             the HAL_FLASH_EndOfOperationCallback could be implemented in the user file
373    */
374 }
375 
376 /**
377   * @brief  FLASH operation error interrupt callback.
378   * @param  ReturnValue The value saved in this parameter depends on the ongoing procedure :
379   *                 @arg Mass Erase: Bank number which has been requested to erase
380   *                 @arg Page Erase: Page number which returned an error
381   *                 @arg Program: Address which was selected for data program
382   * @retval None
383   */
HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue)384 __weak void HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue)
385 {
386   /* Prevent unused argument(s) compilation warning */
387   UNUSED(ReturnValue);
388 
389   /* NOTE : This function should not be modified, when the callback is needed,
390             the HAL_FLASH_OperationErrorCallback could be implemented in the user file
391    */
392 }
393 
394 /**
395   * @}
396   */
397 
398 /** @defgroup FLASH_Exported_Functions_Group2 Peripheral Control functions
399  *  @brief   Management functions
400  *
401 @verbatim
402  ===============================================================================
403                       ##### Peripheral Control functions #####
404  ===============================================================================
405     [..]
406     This subsection provides a set of functions allowing to control the FLASH
407     memory operations.
408 
409 @endverbatim
410   * @{
411   */
412 
413 /**
414   * @brief  Unlock the FLASH control register access.
415   * @retval HAL Status
416   */
HAL_FLASH_Unlock(void)417 HAL_StatusTypeDef HAL_FLASH_Unlock(void)
418 {
419   HAL_StatusTypeDef status = HAL_OK;
420 
421   if(READ_BIT(FLASH->NSCR, FLASH_NSCR_NSLOCK) != 0u)
422   {
423     /* Authorize the FLASH Registers access */
424     WRITE_REG(FLASH->NSKEYR, FLASH_KEY1);
425     WRITE_REG(FLASH->NSKEYR, FLASH_KEY2);
426 
427     /* verify Flash is unlocked */
428     if (READ_BIT(FLASH->NSCR, FLASH_NSCR_NSLOCK) != 0u)
429     {
430       status = HAL_ERROR;
431     }
432   }
433 
434 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
435   if (status == HAL_OK)
436   {
437     if(READ_BIT(FLASH->SECCR, FLASH_SECCR_SECLOCK) != 0u)
438     {
439       /* Authorize the FLASH Registers access */
440       WRITE_REG(FLASH->SECKEYR, FLASH_KEY1);
441       WRITE_REG(FLASH->SECKEYR, FLASH_KEY2);
442 
443       /* verify Flash is unlocked */
444       if (READ_BIT(FLASH->SECCR, FLASH_SECCR_SECLOCK) != 0u)
445       {
446         status = HAL_ERROR;
447       }
448     }
449   }
450 #endif
451 
452   return status;
453 }
454 
455 /**
456   * @brief  Lock the FLASH control register access.
457   * @retval HAL Status
458   */
HAL_FLASH_Lock(void)459 HAL_StatusTypeDef HAL_FLASH_Lock(void)
460 {
461   HAL_StatusTypeDef status = HAL_ERROR;
462 
463   /* Set the LOCK Bit to lock the FLASH Registers access */
464   SET_BIT(FLASH->NSCR, FLASH_NSCR_NSLOCK);
465 
466   /* verify Flash is locked */
467   if (READ_BIT(FLASH->NSCR, FLASH_NSCR_NSLOCK) != 0u)
468   {
469     status = HAL_OK;
470   }
471 
472 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
473   if (status == HAL_OK)
474   {
475     SET_BIT(FLASH->SECCR, FLASH_SECCR_SECLOCK);
476 
477     /* verify Flash is locked */
478     if (READ_BIT(FLASH->SECCR, FLASH_SECCR_SECLOCK) != 0u)
479     {
480       status = HAL_OK;
481     }
482   }
483 #endif
484 
485   return status;
486 }
487 
488 /**
489   * @brief  Unlock the FLASH Option Bytes Registers access.
490   * @retval HAL Status
491   */
HAL_FLASH_OB_Unlock(void)492 HAL_StatusTypeDef HAL_FLASH_OB_Unlock(void)
493 {
494   if(READ_BIT(FLASH->NSCR, FLASH_NSCR_OPTLOCK) != 0u)
495   {
496     /* Authorizes the Option Byte register programming */
497     WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY1);
498     WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY2);
499 
500     /* Verify that the Option Bytes are unlocked */
501     if (READ_BIT(FLASH->NSCR, FLASH_NSCR_OPTLOCK) != 0u)
502     {
503       return HAL_ERROR;
504     }
505   }
506 
507   return HAL_OK;
508 }
509 
510 /**
511   * @brief  Lock the FLASH Option Bytes Registers access.
512   * @retval HAL Status
513   */
HAL_FLASH_OB_Lock(void)514 HAL_StatusTypeDef HAL_FLASH_OB_Lock(void)
515 {
516   /* Set the OPTLOCK Bit to lock the FLASH Option Byte Registers access */
517   SET_BIT(FLASH->NSCR, FLASH_NSCR_OPTLOCK);
518 
519   /* Verify that the Option Bytes are locked */
520   if (READ_BIT(FLASH->NSCR, FLASH_NSCR_OPTLOCK) != 0u)
521   {
522     return HAL_OK;
523   }
524 
525   return HAL_ERROR;
526 }
527 
528 /**
529   * @brief  Launch the option byte loading.
530   * @retval HAL Status
531   */
HAL_FLASH_OB_Launch(void)532 HAL_StatusTypeDef HAL_FLASH_OB_Launch(void)
533 {
534   /* Set the bit to force the option byte reloading */
535   SET_BIT(FLASH->NSCR, FLASH_NSCR_OBL_LAUNCH);
536 
537   /* We should not reach here : Option byte launch generates Option byte reset
538      so return error */
539   return HAL_ERROR;
540 }
541 
542 /**
543   * @}
544   */
545 
546 /** @defgroup FLASH_Exported_Functions_Group3 Peripheral State and Errors functions
547  *  @brief   Peripheral Errors functions
548  *
549 @verbatim
550  ===============================================================================
551                 ##### Peripheral Errors functions #####
552  ===============================================================================
553     [..]
554     This subsection permits to get in run-time Errors of the FLASH peripheral.
555 
556 @endverbatim
557   * @{
558   */
559 
560 /**
561   * @brief  Get the specific FLASH error flag.
562   * @retval FLASH_ErrorCode The returned value can be:
563   *            @arg HAL_FLASH_ERROR_NONE: No error set
564   *            @arg HAL_FLASH_ERROR_OP: FLASH Operation error
565   *            @arg HAL_FLASH_ERROR_PROG: FLASH Programming error
566   *            @arg HAL_FLASH_ERROR_WRP: FLASH Write protection error
567   *            @arg HAL_FLASH_ERROR_PGA: FLASH Programming alignment error
568   *            @arg HAL_FLASH_ERROR_SIZ: FLASH Size error
569   *            @arg HAL_FLASH_ERROR_PGS: FLASH Programming sequence error
570   *            @arg HAL_FLASH_ERROR_OPTW: FLASH Option modification error
571   */
HAL_FLASH_GetError(void)572 uint32_t HAL_FLASH_GetError(void)
573 {
574    return pFlash.ErrorCode;
575 }
576 
577 /**
578   * @}
579   */
580 
581 /**
582   * @}
583   */
584 
585 /* Private functions ---------------------------------------------------------*/
586 
587 /** @addtogroup FLASH_Private_Functions
588   * @{
589   */
590 
591 /**
592   * @brief  Wait for a FLASH operation to complete.
593   * @param  Timeout maximum flash operation timeout
594   * @retval HAL_StatusTypeDef HAL Status
595   */
FLASH_WaitForLastOperation(uint32_t Timeout)596 HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout)
597 {
598   /* Wait for the FLASH operation to complete by polling on BUSY flag to be reset.
599      Even if the FLASH operation fails, the BUSY flag will be reset and an error
600      flag will be set */
601 
602   uint32_t timeout = HAL_GetTick() + Timeout;
603   uint32_t error;
604   __IO uint32_t *reg_sr;
605 
606   while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY))
607   {
608     if(Timeout != HAL_MAX_DELAY)
609     {
610       if(HAL_GetTick() >= timeout)
611       {
612         return HAL_TIMEOUT;
613       }
614     }
615   }
616 
617   /* Access to SECSR or NSSR registers depends on operation type */
618   reg_sr = IS_FLASH_SECURE_OPERATION() ? &(FLASH->SECSR) : &(FLASH_NS->NSSR);
619 
620   /* Check FLASH operation error flags */
621   error = ((*reg_sr) & FLASH_FLAG_SR_ERRORS);
622 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
623   error |= (FLASH->NSSR & FLASH_FLAG_OPTWERR);
624 #endif /* __ARM_FEATURE_CMSE */
625 
626   if(error != 0u)
627   {
628     /*Save the error code*/
629     pFlash.ErrorCode |= error;
630 
631     /* Clear error programming flags */
632     (*reg_sr) = error;
633 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
634     if ((error & FLASH_FLAG_OPTWERR) != 0U)
635     {
636       FLASH->NSSR = FLASH_FLAG_OPTWERR;
637     }
638 #endif /* __ARM_FEATURE_CMSE */
639 
640     return HAL_ERROR;
641   }
642 
643   /* Check FLASH End of Operation flag  */
644   if (((*reg_sr) & FLASH_FLAG_EOP) != 0U)
645   {
646     /* Clear FLASH End of Operation pending bit */
647     (*reg_sr) = FLASH_FLAG_EOP;
648   }
649 
650   /* If there is an error flag set */
651   return HAL_OK;
652 }
653 
654 /**
655   * @brief  Program double-word (64-bit) at a specified address.
656   * @param  Address specifies the address to be programmed.
657   * @param  Data specifies the data to be programmed.
658   * @retval None
659   */
FLASH_Program_DoubleWord(uint32_t Address,uint64_t Data)660 static void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data)
661 {
662   uint32_t primask_bit;
663   __IO uint32_t *reg;
664   /* Check the parameters */
665   assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
666 
667   /* Access to SECCR or NSCR registers depends on operation type */
668   reg = IS_FLASH_SECURE_OPERATION() ? &(FLASH->SECCR) : &(FLASH_NS->NSCR);
669 
670   /* Disable interrupts to avoid any interruption during the double word programming */
671   primask_bit = __get_PRIMASK();
672   __disable_irq();
673 
674   /* Set PG bit */
675   SET_BIT((*reg), FLASH_NSCR_NSPG);
676 
677   /* Program first word */
678   *(uint32_t*)Address = (uint32_t)Data;
679 
680   /* Barrier to ensure programming is performed in 2 steps, in right order
681     (independently of compiler optimization behavior) */
682   __ISB();
683 
684   /* Program second word */
685   *(uint32_t*)(Address+4U) = (uint32_t)(Data >> 32U);
686 
687   /* Re-enable the interrupts */
688   __set_PRIMASK(primask_bit);
689 }
690 
691 /**
692   * @}
693   */
694 
695 #endif /* HAL_FLASH_MODULE_ENABLED */
696 
697 /**
698   * @}
699   */
700 
701 /**
702   * @}
703   */
704 
705 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
706