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