1 /**
2   ******************************************************************************
3   * @file    stm32wlxx_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   ******************************************************************************
13   * @attention
14   *
15   * Copyright (c) 2020 STMicroelectronics.
16   * All rights reserved.
17   *
18   * This software is licensed under terms that can be found in the LICENSE file
19   * in the root directory of this software component.
20   * If no LICENSE file comes with this software, it is provided AS-IS.
21   *
22   ******************************************************************************
23  @verbatim
24   ==============================================================================
25                         ##### FLASH peripheral features #####
26   ==============================================================================
27 
28   [..] The Flash memory interface manages CPU AHB I-Code and D-Code accesses
29        to the Flash memory. It implements the erase and program Flash memory operations
30        and the read and write protection mechanisms.
31 
32   [..] The Flash memory interface accelerates code execution with a system of instruction
33        prefetch and cache lines.
34 
35   [..] The FLASH main features are:
36       (+) Flash memory read operations
37       (+) Flash memory program/erase operations
38       (+) Program and Erase suspension
39       (+) Read / write protections (2 areas per features)
40       (+) CPU2 Security area
41       (+) Option bytes programming
42       (+) Prefetch on CPU1 I-Code and CPU2 S-bus
43       (+) 32 instruction cache lines of 4*64 bits on I-Code for CPU1
44       (+) 8 data cache lines of 4*64 bits on D-Code for CPU1
45       (+) 4 instruction cache lines of 1*64 bits on S-bus for CPU2
46       (+) 4 data cache lines of 1*64 bits on S-Bus for CPU2
47       (+) Error code correction (ECC) : Data in flash are 72-bits word
48           (8 bits added per double word)
49 
50                         ##### How to use this driver #####
51  ==============================================================================
52     [..]
53       This driver provides functions and macros to configure and program the FLASH
54       memory of all STM32WLxx devices.
55 
56       (#) Flash Memory IO Programming functions:
57            (++) Lock and Unlock the FLASH interface using HAL_FLASH_Unlock() and
58                 HAL_FLASH_Lock() functions
59            (++) Program functions: double word and fast program (full row programming)
60            (++) There are two modes of programming:
61             (+++) Polling mode using HAL_FLASH_Program() function
62             (+++) Interrupt mode using HAL_FLASH_Program_IT() function
63 
64       (#) Interrupts and flags management functions:
65            (++) Handle FLASH interrupts by calling HAL_FLASH_IRQHandler()
66            (++) Callback functions are called when the flash operations are finished :
67                 HAL_FLASH_EndOfOperationCallback() when everything is ok, otherwise
68                 HAL_FLASH_OperationErrorCallback()
69            (++) Get error flag status by calling HAL_GetError()
70 
71       (#) Option bytes management functions :
72            (++) Lock and Unlock the option bytes using HAL_FLASH_OB_Unlock() and
73                 HAL_FLASH_OB_Lock() functions
74            (++) Launch the reload of the option bytes using HAL_FLASH_OB_Launch() function.
75                 In this case, a reset is generated
76 
77     [..]
78       In addition to these functions, this driver includes a set of macros allowing
79       to handle the following operations:
80        (+) Set the latency
81        (+) Enable/Disable the prefetch buffer
82        (+) Enable/Disable the suspend program or erase request
83        (+) Enable/Disable the Instruction cache and the Data cache
84        (+) Reset the Instruction cache and the Data cache
85        (+) Enable/Disable the Flash interrupts
86        (+) Monitor the Flash flags status
87 
88  @endverbatim
89   ******************************************************************************
90   */
91 
92 /* Includes ------------------------------------------------------------------*/
93 #include "stm32wlxx_hal.h"
94 
95 /** @addtogroup STM32WLxx_HAL_Driver
96   * @{
97   */
98 
99 /** @defgroup FLASH FLASH
100   * @brief FLASH HAL module driver
101   * @{
102   */
103 
104 #ifdef HAL_FLASH_MODULE_ENABLED
105 
106 /* Private typedef -----------------------------------------------------------*/
107 /* Private defines -----------------------------------------------------------*/
108 /** @addtogroup FLASH_Private_Constants
109   * @{
110   */
111 #define FLASH_NB_DOUBLE_WORDS_IN_ROW  32
112 /**
113   * @}
114   */
115 
116 /* Private macros ------------------------------------------------------------*/
117 /* Private variables ---------------------------------------------------------*/
118 /** @defgroup FLASH_Private_Variables FLASH Private Variables
119  * @{
120  */
121 /**
122   * @brief  Variable used for Program/Erase sectors under interruption
123   */
124 FLASH_ProcessTypeDef pFlash = {.Lock = HAL_UNLOCKED, \
125                                .ErrorCode = HAL_FLASH_ERROR_NONE, \
126                                .ProcedureOnGoing = 0U, \
127                                .Address = 0U, \
128                                .Page = 0U, \
129                                .NbPagesToErase = 0U
130                               };
131 /**
132   * @}
133   */
134 
135 /* Private function prototypes -----------------------------------------------*/
136 /** @defgroup FLASH_Private_Functions FLASH Private Functions
137  * @{
138  */
139 static void          FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data);
140 static void          FLASH_Program_Fast(uint32_t Address, uint32_t DataAddress);
141 /**
142   * @}
143   */
144 
145 /* Exported functions --------------------------------------------------------*/
146 /** @defgroup FLASH_Exported_Functions FLASH Exported Functions
147   * @{
148   */
149 
150 /** @defgroup FLASH_Exported_Functions_Group1 Programming operation functions
151  *  @brief   Programming operation functions
152  *
153 @verbatim
154  ===============================================================================
155                   ##### Programming operation functions #####
156  ===============================================================================
157     [..]
158     This subsection provides a set of functions allowing to manage the FLASH
159     program operations.
160 
161 @endverbatim
162   * @{
163   */
164 
165 /**
166   * @brief  Program double word or fast program of a row at a specified address.
167   * @note   Before any operation, it is possible to check there is no operation suspended
168   *         by call HAL_FLASHEx_IsOperationSuspended()
169   * @param  TypeProgram Indicate the way to program at a specified address
170   *                       This parameter can be a value of @ref FLASH_TYPE_PROGRAM
171   * @param  Address Specifies the address to be programmed.
172   * @param  Data Specifies the data to be programmed
173   *                This parameter is the data for the double word program and the address where
174   *                are stored the data for the row fast program.
175   *
176   * @retval HAL_StatusTypeDef HAL Status
177   */
HAL_FLASH_Program(uint32_t TypeProgram,uint32_t Address,uint64_t Data)178 HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
179 {
180   HAL_StatusTypeDef status;
181 
182   /* Check the parameters */
183   assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
184   assert_param(IS_ADDR_ALIGNED_64BITS(Address));
185   assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
186 
187   /* Process Locked */
188   __HAL_LOCK(&pFlash);
189 
190   /* Reset error code */
191   pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
192 
193   /* Verify that next operation can be proceed */
194   status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
195 
196   if (status == HAL_OK)
197   {
198     if (TypeProgram == FLASH_TYPEPROGRAM_DOUBLEWORD)
199     {
200       /* Check the parameters */
201       assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
202 
203       /* Program double-word (64-bit) at a specified address */
204       FLASH_Program_DoubleWord(Address, Data);
205     }
206     else
207     {
208       /* Check the parameters */
209       assert_param(IS_FLASH_FAST_PROGRAM_ADDRESS(Address));
210 
211       /* Fast program a 32 double-word (64-bit) row at a specified address */
212       FLASH_Program_Fast(Address, (uint32_t)Data);
213     }
214 
215     /* Wait for last operation to be completed */
216     status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
217 
218     /* If the program operation is completed, disable the PG or FSTPG Bit */
219 #ifdef CORE_CM0PLUS
220     CLEAR_BIT(FLASH->C2CR, TypeProgram);
221 #else
222     CLEAR_BIT(FLASH->CR, TypeProgram);
223 #endif
224   }
225 
226   /* Process Unlocked */
227   __HAL_UNLOCK(&pFlash);
228 
229   /* return status */
230   return status;
231 }
232 
233 /**
234   * @brief  Program double word or fast program of a row at a specified address with interrupt enabled.
235   * @note   Before any operation, it is possible to check there is no operation suspended
236   *         by call HAL_FLASHEx_IsOperationSuspended()
237   * @param  TypeProgram Indicate the way to program at a specified address.
238   *                           This parameter can be a value of @ref FLASH_TYPE_PROGRAM
239   * @param  Address Specifies the address to be programmed.
240   * @param  Data Specifies the data to be programmed
241   *                This parameter is the data for the double word program and the address where
242   *                are stored the data for the row fast program.
243   *
244   * @retval HAL Status
245   */
HAL_FLASH_Program_IT(uint32_t TypeProgram,uint32_t Address,uint64_t Data)246 HAL_StatusTypeDef HAL_FLASH_Program_IT(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
247 {
248   HAL_StatusTypeDef status;
249 
250   /* Check the parameters */
251   assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
252   assert_param(IS_ADDR_ALIGNED_64BITS(Address));
253   assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
254 
255   /* Process Locked */
256   __HAL_LOCK(&pFlash);
257 
258   /* Reset error code */
259   pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
260 
261   /* Verify that next operation can be proceed */
262   status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
263 
264   if (status != HAL_OK)
265   {
266     /* Process Unlocked */
267     __HAL_UNLOCK(&pFlash);
268   }
269   else
270   {
271     /* Set internal variables used by the IRQ handler */
272     pFlash.ProcedureOnGoing = TypeProgram;
273     pFlash.Address = Address;
274 
275     /* Enable End of Operation and Error interrupts */
276     __HAL_FLASH_ENABLE_IT(FLASH_IT_EOP | FLASH_IT_OPERR | FLASH_IT_ECCC);
277 
278     if (TypeProgram == FLASH_TYPEPROGRAM_DOUBLEWORD)
279     {
280       /* Check the parameters */
281       assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
282 
283       /* Program double-word (64-bit) at a specified address */
284       FLASH_Program_DoubleWord(Address, Data);
285     }
286     else
287     {
288       /* Check the parameters */
289       assert_param(IS_FLASH_FAST_PROGRAM_ADDRESS(Address));
290 
291       /* Fast program a 32 double-word (64-bit) row at a specified address */
292       FLASH_Program_Fast(Address, (uint32_t)Data);
293     }
294   }
295 
296   /* return status */
297   return status;
298 }
299 
300 /**
301   * @brief Handle FLASH interrupt request.
302   * @retval None
303   */
HAL_FLASH_IRQHandler(void)304 void HAL_FLASH_IRQHandler(void)
305 {
306   uint32_t param = 0xFFFFFFFFU;
307   uint32_t error;
308 
309   /* Save flash errors. Only ECC detection can be checked here as ECCC
310      generates NMI */
311 #ifdef CORE_CM0PLUS
312   error = (FLASH->C2SR & FLASH_FLAG_SR_ERRORS);
313 
314   /* Clear Current operation */
315   CLEAR_BIT(FLASH->C2CR, pFlash.ProcedureOnGoing);
316 #else
317   error = (FLASH->SR & FLASH_FLAG_SR_ERRORS);
318 
319   /* Clear Current operation */
320   CLEAR_BIT(FLASH->CR, pFlash.ProcedureOnGoing);
321 #endif
322 
323   /* A] Set parameter for user or error callbacks */
324   /* check operation was a program or erase */
325   if ((pFlash.ProcedureOnGoing & (FLASH_TYPEPROGRAM_DOUBLEWORD | FLASH_TYPEPROGRAM_FAST)) != 0U)
326   {
327     /* return address being programmed */
328     param = pFlash.Address;
329   }
330   else if ((pFlash.ProcedureOnGoing & (FLASH_TYPEERASE_MASSERASE | FLASH_TYPEERASE_PAGES)) != 0U)
331   {
332     /* return page number being erased (0 for mass erase) */
333     param = pFlash.Page;
334   }
335   else
336   {
337     /* No Procedure on-going */
338     /* Nothing to do, but check error if any */
339   }
340 
341   /* B] Check errors */
342   if (error != 0U)
343   {
344     /*Save the error code*/
345     pFlash.ErrorCode |= error;
346 
347     /* clear error flags */
348     __HAL_FLASH_CLEAR_FLAG(error);
349 
350     /*Stop the procedure ongoing*/
351     pFlash.ProcedureOnGoing = FLASH_TYPENONE;
352 
353     /* Error callback */
354     HAL_FLASH_OperationErrorCallback(param);
355   }
356 
357   /* C] Check FLASH End of Operation flag */
358   if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP))
359   {
360     /* Clear FLASH End of Operation pending bit */
361     __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
362 
363     if (pFlash.ProcedureOnGoing == FLASH_TYPEERASE_PAGES)
364     {
365       /* Nb of pages to erased can be decreased */
366       pFlash.NbPagesToErase--;
367 
368       /* Check if there are still pages to erase*/
369       if (pFlash.NbPagesToErase != 0U)
370       {
371         /* Increment page number */
372         pFlash.Page++;
373         FLASH_PageErase(pFlash.Page);
374       }
375       else
376       {
377         /* No more pages to erase: stop erase pages procedure */
378         pFlash.ProcedureOnGoing = FLASH_TYPENONE;
379       }
380     }
381     else
382     {
383       /*Stop the ongoing procedure */
384       pFlash.ProcedureOnGoing = FLASH_TYPENONE;
385     }
386 
387     /* User callback */
388     HAL_FLASH_EndOfOperationCallback(param);
389   }
390 
391   if (pFlash.ProcedureOnGoing == FLASH_TYPENONE)
392   {
393     /* Disable End of Operation and Error interrupts */
394     __HAL_FLASH_DISABLE_IT(FLASH_IT_EOP | FLASH_IT_OPERR | FLASH_IT_ECCC);
395 
396     /* Process Unlocked */
397     __HAL_UNLOCK(&pFlash);
398   }
399 }
400 
401 /**
402   * @brief  FLASH end of operation interrupt callback.
403   * @param  ReturnValue The value saved in this parameter depends on the ongoing procedure
404   *                  Mass Erase: 0
405   *                  Page Erase: Page which has been erased
406   *                  Program: Address which was selected for data program
407   * @retval None
408   */
HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue)409 __weak void HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue)
410 {
411   /* Prevent unused argument(s) compilation warning */
412   UNUSED(ReturnValue);
413 
414   /* NOTE : This function should not be modified, when the callback is needed,
415             the HAL_FLASH_EndOfOperationCallback could be implemented in the user file
416    */
417 }
418 
419 /**
420   * @brief  FLASH operation error interrupt callback.
421   * @param  ReturnValue The value saved in this parameter depends on the ongoing procedure
422   *                 Mass Erase: 0
423   *                 Page Erase: Page number which returned an error
424   *                 Program: Address which was selected for data program
425   * @retval None
426   */
HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue)427 __weak void HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue)
428 {
429   /* Prevent unused argument(s) compilation warning */
430   UNUSED(ReturnValue);
431 
432   /* NOTE : This function should not be modified, when the callback is needed,
433             the HAL_FLASH_OperationErrorCallback could be implemented in the user file
434    */
435 }
436 
437 /**
438   * @}
439   */
440 
441 /** @defgroup FLASH_Exported_Functions_Group2 Peripheral Control functions
442  *  @brief   Management functions
443  *
444 @verbatim
445  ===============================================================================
446                       ##### Peripheral Control functions #####
447  ===============================================================================
448     [..]
449     This subsection provides a set of functions allowing to control the FLASH
450     memory operations.
451 
452 @endverbatim
453   * @{
454   */
455 
456 /**
457   * @brief  Unlock the FLASH control register access.
458   * @retval HAL Status
459   */
HAL_FLASH_Unlock(void)460 HAL_StatusTypeDef HAL_FLASH_Unlock(void)
461 {
462   HAL_StatusTypeDef status = HAL_OK;
463 
464   if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0U)
465   {
466     /* Authorize the FLASH Registers access */
467     WRITE_REG(FLASH->KEYR, FLASH_KEY1);
468     WRITE_REG(FLASH->KEYR, FLASH_KEY2);
469 
470     /* verify Flash is unlock */
471     if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0U)
472     {
473       status = HAL_ERROR;
474     }
475   }
476 
477   return status;
478 }
479 
480 /**
481   * @brief  Lock the FLASH control register access.
482   * @retval HAL Status
483   */
HAL_FLASH_Lock(void)484 HAL_StatusTypeDef HAL_FLASH_Lock(void)
485 {
486   HAL_StatusTypeDef status = HAL_OK;
487 
488   /* Set the LOCK Bit to lock the FLASH Registers access */
489   /* @Note  The lock and unlock procedure is done only using CR registers even from CPU2 */
490   SET_BIT(FLASH->CR, FLASH_CR_LOCK);
491 
492   /* verify Flash is locked */
493   if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) == 0U)
494   {
495     status = HAL_ERROR;
496   }
497 
498   return status;
499 }
500 
501 /**
502   * @brief  Unlock the FLASH Option Bytes Registers access.
503   * @retval HAL Status
504   */
HAL_FLASH_OB_Unlock(void)505 HAL_StatusTypeDef HAL_FLASH_OB_Unlock(void)
506 {
507   HAL_StatusTypeDef status = HAL_ERROR;
508 
509   /* @Note The lock and unlock procedure is done only using CR registers even from CPU2 */
510   if (READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) != 0U)
511   {
512     /* Authorizes the Option Byte register programming */
513     WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY1);
514     WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY2);
515 
516     /* verify option bytes are unlocked */
517     if (READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) == 0U)
518     {
519       status = HAL_OK;
520     }
521   }
522 
523   return status;
524 }
525 
526 /**
527   * @brief  Lock the FLASH Option Bytes Registers access.
528   * @retval HAL Status
529   */
HAL_FLASH_OB_Lock(void)530 HAL_StatusTypeDef HAL_FLASH_OB_Lock(void)
531 {
532   HAL_StatusTypeDef status = HAL_OK;
533 
534   /* Set the OPTLOCK Bit to lock the FLASH Option Byte Registers access */
535   /* @Note The lock and unlock procedure is done only using CR registers even from CPU2 */
536   SET_BIT(FLASH->CR, FLASH_CR_OPTLOCK);
537 
538   /* verify option bytes are lock */
539   if (READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) == 0U)
540   {
541     status = HAL_ERROR;
542   }
543 
544   return status;
545 }
546 
547 /**
548   * @brief  Launch the option byte loading.
549   * @retval HAL Status
550   */
HAL_FLASH_OB_Launch(void)551 HAL_StatusTypeDef HAL_FLASH_OB_Launch(void)
552 {
553   /* Set the bit to force the option byte reloading */
554   /* The OB launch is done from the same register either from CPU1 or CPU2 */
555   SET_BIT(FLASH->CR, FLASH_CR_OBL_LAUNCH);
556 
557   /* We should not reach here : Option byte launch generates Option byte reset
558      so return error */
559   return HAL_ERROR;
560 }
561 
562 /**
563   * @}
564   */
565 
566 /** @defgroup FLASH_Exported_Functions_Group3 Peripheral State and Errors functions
567  *  @brief   Peripheral Errors functions
568  *
569 @verbatim
570  ===============================================================================
571                 ##### Peripheral Errors functions #####
572  ===============================================================================
573     [..]
574     This subsection permits to get in run-time Errors of the FLASH peripheral.
575 
576 @endverbatim
577   * @{
578   */
579 
580 /**
581   * @brief  Get the specific FLASH error flag.
582   * @retval FLASH_ErrorCode The returned value can be
583   *            @arg @ref HAL_FLASH_ERROR_NONE No error set
584   *            @arg @ref HAL_FLASH_ERROR_OP FLASH Operation error
585   *            @arg @ref HAL_FLASH_ERROR_PROG FLASH Programming error
586   *            @arg @ref HAL_FLASH_ERROR_WRP FLASH Write protection error
587   *            @arg @ref HAL_FLASH_ERROR_PGA FLASH Programming alignment error
588   *            @arg @ref HAL_FLASH_ERROR_SIZ FLASH Size error
589   *            @arg @ref HAL_FLASH_ERROR_PGS FLASH Programming sequence error
590   *            @arg @ref HAL_FLASH_ERROR_MIS FLASH Fast programming data miss error
591   *            @arg @ref HAL_FLASH_ERROR_FAST FLASH Fast programming error
592   *            @arg @ref HAL_FLASH_ERROR_RD FLASH Read Protection error (PCROP)
593   *            @arg @ref HAL_FLASH_ERROR_OPTV FLASH Option validity error
594   */
HAL_FLASH_GetError(void)595 uint32_t HAL_FLASH_GetError(void)
596 {
597   return pFlash.ErrorCode;
598 }
599 
600 /**
601   * @}
602   */
603 
604 /**
605   * @}
606   */
607 
608 /* Private functions ---------------------------------------------------------*/
609 
610 /** @addtogroup FLASH_Private_Functions
611   * @{
612   */
613 
614 /**
615   * @brief  Wait for a FLASH operation to complete.
616   * @param  Timeout Maximum flash operation timeout
617   * @retval HAL_StatusTypeDef HAL Status
618   */
FLASH_WaitForLastOperation(uint32_t Timeout)619 HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout)
620 {
621   uint32_t error;
622   uint32_t tickstart = HAL_GetTick();
623 
624   /* Wait for the FLASH operation to complete by polling on BUSY flag to be reset.
625      Even if the FLASH operation fails, the BUSY flag will be reset and an error
626      flag will be set */
627   while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY))
628   {
629     if ((HAL_GetTick() - tickstart) >= Timeout)
630     {
631       return HAL_TIMEOUT;
632     }
633   }
634 
635   /* check flash errors. Only ECC correction can be checked here as ECCD
636       generates NMI */
637 #ifdef CORE_CM0PLUS
638   error = FLASH->C2SR;
639 #else
640   error = FLASH->SR;
641 #endif
642 
643   /* Check FLASH End of Operation flag */
644   if ((error & FLASH_FLAG_EOP) != 0U)
645   {
646     /* Clear FLASH End of Operation pending bit */
647     __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
648   }
649 
650   /* Now update error variable to only error value */
651   error &= FLASH_FLAG_SR_ERRORS;
652 
653   /* clear error flags */
654   __HAL_FLASH_CLEAR_FLAG(error);
655 
656   if (error != 0U)
657   {
658     /*Save the error code*/
659     pFlash.ErrorCode = error;
660 
661     return HAL_ERROR;
662   }
663 
664   /* Wait for control register to be written */
665   while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_CFGBSY))
666   {
667     if ((HAL_GetTick() - tickstart) >= Timeout)
668     {
669       return HAL_TIMEOUT;
670     }
671   }
672 
673   return HAL_OK;
674 }
675 
676 /**
677   * @brief  Program double-word (64-bit) at a specified address.
678   * @param  Address Specifies the address to be programmed.
679   * @param  Data Specifies the data to be programmed.
680   * @retval None
681   */
FLASH_Program_DoubleWord(uint32_t Address,uint64_t Data)682 static void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data)
683 {
684 #ifdef CORE_CM0PLUS
685   /* Set PG bit */
686   SET_BIT(FLASH->C2CR, FLASH_CR_PG);
687 #else
688   /* Set PG bit */
689   SET_BIT(FLASH->CR, FLASH_CR_PG);
690 #endif
691 
692   /* Program first word */
693   *(uint32_t *)Address = (uint32_t)Data;
694 
695   /* Barrier to ensure programming is performed in 2 steps, in right order
696     (independently of compiler optimization behavior) */
697   __ISB();
698 
699   /* Program second word */
700   *(uint32_t *)(Address + 4U) = (uint32_t)(Data >> 32U);
701 }
702 
703 /**
704   * @brief  Fast program a 32 row double-word (64-bit) at a specified address.
705   * @param  Address Specifies the address to be programmed.
706   * @param  DataAddress Specifies the address where the data are stored.
707   * @retval None
708   */
709 #ifdef CORE_CM0PLUS
FLASH_Program_Fast(uint32_t Address,uint32_t DataAddress)710 static __RAM_FUNC void FLASH_Program_Fast(uint32_t Address, uint32_t DataAddress)
711 #else
712 static void FLASH_Program_Fast(uint32_t Address, uint32_t DataAddress)
713 #endif
714 {
715   uint8_t row_index = (2 * FLASH_NB_DOUBLE_WORDS_IN_ROW);
716   __IO uint32_t *dest_addr = (__IO uint32_t *)Address;
717   __IO uint32_t *src_addr = (__IO uint32_t *)DataAddress;
718   uint32_t primask_bit;
719 
720   /* Set FSTPG bit */
721 #ifdef CORE_CM0PLUS
722   SET_BIT(FLASH->C2CR, FLASH_CR_FSTPG);
723 #else
724   SET_BIT(FLASH->CR, FLASH_CR_FSTPG);
725 #endif
726 
727   /* Enter critical section: row programming should not be longer than 7 ms */
728   primask_bit = __get_PRIMASK();
729   __disable_irq();
730 
731   /* Program the double word of the row */
732   do
733   {
734     *dest_addr = *src_addr;
735     dest_addr++;
736     src_addr++;
737     row_index--;
738   }
739   while (row_index != 0U);
740 
741   /* wait for BSY in order to be sure that flash operation is ended before
742      allowing prefetch in flash. Timeout does not return status, as it will
743      be anyway done later */
744   while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY) != 0U)
745   {
746   }
747 
748   /* Exit critical section: restore previous priority mask */
749   __set_PRIMASK(primask_bit);
750 }
751 
752 /**
753   * @}
754   */
755 
756 #endif /* HAL_FLASH_MODULE_ENABLED */
757 
758 /**
759   * @}
760   */
761 
762 /**
763   * @}
764   */
765 
766