1 /**
2   ******************************************************************************
3   * @file    stm32f0xx_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 State functions
11   *
12   @verbatim
13   ==============================================================================
14                         ##### FLASH peripheral features #####
15   ==============================================================================
16   [..] The Flash memory interface manages CPU AHB I-Code and D-Code accesses
17        to the Flash memory. It implements the erase and program Flash memory operations
18        and the read and write protection mechanisms.
19 
20   [..] The Flash memory interface accelerates code execution with a system of instruction
21       prefetch.
22 
23   [..] The FLASH main features are:
24       (+) Flash memory read operations
25       (+) Flash memory program/erase operations
26       (+) Read / write protections
27       (+) Prefetch on I-Code
28       (+) Option Bytes programming
29 
30 
31                      ##### How to use this driver #####
32   ==============================================================================
33   [..]
34       This driver provides functions and macros to configure and program the FLASH
35       memory of all STM32F0xx devices.
36 
37       (#) FLASH Memory I/O Programming functions: this group includes all needed
38           functions to erase and program the main memory:
39         (++) Lock and Unlock the FLASH interface
40         (++) Erase function: Erase page, erase all pages
41         (++) Program functions: half word, word and doubleword
42       (#) FLASH Option Bytes Programming functions: this group includes all needed
43           functions to manage the Option Bytes:
44         (++) Lock and Unlock the Option Bytes
45         (++) Set/Reset the write protection
46         (++) Set the Read protection Level
47         (++) Program the user Option Bytes
48         (++) Launch the Option Bytes loader
49         (++) Erase Option Bytes
50         (++) Program the data Option Bytes
51         (++) Get the Write protection.
52         (++) Get the user option bytes.
53 
54       (#) Interrupts and flags management functions : this group
55           includes all needed functions to:
56         (++) Handle FLASH interrupts
57         (++) Wait for last FLASH operation according to its status
58         (++) Get error flag status
59 
60   [..] In addition to these function, this driver includes a set of macros allowing
61        to handle the following operations:
62 
63       (+) Set/Get the latency
64       (+) Enable/Disable the prefetch buffer
65       (+) Enable/Disable the FLASH interrupts
66       (+) Monitor the FLASH flags status
67 
68   @endverbatim
69   ******************************************************************************
70   * @attention
71   *
72   * Copyright (c) 2016 STMicroelectronics.
73   * All rights reserved.
74   *
75   * This software is licensed under terms that can be found in the LICENSE file in
76   * the root directory of this software component.
77   * If no LICENSE file comes with this software, it is provided AS-IS.
78   ******************************************************************************
79   */
80 
81 /* Includes ------------------------------------------------------------------*/
82 #include "stm32f0xx_hal.h"
83 
84 /** @addtogroup STM32F0xx_HAL_Driver
85   * @{
86   */
87 
88 #ifdef HAL_FLASH_MODULE_ENABLED
89 
90 /** @defgroup FLASH FLASH
91   * @brief FLASH HAL module driver
92   * @{
93   */
94 
95 /* Private typedef -----------------------------------------------------------*/
96 /* Private define ------------------------------------------------------------*/
97 /** @defgroup FLASH_Private_Constants FLASH Private Constants
98   * @{
99   */
100 /**
101   * @}
102   */
103 
104 /* Private macro ---------------------------- ---------------------------------*/
105 /** @defgroup FLASH_Private_Macros FLASH Private Macros
106   * @{
107   */
108 
109 /**
110   * @}
111   */
112 
113 /* Private variables ---------------------------------------------------------*/
114 /** @defgroup FLASH_Private_Variables FLASH Private Variables
115   * @{
116   */
117 /* Variables used for Erase pages under interruption*/
118 FLASH_ProcessTypeDef pFlash;
119 /**
120   * @}
121   */
122 
123 /* Private function prototypes -----------------------------------------------*/
124 /** @defgroup FLASH_Private_Functions FLASH Private Functions
125   * @{
126   */
127 static  void   FLASH_Program_HalfWord(uint32_t Address, uint16_t Data);
128 static  void   FLASH_SetErrorCode(void);
129 extern void    FLASH_PageErase(uint32_t PageAddress);
130 /**
131   * @}
132   */
133 
134 /* Exported functions ---------------------------------------------------------*/
135 /** @defgroup FLASH_Exported_Functions FLASH Exported Functions
136   * @{
137   */
138 
139 /** @defgroup FLASH_Exported_Functions_Group1 Programming operation functions
140   *  @brief   Programming operation functions
141   *
142 @verbatim
143 @endverbatim
144   * @{
145   */
146 
147 /**
148   * @brief  Program halfword, word or double word at a specified address
149   * @note   The function HAL_FLASH_Unlock() should be called before to unlock the FLASH interface
150   *         The function HAL_FLASH_Lock() should be called after to lock the FLASH interface
151   *
152   * @note   If an erase and a program operations are requested simultaneously,
153   *         the erase operation is performed before the program one.
154   *
155   * @note   FLASH should be previously erased before new programming (only exception to this
156   *         is when 0x0000 is programmed)
157   *
158   * @param  TypeProgram   Indicate the way to program at a specified address.
159   *                       This parameter can be a value of @ref FLASH_Type_Program
160   * @param  Address       Specifie the address to be programmed.
161   * @param  Data          Specifie the data to be programmed
162   *
163   * @retval HAL_StatusTypeDef HAL Status
164   */
HAL_FLASH_Program(uint32_t TypeProgram,uint32_t Address,uint64_t Data)165 HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
166 {
167   HAL_StatusTypeDef status = HAL_ERROR;
168   uint8_t index = 0U;
169   uint8_t nbiterations = 0U;
170 
171   /* Process Locked */
172   __HAL_LOCK(&pFlash);
173 
174   /* Check the parameters */
175   assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
176   assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
177 
178     /* Wait for last operation to be completed */
179     status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
180 
181   if(status == HAL_OK)
182   {
183     if(TypeProgram == FLASH_TYPEPROGRAM_HALFWORD)
184     {
185       /* Program halfword (16-bit) at a specified address. */
186       nbiterations = 1U;
187     }
188     else if(TypeProgram == FLASH_TYPEPROGRAM_WORD)
189     {
190       /* Program word (32-bit = 2*16-bit) at a specified address. */
191       nbiterations = 2U;
192     }
193     else
194     {
195       /* Program double word (64-bit = 4*16-bit) at a specified address. */
196       nbiterations = 4U;
197     }
198 
199     for (index = 0U; index < nbiterations; index++)
200     {
201       FLASH_Program_HalfWord((Address + (2U*index)), (uint16_t)(Data >> (16U*index)));
202 
203         /* Wait for last operation to be completed */
204         status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
205 
206         /* If the program operation is completed, disable the PG Bit */
207         CLEAR_BIT(FLASH->CR, FLASH_CR_PG);
208       /* In case of error, stop programming procedure */
209       if (status != HAL_OK)
210       {
211         break;
212       }
213     }
214   }
215 
216   /* Process Unlocked */
217   __HAL_UNLOCK(&pFlash);
218 
219   return status;
220 }
221 
222 /**
223   * @brief  Program halfword, word or double word at a specified address  with interrupt enabled.
224   * @note   The function HAL_FLASH_Unlock() should be called before to unlock the FLASH interface
225   *         The function HAL_FLASH_Lock() should be called after to lock the FLASH interface
226   *
227   * @note   If an erase and a program operations are requested simultaneously,
228   *         the erase operation is performed before the program one.
229   *
230   * @param  TypeProgram  Indicate the way to program at a specified address.
231   *                      This parameter can be a value of @ref FLASH_Type_Program
232   * @param  Address      Specifie the address to be programmed.
233   * @param  Data         Specifie the data to be programmed
234   *
235   * @retval HAL_StatusTypeDef HAL Status
236   */
HAL_FLASH_Program_IT(uint32_t TypeProgram,uint32_t Address,uint64_t Data)237 HAL_StatusTypeDef HAL_FLASH_Program_IT(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
238 {
239   HAL_StatusTypeDef status = HAL_OK;
240 
241   /* Process Locked */
242   __HAL_LOCK(&pFlash);
243 
244   /* Check the parameters */
245   assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
246   assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
247 
248   /* Enable End of FLASH Operation and Error source interrupts */
249   __HAL_FLASH_ENABLE_IT(FLASH_IT_EOP | FLASH_IT_ERR);
250 
251   pFlash.Address = Address;
252   pFlash.Data = Data;
253 
254   if(TypeProgram == FLASH_TYPEPROGRAM_HALFWORD)
255   {
256     pFlash.ProcedureOnGoing = FLASH_PROC_PROGRAMHALFWORD;
257     /* Program halfword (16-bit) at a specified address. */
258     pFlash.DataRemaining = 1U;
259   }
260   else if(TypeProgram == FLASH_TYPEPROGRAM_WORD)
261   {
262     pFlash.ProcedureOnGoing = FLASH_PROC_PROGRAMWORD;
263     /* Program word (32-bit : 2*16-bit) at a specified address. */
264     pFlash.DataRemaining = 2U;
265   }
266   else
267   {
268     pFlash.ProcedureOnGoing = FLASH_PROC_PROGRAMDOUBLEWORD;
269     /* Program double word (64-bit : 4*16-bit) at a specified address. */
270     pFlash.DataRemaining = 4U;
271   }
272 
273   /* Program halfword (16-bit) at a specified address. */
274   FLASH_Program_HalfWord(Address, (uint16_t)Data);
275 
276   return status;
277 }
278 
279 /**
280   * @brief This function handles FLASH interrupt request.
281   * @retval None
282   */
HAL_FLASH_IRQHandler(void)283 void HAL_FLASH_IRQHandler(void)
284 {
285   uint32_t addresstmp = 0U;
286 
287   /* Check FLASH operation error flags */
288   if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR) ||__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGERR))
289   {
290     /* Return the faulty address */
291     addresstmp = pFlash.Address;
292     /* Reset address */
293     pFlash.Address = 0xFFFFFFFFU;
294 
295     /* Save the Error code */
296     FLASH_SetErrorCode();
297 
298     /* FLASH error interrupt user callback */
299     HAL_FLASH_OperationErrorCallback(addresstmp);
300 
301     /* Stop the procedure ongoing */
302     pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
303   }
304 
305   /* Check FLASH End of Operation flag  */
306   if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP))
307   {
308     /* Clear FLASH End of Operation pending bit */
309     __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
310 
311     /* Process can continue only if no error detected */
312     if(pFlash.ProcedureOnGoing != FLASH_PROC_NONE)
313     {
314       if(pFlash.ProcedureOnGoing == FLASH_PROC_PAGEERASE)
315       {
316         /* Nb of pages to erased can be decreased */
317         pFlash.DataRemaining--;
318 
319         /* Check if there are still pages to erase */
320         if(pFlash.DataRemaining != 0U)
321         {
322           addresstmp = pFlash.Address;
323           /*Indicate user which sector has been erased */
324           HAL_FLASH_EndOfOperationCallback(addresstmp);
325 
326           /*Increment sector number*/
327           addresstmp = pFlash.Address + FLASH_PAGE_SIZE;
328           pFlash.Address = addresstmp;
329 
330           /* If the erase operation is completed, disable the PER Bit */
331           CLEAR_BIT(FLASH->CR, FLASH_CR_PER);
332 
333           FLASH_PageErase(addresstmp);
334         }
335         else
336         {
337           /* No more pages to Erase, user callback can be called. */
338           /* Reset Sector and stop Erase pages procedure */
339           pFlash.Address = addresstmp = 0xFFFFFFFFU;
340           pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
341           /* FLASH EOP interrupt user callback */
342           HAL_FLASH_EndOfOperationCallback(addresstmp);
343         }
344       }
345       else if(pFlash.ProcedureOnGoing == FLASH_PROC_MASSERASE)
346       {
347         /* Operation is completed, disable the MER Bit */
348         CLEAR_BIT(FLASH->CR, FLASH_CR_MER);
349 
350           /* MassErase ended. Return the selected bank */
351           /* FLASH EOP interrupt user callback */
352           HAL_FLASH_EndOfOperationCallback(0);
353 
354           /* Stop Mass Erase procedure*/
355           pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
356         }
357       else
358       {
359         /* Nb of 16-bit data to program can be decreased */
360         pFlash.DataRemaining--;
361 
362         /* Check if there are still 16-bit data to program */
363         if(pFlash.DataRemaining != 0U)
364         {
365           /* Increment address to 16-bit */
366           pFlash.Address += 2;
367           addresstmp = pFlash.Address;
368 
369           /* Shift to have next 16-bit data */
370           pFlash.Data = (pFlash.Data >> 16U);
371 
372           /* Operation is completed, disable the PG Bit */
373           CLEAR_BIT(FLASH->CR, FLASH_CR_PG);
374 
375           /*Program halfword (16-bit) at a specified address.*/
376           FLASH_Program_HalfWord(addresstmp, (uint16_t)pFlash.Data);
377         }
378         else
379         {
380           /* Program ended. Return the selected address */
381           /* FLASH EOP interrupt user callback */
382           if (pFlash.ProcedureOnGoing == FLASH_PROC_PROGRAMHALFWORD)
383           {
384             HAL_FLASH_EndOfOperationCallback(pFlash.Address);
385           }
386           else if (pFlash.ProcedureOnGoing == FLASH_PROC_PROGRAMWORD)
387           {
388             HAL_FLASH_EndOfOperationCallback(pFlash.Address - 2U);
389           }
390           else
391           {
392             HAL_FLASH_EndOfOperationCallback(pFlash.Address - 6U);
393           }
394 
395           /* Reset Address and stop Program procedure */
396           pFlash.Address = 0xFFFFFFFFU;
397           pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
398         }
399       }
400     }
401   }
402 
403 
404   if(pFlash.ProcedureOnGoing == FLASH_PROC_NONE)
405   {
406     /* Operation is completed, disable the PG, PER and MER Bits */
407     CLEAR_BIT(FLASH->CR, (FLASH_CR_PG | FLASH_CR_PER | FLASH_CR_MER));
408 
409     /* Disable End of FLASH Operation and Error source interrupts */
410     __HAL_FLASH_DISABLE_IT(FLASH_IT_EOP | FLASH_IT_ERR);
411 
412     /* Process Unlocked */
413     __HAL_UNLOCK(&pFlash);
414   }
415 }
416 
417 /**
418   * @brief  FLASH end of operation interrupt callback
419   * @param  ReturnValue The value saved in this parameter depends on the ongoing procedure
420   *                 - Mass Erase: No return value expected
421   *                 - Pages Erase: Address of the page which has been erased
422   *                    (if 0xFFFFFFFF, it means that all the selected pages have been erased)
423   *                 - Program: Address which was selected for data program
424   * @retval none
425   */
HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue)426 __weak void HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue)
427 {
428   /* Prevent unused argument(s) compilation warning */
429   UNUSED(ReturnValue);
430 
431   /* NOTE : This function Should not be modified, when the callback is needed,
432             the HAL_FLASH_EndOfOperationCallback could be implemented in the user file
433    */
434 }
435 
436 /**
437   * @brief  FLASH operation error interrupt callback
438   * @param  ReturnValue The value saved in this parameter depends on the ongoing procedure
439   *                 - Mass Erase: No return value expected
440   *                 - Pages Erase: Address of the page which returned an error
441   *                 - Program: Address which was selected for data program
442   * @retval none
443   */
HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue)444 __weak void HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue)
445 {
446   /* Prevent unused argument(s) compilation warning */
447   UNUSED(ReturnValue);
448 
449   /* NOTE : This function Should not be modified, when the callback is needed,
450             the HAL_FLASH_OperationErrorCallback could be implemented in the user file
451    */
452 }
453 
454 /**
455   * @}
456   */
457 
458 /** @defgroup FLASH_Exported_Functions_Group2 Peripheral Control functions
459  *  @brief   management functions
460  *
461 @verbatim
462  ===============================================================================
463                       ##### Peripheral Control functions #####
464  ===============================================================================
465     [..]
466     This subsection provides a set of functions allowing to control the FLASH
467     memory operations.
468 
469 @endverbatim
470   * @{
471   */
472 
473 /**
474   * @brief  Unlock the FLASH control register access
475   * @retval HAL Status
476   */
HAL_FLASH_Unlock(void)477 HAL_StatusTypeDef HAL_FLASH_Unlock(void)
478 {
479   HAL_StatusTypeDef status = HAL_OK;
480 
481   if(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != RESET)
482   {
483     /* Authorize the FLASH Registers access */
484     WRITE_REG(FLASH->KEYR, FLASH_KEY1);
485     WRITE_REG(FLASH->KEYR, FLASH_KEY2);
486 
487     /* Verify Flash is unlocked */
488     if(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != RESET)
489     {
490       status = HAL_ERROR;
491     }
492   }
493 
494   return status;
495 }
496 
497 /**
498   * @brief  Locks the FLASH control register access
499   * @retval HAL Status
500   */
HAL_FLASH_Lock(void)501 HAL_StatusTypeDef HAL_FLASH_Lock(void)
502 {
503   /* Set the LOCK Bit to lock the FLASH Registers access */
504   SET_BIT(FLASH->CR, FLASH_CR_LOCK);
505 
506   return HAL_OK;
507 }
508 
509 /**
510   * @brief  Unlock the FLASH Option Control Registers access.
511   * @retval HAL Status
512   */
HAL_FLASH_OB_Unlock(void)513 HAL_StatusTypeDef HAL_FLASH_OB_Unlock(void)
514 {
515   if (HAL_IS_BIT_CLR(FLASH->CR, FLASH_CR_OPTWRE))
516   {
517     /* Authorizes the Option Byte register programming */
518     WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY1);
519     WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY2);
520   }
521   else
522   {
523     return HAL_ERROR;
524   }
525 
526   return HAL_OK;
527 }
528 
529 /**
530   * @brief  Lock the FLASH Option Control Registers access.
531   * @retval HAL Status
532   */
HAL_FLASH_OB_Lock(void)533 HAL_StatusTypeDef HAL_FLASH_OB_Lock(void)
534 {
535   /* Clear the OPTWRE Bit to lock the FLASH Option Byte Registers access */
536   CLEAR_BIT(FLASH->CR, FLASH_CR_OPTWRE);
537 
538   return HAL_OK;
539 }
540 
541 /**
542   * @brief  Launch the option byte loading.
543   * @note   This function will reset automatically the MCU.
544   * @retval HAL Status
545   */
HAL_FLASH_OB_Launch(void)546 HAL_StatusTypeDef HAL_FLASH_OB_Launch(void)
547 {
548   /* Set the OBL_Launch bit to launch the option byte loading */
549   SET_BIT(FLASH->CR, FLASH_CR_OBL_LAUNCH);
550 
551   /* Wait for last operation to be completed */
552   return(FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE));
553 }
554 
555 /**
556   * @}
557   */
558 
559 /** @defgroup FLASH_Exported_Functions_Group3 Peripheral errors functions
560  *  @brief    Peripheral errors functions
561  *
562 @verbatim
563  ===============================================================================
564                       ##### Peripheral Errors functions #####
565  ===============================================================================
566     [..]
567     This subsection permit to get in run-time errors of  the FLASH peripheral.
568 
569 @endverbatim
570   * @{
571   */
572 
573 /**
574   * @brief  Get the specific FLASH error flag.
575   * @retval FLASH_ErrorCode The returned value can be:
576   *            @ref FLASH_Error_Codes
577   */
HAL_FLASH_GetError(void)578 uint32_t HAL_FLASH_GetError(void)
579 {
580    return pFlash.ErrorCode;
581 }
582 
583 /**
584   * @}
585   */
586 
587 /**
588   * @}
589   */
590 
591 /** @addtogroup FLASH_Private_Functions
592  * @{
593  */
594 
595 /**
596   * @brief  Program a half-word (16-bit) at a specified address.
597   * @param  Address specify the address to be programmed.
598   * @param  Data    specify the data to be programmed.
599   * @retval None
600   */
FLASH_Program_HalfWord(uint32_t Address,uint16_t Data)601 static void FLASH_Program_HalfWord(uint32_t Address, uint16_t Data)
602 {
603   /* Clean the error context */
604   pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
605 
606     /* Proceed to program the new data */
607     SET_BIT(FLASH->CR, FLASH_CR_PG);
608 
609   /* Write data in the address */
610   *(__IO uint16_t*)Address = Data;
611 }
612 
613 /**
614   * @brief  Wait for a FLASH operation to complete.
615   * @param  Timeout  maximum flash operation timeout
616   * @retval HAL Status
617   */
FLASH_WaitForLastOperation(uint32_t Timeout)618 HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout)
619 {
620   /* Wait for the FLASH operation to complete by polling on BUSY flag to be reset.
621      Even if the FLASH operation fails, the BUSY flag will be reset and an error
622      flag will be set */
623 
624   uint32_t tickstart = HAL_GetTick();
625 
626   while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY))
627   {
628     if (Timeout != HAL_MAX_DELAY)
629     {
630       if((Timeout == 0U) || ((HAL_GetTick()-tickstart) > Timeout))
631       {
632         return HAL_TIMEOUT;
633       }
634     }
635   }
636 
637   /* Check FLASH End of Operation flag  */
638   if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP))
639   {
640     /* Clear FLASH End of Operation pending bit */
641     __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
642   }
643 
644   if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)  ||
645      __HAL_FLASH_GET_FLAG(FLASH_FLAG_PGERR))
646   {
647     /*Save the error code*/
648     FLASH_SetErrorCode();
649     return HAL_ERROR;
650   }
651 
652   /* There is no error flag set */
653   return HAL_OK;
654 }
655 
656 
657 /**
658   * @brief  Set the specific FLASH error flag.
659   * @retval None
660   */
FLASH_SetErrorCode(void)661 static void FLASH_SetErrorCode(void)
662 {
663   uint32_t flags = 0U;
664 
665   if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR))
666   {
667     pFlash.ErrorCode |= HAL_FLASH_ERROR_WRP;
668     flags |= FLASH_FLAG_WRPERR;
669   }
670   if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGERR))
671   {
672     pFlash.ErrorCode |= HAL_FLASH_ERROR_PROG;
673     flags |= FLASH_FLAG_PGERR;
674   }
675   /* Clear FLASH error pending bits */
676   __HAL_FLASH_CLEAR_FLAG(flags);
677 }
678 /**
679   * @}
680   */
681 
682 /**
683   * @}
684   */
685 
686 #endif /* HAL_FLASH_MODULE_ENABLED */
687 
688 /**
689   * @}
690   */
691 
692