1 /**
2   ******************************************************************************
3   * @file    stm32h7rsxx_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 to the Flash memory.
18        It implements the erase and program Flash memory operations and the read
19        and write protection mechanisms.
20 
21   [..] The FLASH main features are:
22       (+) Flash memory read operations
23       (+) Flash memory program/erase operations
24       (+) Read / write protections
25       (+) Option bytes programming
26       (+) Error code correction (ECC) : Data in flash are 137-bits word
27           (9 bits added per quad-word)
28 
29                         ##### How to use this driver #####
30  ==============================================================================
31     [..]
32       This driver provides functions and macros to configure and program the FLASH
33       memory of all STM32H7RSxx devices.
34 
35       (#) Flash Memory IO Programming functions:
36         (++) Lock and Unlock the FLASH interface using HAL_FLASH_Unlock() and
37              HAL_FLASH_Lock() functions
38         (++) Program functions: bytes, half-words, words, double-words and quad-words
39         (++) There are two modes of programming :
40           (+++) Polling mode using HAL_FLASH_Program() function
41           (+++) Interrupt mode using HAL_FLASH_Program_IT() function
42 
43       (#) Interrupts and flags management functions :
44         (++) Handle FLASH interrupts by calling HAL_FLASH_IRQHandler()
45         (++) Callback functions are called when the flash operations are finished :
46              HAL_FLASH_EndOfOperationCallback() when everything is ok, otherwise
47              HAL_FLASH_OperationErrorCallback()
48         (++) Get error flag status by calling HAL_GetError()
49 
50       (#) Option bytes management functions :
51         (++) Lock and Unlock the option bytes using HAL_FLASH_OB_Unlock() and
52              HAL_FLASH_OB_Lock() functions
53         (++) Launch the reload of the option bytes using HAL_FLASH_Launch() function.
54              In this case, a reset is generated
55 
56     [..]
57       In addition to these functions, this driver includes a set of macros allowing
58       to handle the following operations:
59        (+) Set the latency
60        (+) Enable/Disable the Flash interrupts
61        (+) Monitor the Flash flags status
62 
63  @endverbatim
64   ******************************************************************************
65   * @attention
66   *
67   * Copyright (c) 2022 STMicroelectronics.
68   * All rights reserved.
69   *
70   * This software is licensed under terms that can be found in the LICENSE file
71   * in the root directory of this software component.
72   * If no LICENSE file comes with this software, it is provided AS-IS.
73   *
74   ******************************************************************************
75   */
76 
77 /* Includes ------------------------------------------------------------------*/
78 #include "stm32h7rsxx_hal.h"
79 
80 /** @addtogroup STM32H7RSxx_HAL_Driver
81   * @{
82   */
83 
84 /** @defgroup FLASH FLASH
85   * @brief FLASH HAL module driver
86   * @{
87   */
88 
89 #ifdef HAL_FLASH_MODULE_ENABLED
90 
91 /* Private typedef -----------------------------------------------------------*/
92 /* Private defines -----------------------------------------------------------*/
93 
94 /* Private macros ------------------------------------------------------------*/
95 /* Private variables ---------------------------------------------------------*/
96 /** @defgroup FLASH_Private_Variables FLASH Private Variables
97   * @{
98   */
99 /**
100   * @brief  Variable used for Program/Erase sectors under interruption
101   */
102 FLASH_ProcessTypeDef pFlash = {.Lock = HAL_UNLOCKED, \
103                                .ErrorCode = HAL_FLASH_ERROR_NONE, \
104                                .ProcedureOnGoing = 0U, \
105                                .Address = 0U, \
106                                .Sector = 0U, \
107                                .NbSectorsToErase = 0U
108                               };
109 /**
110   * @}
111   */
112 
113 /* Private function prototypes -----------------------------------------------*/
114 /** @defgroup FLASH_Private_Functions FLASH Private Functions
115   * @{
116   */
117 static void FLASH_Program_Byte(uint32_t Address, uint32_t DataAddress);
118 static void FLASH_Program_HalfWord(uint32_t Address, uint32_t DataAddress);
119 static void FLASH_Program_Word(uint32_t Address, uint32_t DataAddress);
120 static void FLASH_Program_DoubleWord(uint32_t Address, uint32_t DataAddress);
121 static void FLASH_Program_QuadWord(uint32_t Address, uint32_t DataAddress);
122 static void FLASH_Program_OTPHalfWord(uint32_t Address, uint32_t DataAddress);
123 static void FLASH_Program_OTPWord(uint32_t Address, uint32_t DataAddress);
124 /**
125   * @}
126   */
127 
128 /* Exported functions --------------------------------------------------------*/
129 /** @defgroup FLASH_Exported_Functions FLASH Exported Functions
130   * @{
131   */
132 
133 /** @defgroup FLASH_Exported_Functions_Group1 Programming operation functions
134   *  @brief   Programming operation functions
135   *
136 @verbatim
137  ===============================================================================
138                   ##### Programming operation functions #####
139  ===============================================================================
140     [..]
141     This subsection provides a set of functions allowing to manage the FLASH
142     program operations.
143 
144 @endverbatim
145   * @{
146   */
147 
148 /**
149   * @brief  Program a data at a specified address.
150   * @param  TypeProgram  Indicate the way to program at a specified address.
151   *                      This parameter can be a value of @ref FLASH_Type_Program
152   * @param  Address  specifies the address to be programmed.
153   * @param  DataAddress specifies the address of data to be programmed.
154   *
155   * @retval HAL Status
156   */
HAL_FLASH_Program(uint32_t TypeProgram,uint32_t Address,uint32_t DataAddress)157 HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint32_t DataAddress)
158 {
159   HAL_StatusTypeDef status;
160 
161   /* Check the parameters */
162   assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
163 
164   /* Process Locked */
165   __HAL_LOCK(&pFlash);
166 
167   /* Reset error code */
168   pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
169 
170   /* Wait for last operation to be completed */
171   status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
172 
173   if (status == HAL_OK)
174   {
175     switch (TypeProgram)
176     {
177       case FLASH_TYPEPROGRAM_BYTE:
178         /* Program a byte (8-bit) at a specified address */
179         FLASH_Program_Byte(Address, DataAddress);
180         break;
181 
182       case FLASH_TYPEPROGRAM_HALFWORD:
183         /* Program a half-word (16-bit) at a specified address */
184         FLASH_Program_HalfWord(Address, DataAddress);
185         break;
186 
187       case FLASH_TYPEPROGRAM_WORD:
188         /* Program a word (32-bit) at a specified address */
189         FLASH_Program_Word(Address, DataAddress);
190         break;
191 
192       case FLASH_TYPEPROGRAM_DOUBLEWORD:
193         /* Program a double-word (64-bit) at a specified address */
194         FLASH_Program_DoubleWord(Address, DataAddress);
195         break;
196 
197       case FLASH_TYPEPROGRAM_QUADWORD:
198         /* Program a quad-word (128-bit) at a specified address */
199         FLASH_Program_QuadWord(Address, DataAddress);
200         break;
201 
202       case FLASH_TYPEPROGRAM_OTP_HALFWORD:
203         /* Program a half-word (16-bit) at a OTP address */
204         FLASH_Program_OTPHalfWord(Address, DataAddress);
205         break;
206 
207       case FLASH_TYPEPROGRAM_OTP_WORD:
208         /* Program a word (32-bit) at a OTP address */
209         FLASH_Program_OTPWord(Address, DataAddress);
210         break;
211 
212       default:
213         status = HAL_ERROR;
214         break;
215     }
216 
217     if (status != HAL_ERROR)
218     {
219       /* Wait for last operation to be completed */
220       status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
221 
222       /* If the program operation is completed, disable the PG (and FW Bit in non quad-word mode) */
223       CLEAR_BIT(FLASH->CR, (TypeProgram & ~(FLASH_WORD_SIZE_MASK)));
224     }
225   }
226 
227   /* Process Unlocked */
228   __HAL_UNLOCK(&pFlash);
229 
230   /* return status */
231   return status;
232 }
233 
234 /**
235   * @brief  Program a data at a specified address with interrupt enabled.
236   * @param  TypeProgram  Indicate the way to program at a specified address.
237   *                      This parameter can be a value of @ref FLASH_Type_Program
238   * @param  Address  specifies the address to be programmed.
239   * @param  DataAddress specifies the address of data to be programmed
240   *
241   * @retval HAL Status
242   */
HAL_FLASH_Program_IT(uint32_t TypeProgram,uint32_t Address,uint32_t DataAddress)243 HAL_StatusTypeDef HAL_FLASH_Program_IT(uint32_t TypeProgram, uint32_t Address, uint32_t DataAddress)
244 {
245   HAL_StatusTypeDef status;
246 
247   /* Check the parameters */
248   assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
249 
250   /* Process Locked */
251   __HAL_LOCK(&pFlash);
252 
253   /* Reset error code */
254   pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
255 
256   /* Wait for last operation to be completed */
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     SET_BIT(FLASH->IER, (FLASH_IT_EOP | FLASH_IT_WRPERR | FLASH_IT_PGSERR | FLASH_IT_STRBERR | FLASH_IT_INCERR));
272 
273     switch (TypeProgram)
274     {
275       case FLASH_TYPEPROGRAM_BYTE:
276         /* Program a byte (8-bit) at a specified address */
277         FLASH_Program_Byte(Address, DataAddress);
278         break;
279 
280       case FLASH_TYPEPROGRAM_HALFWORD:
281         /* Program a half-word (16-bit) at a specified address */
282         FLASH_Program_HalfWord(Address, DataAddress);
283         break;
284 
285       case FLASH_TYPEPROGRAM_WORD:
286         /* Program a word (32-bit) at a specified address */
287         FLASH_Program_Word(Address, DataAddress);
288         break;
289 
290       case FLASH_TYPEPROGRAM_DOUBLEWORD:
291         /* Program a double-word (64-bit) at a specified address */
292         FLASH_Program_DoubleWord(Address, DataAddress);
293         break;
294 
295       case FLASH_TYPEPROGRAM_QUADWORD:
296         /* Program a quad-word (128-bit) at a specified address */
297         FLASH_Program_QuadWord(Address, DataAddress);
298         break;
299 
300       case FLASH_TYPEPROGRAM_OTP_HALFWORD:
301         /* Program a half-word (16-bit) at a OTP address */
302         FLASH_Program_OTPHalfWord(Address, DataAddress);
303         break;
304 
305       case FLASH_TYPEPROGRAM_OTP_WORD:
306         /* Program a word (32-bit) at a OTP address */
307         FLASH_Program_OTPWord(Address, DataAddress);
308         break;
309 
310       default:
311         status = HAL_ERROR;
312 
313         /* Process Unlocked */
314         __HAL_UNLOCK(&pFlash);
315         break;
316     }
317   }
318 
319   return status;
320 }
321 
322 /**
323   * @brief  Handle FLASH interrupt request.
324   * @retval None
325   */
HAL_FLASH_IRQHandler(void)326 void HAL_FLASH_IRQHandler(void)
327 {
328   uint32_t param = 0U;
329   uint32_t error;
330 
331   /* Save Flash errors */
332   error = FLASH->ISR & FLASH_FLAG_ISR_ERRORS;
333   error |= (FLASH->OPTISR & FLASH_FLAG_OPTISR_ERRORS);
334 
335   /* Set parameter of the callback */
336   if (pFlash.ProcedureOnGoing == FLASH_TYPEERASE_SECTORS)
337   {
338     param = pFlash.Sector;
339   }
340   else if ((pFlash.ProcedureOnGoing & FLASH_CR_PG) != 0U)
341   {
342     param = pFlash.Address;
343   }
344   else
345   {
346     /* Empty statement (to be compliant MISRA 15.7) */
347   }
348 
349   /* Clear operation bit on the on-going procedure */
350   CLEAR_BIT(FLASH->CR, (pFlash.ProcedureOnGoing & ~(FLASH_WORD_SIZE_MASK)));
351 
352   /* Check FLASH operation error flags */
353   if (error != 0U)
354   {
355     /* Save the error code */
356     pFlash.ErrorCode |= error;
357 
358     /* Clear error programming flags */
359     FLASH->ICR = (error & FLASH_FLAG_ISR_ERRORS);
360     FLASH->OPTICR = (error & FLASH_FLAG_OPTISR_ERRORS);
361 
362     /* Stop the procedure ongoing */
363     pFlash.ProcedureOnGoing = 0U;
364 
365     /* FLASH error interrupt user callback */
366     HAL_FLASH_OperationErrorCallback(param);
367   }
368 
369   /* Check FLASH End of Operation flag  */
370   if ((FLASH->ISR & FLASH_FLAG_EOP) != 0U)
371   {
372     /* Clear FLASH End of Operation pending bit */
373     FLASH->ICR = FLASH_FLAG_EOP;
374 
375     if (pFlash.ProcedureOnGoing == FLASH_TYPEERASE_SECTORS)
376     {
377       /* Nb of sectors to erase can be decreased */
378       pFlash.NbSectorsToErase--;
379 
380       /* Check if there are still sectors to erase */
381       if (pFlash.NbSectorsToErase != 0U)
382       {
383         /* Increment sector number */
384         pFlash.Sector++;
385         FLASH_SectorErase(pFlash.Sector);
386       }
387       else
388       {
389         /* No more sectors to Erase */
390         pFlash.ProcedureOnGoing = 0U;
391         param = 0xFFFFFFFFU;
392       }
393     }
394     else
395     {
396       /*Clear the procedure ongoing*/
397       pFlash.ProcedureOnGoing = 0U;
398     }
399 
400     /* FLASH EOP interrupt user callback */
401     HAL_FLASH_EndOfOperationCallback(param);
402   }
403 
404   if (pFlash.ProcedureOnGoing == 0U)
405   {
406     /* Disable End of Operation and Error interrupts */
407     CLEAR_BIT(FLASH->IER, (FLASH_IT_EOP | FLASH_IT_WRPERR | FLASH_IT_PGSERR | FLASH_IT_STRBERR | FLASH_IT_INCERR));
408 
409     /* Process Unlocked */
410     __HAL_UNLOCK(&pFlash);
411   }
412 
413   /* Check ECC Correction Error */
414   if ((FLASH->IER & FLASH_IT_SNECCERR) != 0U)
415   {
416     if ((FLASH->ISR & FLASH_FLAG_SNECCERR) != 0U)
417     {
418       /* Call User callback */
419       HAL_FLASHEx_EccCorrectionCallback();
420 
421       /* Clear ECC correction flag in order to allow new ECC error record */
422       FLASH->ICR = FLASH_FLAG_SNECCERR;
423     }
424   }
425 
426   /* Check ECC Detection Error */
427   if ((FLASH->IER & FLASH_IT_DBECCERR) != 0U)
428   {
429     if ((FLASH->ISR & FLASH_FLAG_DBECCERR) != 0U)
430     {
431       /* Call User callback */
432       HAL_FLASHEx_EccDetectionCallback();
433 
434       /* Clear ECC detection flag in order to allow new ECC error record */
435       FLASH->ICR = FLASH_FLAG_DBECCERR;
436     }
437   }
438 }
439 
440 /**
441   * @brief  FLASH end of operation interrupt callback.
442   * @param  ReturnValue The value saved in this parameter depends on the ongoing procedure
443   *                  Mass Erase: Bank number which has been requested to erase
444   *                  Sector Erase: Sector which has been erased
445   *                    (if 0xFFFFFFFF, it means that all the selected sectors have been erased)
446   *                  Program: Address which was selected for data program
447   * @retval None
448   */
HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue)449 __weak void HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue)
450 {
451   /* Prevent unused argument(s) compilation warning */
452   UNUSED(ReturnValue);
453 
454   /* NOTE : This function should not be modified, when the callback is needed,
455             the HAL_FLASH_EndOfOperationCallback could be implemented in the user file
456    */
457 }
458 
459 /**
460   * @brief  FLASH operation error interrupt callback.
461   * @param  ReturnValue The value saved in this parameter depends on the ongoing procedure
462   *                 Mass Erase: Bank number which has been requested to erase
463   *                 Sector Erase: Sector number which returned an error
464   *                 Program: Address which was selected for data program
465   * @retval None
466   */
HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue)467 __weak void HAL_FLASH_OperationErrorCallback(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_OperationErrorCallback could be implemented in the user file
474    */
475 }
476 
477 /**
478   * @}
479   */
480 
481 /** @defgroup FLASH_Exported_Functions_Group2 Peripheral Control functions
482   *  @brief   Management functions
483   *
484 @verbatim
485  ===============================================================================
486                       ##### Peripheral Control functions #####
487  ===============================================================================
488     [..]
489     This subsection provides a set of functions allowing to control the FLASH
490     memory operations.
491 
492 @endverbatim
493   * @{
494   */
495 
496 /**
497   * @brief  Unlock the FLASH control register access.
498   * @retval HAL Status
499   */
HAL_FLASH_Unlock(void)500 HAL_StatusTypeDef HAL_FLASH_Unlock(void)
501 {
502   if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0U)
503   {
504     /* Authorize the FLASH Registers access */
505     WRITE_REG(FLASH->KEYR, FLASH_KEY1);
506     WRITE_REG(FLASH->KEYR, FLASH_KEY2);
507 
508     /* verify Flash is unlocked */
509     if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0U)
510     {
511       return HAL_ERROR;
512     }
513   }
514 
515   return HAL_OK;
516 }
517 
518 /**
519   * @brief  Lock the FLASH control register access.
520   * @retval HAL Status
521   */
HAL_FLASH_Lock(void)522 HAL_StatusTypeDef HAL_FLASH_Lock(void)
523 {
524   /* Set the LOCK Bit to lock the FLASH Registers access */
525   SET_BIT(FLASH->CR, FLASH_CR_LOCK);
526 
527   /* verify Flash is locked */
528   if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0U)
529   {
530     return HAL_OK;
531   }
532 
533   return HAL_ERROR;
534 }
535 
536 /**
537   * @brief  Unlock the FLASH Option Bytes Registers access.
538   * @retval HAL Status
539   */
HAL_FLASH_OB_Unlock(void)540 HAL_StatusTypeDef HAL_FLASH_OB_Unlock(void)
541 {
542   if (READ_BIT(FLASH->OPTCR, FLASH_OPTCR_OPTLOCK) != 0U)
543   {
544     /* Authorizes the Option Byte register programming */
545     WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY1);
546     WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY2);
547 
548     /* Verify that the Option Bytes are unlocked */
549     if (READ_BIT(FLASH->OPTCR, FLASH_OPTCR_OPTLOCK) != 0U)
550     {
551       return HAL_ERROR;
552     }
553   }
554 
555   return HAL_OK;
556 }
557 
558 /**
559   * @brief  Lock the FLASH Option Bytes Registers access.
560   * @retval HAL Status
561   */
HAL_FLASH_OB_Lock(void)562 HAL_StatusTypeDef HAL_FLASH_OB_Lock(void)
563 {
564   /* Set the OPTLOCK Bit to lock the FLASH Option Byte Registers access */
565   SET_BIT(FLASH->OPTCR, FLASH_OPTCR_OPTLOCK);
566 
567   /* Verify that the Option Bytes are locked */
568   if (READ_BIT(FLASH->OPTCR, FLASH_OPTCR_OPTLOCK) != 0U)
569   {
570     return HAL_OK;
571   }
572 
573   return HAL_ERROR;
574 }
575 
576 /**
577   * @}
578   */
579 
580 /** @defgroup FLASH_Exported_Functions_Group3 Peripheral State and Errors functions
581   *  @brief   Peripheral Errors functions
582   *
583 @verbatim
584  ===============================================================================
585                 ##### Peripheral Errors functions #####
586  ===============================================================================
587     [..]
588     This subsection permits to get in run-time Errors of the FLASH peripheral.
589 
590 @endverbatim
591   * @{
592   */
593 
594 /**
595   * @brief  Get the specific FLASH error flag.
596   * @retval FLASH_ErrorCode The returned value can be:
597   *            @arg HAL_FLASH_ERROR_NONE: No error set
598   *            @arg HAL_FLASH_ERROR_WRP: FLASH Write protection error
599   *            @arg HAL_FLASH_ERROR_PGS: FLASH Programming sequence error
600   *            @arg HAL_FLASH_ERROR_STRB: FLASH Strobe error
601   *            @arg HAL_FLASH_ERROR_INC: FLASH Inconsistency error
602   *            @arg HAL_FLASH_ERROR_RDS: FLASH Read security error
603   *            @arg HAL_FLASH_ERROR_SNECC: FLASH ECC single error
604   *            @arg HAL_FLASH_ERROR_DBECC: FLASH ECC double error
605   *            @arg HAL_FLASH_ERROR_CRC: FLASH CRC error
606   *            @arg HAL_FLASH_ERROR_KDR: FLASH Key data register error
607   *            @arg HAL_FLASH_ERROR_OBC: FLASH Options byte change error
608   */
HAL_FLASH_GetError(void)609 uint32_t HAL_FLASH_GetError(void)
610 {
611   return pFlash.ErrorCode;
612 }
613 
614 /**
615   * @}
616   */
617 
618 /**
619   * @}
620   */
621 
622 /* Private functions ---------------------------------------------------------*/
623 
624 /** @addtogroup FLASH_Private_Functions
625   * @{
626   */
627 
628 /**
629   * @brief  Wait for a FLASH operation to complete.
630   * @param  Timeout maximum flash operation timeout
631   * @retval HAL Status
632   */
FLASH_WaitForLastOperation(uint32_t Timeout)633 HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout)
634 {
635   /* Wait for the FLASH operation to complete by polling on BUSY flag to be reset.
636      Even if the FLASH operation fails, the BUSY flag will be reset and an error
637      flag will be set */
638 
639   uint32_t timeout = HAL_GetTick() + Timeout;
640   uint32_t error;
641 
642   while ((FLASH->SR & FLASH_SR_QW) != 0U)
643   {
644     if (Timeout != HAL_MAX_DELAY)
645     {
646       if (HAL_GetTick() >= timeout)
647       {
648         return HAL_TIMEOUT;
649       }
650     }
651   }
652 
653   /* Check FLASH operation error flags */
654   error = (FLASH->ISR & FLASH_FLAG_ISR_ERRORS);
655   error |= (FLASH->OPTISR & FLASH_FLAG_OPTISR_ERRORS);
656 
657   if (error != 0U)
658   {
659     /*Save the error code*/
660     pFlash.ErrorCode |= error;
661 
662     /* Clear error programming flags */
663     FLASH->ICR = (error & FLASH_FLAG_ISR_ERRORS);
664     FLASH->OPTICR = (error & FLASH_FLAG_OPTISR_ERRORS);
665 
666     return HAL_ERROR;
667   }
668 
669   /* Check FLASH End of Operation flag  */
670   if ((FLASH->ISR & FLASH_FLAG_EOP) != 0U)
671   {
672     /* Clear FLASH End of Operation pending bit */
673     FLASH->ICR = FLASH_FLAG_EOP;
674   }
675 
676   /* If there is no error flag set */
677   return HAL_OK;
678 }
679 
680 /**
681   * @brief  Program a byte (8-bit) at a specified address.
682   * @param  Address specifies the address to be programmed.
683   * @param  DataAddress specifies the address of data to be programmed.
684   * @retval None
685   */
FLASH_Program_Byte(uint32_t Address,uint32_t DataAddress)686 static void FLASH_Program_Byte(uint32_t Address, uint32_t DataAddress)
687 {
688   uint8_t *dest_addr = (uint8_t *)Address;
689   uint8_t *src_addr  = (uint8_t *)DataAddress;
690   uint32_t primask_bit;
691 
692   /* Check the parameters */
693   assert_param(IS_FLASH_MAIN_MEM_ADDRESS(Address));
694 
695   /* Set PG bit */
696   SET_BIT(FLASH->CR, FLASH_CR_PG);
697 
698   /* Enter critical section: Disable interrupts to avoid any interruption during the loop */
699   primask_bit = __get_PRIMASK();
700   __disable_irq();
701 
702   /* Program the byte */
703   *dest_addr = *src_addr;
704 
705   __ISB();
706   __DSB();
707 
708   /* Set FW bit */
709   SET_BIT(FLASH->CR, FLASH_CR_FW);
710 
711   /* Exit critical section: restore previous priority mask */
712   __set_PRIMASK(primask_bit);
713 }
714 
715 /**
716   * @brief  Program a half-word (16-bit) at a specified address.
717   * @param  Address specifies the address to be programmed.
718   * @param  DataAddress specifies the address of data to be programmed.
719   * @retval None
720   */
FLASH_Program_HalfWord(uint32_t Address,uint32_t DataAddress)721 static void FLASH_Program_HalfWord(uint32_t Address, uint32_t DataAddress)
722 {
723   uint16_t *dest_addr = (uint16_t *)Address;
724   uint16_t *src_addr  = (uint16_t *)DataAddress;
725   uint32_t primask_bit;
726 
727   /* Check the parameters */
728   assert_param(IS_FLASH_MAIN_MEM_ADDRESS(Address));
729 
730   /* Set PG bit */
731   SET_BIT(FLASH->CR, FLASH_CR_PG);
732 
733   /* Enter critical section: Disable interrupts to avoid any interruption during the loop */
734   primask_bit = __get_PRIMASK();
735   __disable_irq();
736 
737   /* Program the half-word */
738   *dest_addr = *src_addr;
739 
740   __ISB();
741   __DSB();
742 
743   /* Set FW bit */
744   SET_BIT(FLASH->CR, FLASH_CR_FW);
745 
746   /* Exit critical section: restore previous priority mask */
747   __set_PRIMASK(primask_bit);
748 }
749 
750 /**
751   * @brief  Program a word (32-bit) at a specified address.
752   * @param  Address specifies the address to be programmed.
753   * @param  DataAddress specifies the address of data to be programmed.
754   * @retval None
755   */
FLASH_Program_Word(uint32_t Address,uint32_t DataAddress)756 static void FLASH_Program_Word(uint32_t Address, uint32_t DataAddress)
757 {
758   uint8_t index = 2;
759   uint16_t *dest_addr = (uint16_t *)Address;
760   uint16_t *src_addr  = (uint16_t *)DataAddress;
761   uint32_t primask_bit;
762 
763   /* Check the parameters */
764   assert_param(IS_FLASH_MAIN_MEM_ADDRESS(Address));
765 
766   /* Set PG bit */
767   SET_BIT(FLASH->CR, FLASH_CR_PG);
768 
769   /* Enter critical section: Disable interrupts to avoid any interruption during the loop */
770   primask_bit = __get_PRIMASK();
771   __disable_irq();
772 
773   /* Program the word */
774   do
775   {
776     *dest_addr = *src_addr;
777     dest_addr++;
778     src_addr++;
779     index--;
780   } while (index != 0U);
781 
782   __ISB();
783   __DSB();
784 
785   /* Set FW bit */
786   SET_BIT(FLASH->CR, FLASH_CR_FW);
787 
788   /* Exit critical section: restore previous priority mask */
789   __set_PRIMASK(primask_bit);
790 }
791 
792 /**
793   * @brief  Program a double-word (64-bit) at a specified address.
794   * @param  Address specifies the address to be programmed.
795   * @param  DataAddress specifies the address of data to be programmed.
796   * @retval None
797   */
FLASH_Program_DoubleWord(uint32_t Address,uint32_t DataAddress)798 static void FLASH_Program_DoubleWord(uint32_t Address, uint32_t DataAddress)
799 {
800   uint8_t index = 4;
801   uint16_t *dest_addr = (uint16_t *)Address;
802   uint16_t *src_addr  = (uint16_t *)DataAddress;
803   uint32_t primask_bit;
804 
805   /* Check the parameters */
806   assert_param(IS_FLASH_MAIN_MEM_ADDRESS(Address));
807 
808   /* Set PG bit */
809   SET_BIT(FLASH->CR, FLASH_CR_PG);
810 
811   /* Enter critical section: Disable interrupts to avoid any interruption during the loop */
812   primask_bit = __get_PRIMASK();
813   __disable_irq();
814 
815   /* Program the double-word */
816   do
817   {
818     *dest_addr = *src_addr;
819     dest_addr++;
820     src_addr++;
821     index--;
822   } while (index != 0U);
823 
824   __ISB();
825   __DSB();
826 
827   /* Set FW bit */
828   SET_BIT(FLASH->CR, FLASH_CR_FW);
829 
830   /* Exit critical section: restore previous priority mask */
831   __set_PRIMASK(primask_bit);
832 }
833 
834 /**
835   * @brief  Program a quad-word (128-bit) at a specified address.
836   * @param  Address specifies the address to be programmed.
837   * @param  DataAddress specifies the address of data to be programmed.
838   * @retval None
839   */
FLASH_Program_QuadWord(uint32_t Address,uint32_t DataAddress)840 static void FLASH_Program_QuadWord(uint32_t Address, uint32_t DataAddress)
841 {
842   uint8_t index = 8;
843   uint16_t *dest_addr = (uint16_t *)Address;
844   uint16_t *src_addr  = (uint16_t *)DataAddress;
845   uint32_t primask_bit;
846 
847   /* Check the parameters */
848   assert_param(IS_FLASH_MAIN_MEM_ADDRESS(Address));
849 
850   /* Set PG bit */
851   SET_BIT(FLASH->CR, FLASH_CR_PG);
852 
853   /* Enter critical section: Disable interrupts to avoid any interruption during the loop */
854   primask_bit = __get_PRIMASK();
855   __disable_irq();
856 
857   /* Program the quad-word */
858   do
859   {
860     *dest_addr = *src_addr;
861     dest_addr++;
862     src_addr++;
863     index--;
864   } while (index != 0U);
865 
866   __ISB();
867   __DSB();
868 
869   /* Exit critical section: restore previous priority mask */
870   __set_PRIMASK(primask_bit);
871 }
872 
873 /**
874   * @brief  Program a half-word (16-bit) at a OTP address.
875   * @param  Address specifies the address to be programmed.
876   * @param  DataAddress specifies the address of data to be programmed.
877   * @retval None
878   */
FLASH_Program_OTPHalfWord(uint32_t Address,uint32_t DataAddress)879 static void FLASH_Program_OTPHalfWord(uint32_t Address, uint32_t DataAddress)
880 {
881   uint16_t *dest_addr = (uint16_t *)Address;
882   uint16_t *src_addr  = (uint16_t *)DataAddress;
883   uint32_t primask_bit;
884 
885   /* Check the parameters */
886   assert_param(IS_FLASH_OTP_ADDRESS(Address));
887 
888   /* Set PG_OTP bit */
889   SET_BIT(FLASH->CR, FLASH_CR_PG_OTP);
890 
891   /* Enter critical section: Disable interrupts to avoid any interruption during the loop */
892   primask_bit = __get_PRIMASK();
893   __disable_irq();
894 
895   /* Program the half-word */
896   *dest_addr = *src_addr;
897 
898   __ISB();
899   __DSB();
900 
901   /* Set FW bit */
902   SET_BIT(FLASH->CR, FLASH_CR_FW);
903 
904   /* Exit critical section: restore previous priority mask */
905   __set_PRIMASK(primask_bit);
906 }
907 
908 /**
909   * @brief  Program a word (32-bit) at a OTP address.
910   * @param  Address specifies the address to be programmed.
911   * @param  DataAddress specifies the address of data to be programmed.
912   * @retval None
913   */
FLASH_Program_OTPWord(uint32_t Address,uint32_t DataAddress)914 static void FLASH_Program_OTPWord(uint32_t Address, uint32_t DataAddress)
915 {
916   uint8_t index = 2;
917   uint16_t *dest_addr = (uint16_t *)Address;
918   uint16_t *src_addr  = (uint16_t *)DataAddress;
919   uint32_t primask_bit;
920 
921   /* Check the parameters */
922   assert_param(IS_FLASH_OTP_ADDRESS(Address));
923 
924   /* Set PG_OTP bit */
925   SET_BIT(FLASH->CR, FLASH_CR_PG_OTP);
926 
927   /* Enter critical section: Disable interrupts to avoid any interruption during the loop */
928   primask_bit = __get_PRIMASK();
929   __disable_irq();
930 
931   /* Program the word */
932   do
933   {
934     *dest_addr = *src_addr;
935     dest_addr++;
936     src_addr++;
937     index--;
938   } while (index != 0U);
939 
940   __ISB();
941   __DSB();
942 
943   /* Set FW bit */
944   SET_BIT(FLASH->CR, FLASH_CR_FW);
945 
946   /* Exit critical section: restore previous priority mask */
947   __set_PRIMASK(primask_bit);
948 }
949 
950 /**
951   * @}
952   */
953 
954 #endif /* HAL_FLASH_MODULE_ENABLED */
955 
956 /**
957   * @}
958   */
959 
960 /**
961   * @}
962   */
963