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