1 /**
2   ******************************************************************************
3   * @file    stm32l1xx_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 STM32L1xx 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
41         (++) Program functions: Fast Word and Half Page(should be
42         executed from internal SRAM).
43 
44       (#) DATA EEPROM Programming functions: this group includes all
45           needed functions to erase and program the DATA EEPROM memory:
46         (++) Lock and Unlock the DATA EEPROM interface.
47         (++) Erase function: Erase Byte, erase HalfWord, erase Word, erase
48              Double Word (should be executed from internal SRAM).
49         (++) Program functions: Fast Program Byte, Fast Program Half-Word,
50              FastProgramWord, Program Byte, Program Half-Word,
51              Program Word and Program Double-Word (should be executed
52              from internal SRAM).
53 
54       (#) FLASH Option Bytes Programming functions: this group includes all needed
55           functions to manage the Option Bytes:
56         (++) Lock and Unlock the Option Bytes
57         (++) Set/Reset the write protection
58         (++) Set the Read protection Level
59         (++) Program the user Option Bytes
60         (++) Launch the Option Bytes loader
61         (++) Set/Get the Read protection Level.
62         (++) Set/Get the BOR level.
63         (++) Get the Write protection.
64         (++) Get the user option bytes.
65 
66       (#) Interrupts and flags management functions : this group
67           includes all needed functions to:
68         (++) Handle FLASH interrupts
69         (++) Wait for last FLASH operation according to its status
70         (++) Get error flag status
71 
72     (#) FLASH Interface configuration functions: this group includes
73       the management of following features:
74       (++) Enable/Disable the RUN PowerDown mode.
75       (++) Enable/Disable the SLEEP PowerDown mode.
76 
77     (#) FLASH Peripheral State methods: this group includes
78       the management of following features:
79       (++) Wait for the FLASH operation
80       (++)  Get the specific FLASH error flag
81 
82   [..] In addition to these function, this driver includes a set of macros allowing
83        to handle the following operations:
84 
85       (+) Set/Get the latency
86       (+) Enable/Disable the prefetch buffer
87       (+) Enable/Disable the 64 bit Read Access.
88       (+) Enable/Disable the Flash power-down
89       (+) Enable/Disable the FLASH interrupts
90       (+) Monitor the FLASH flags status
91 
92                  ##### Programming operation functions #####
93   ===============================================================================
94      [..]
95      This subsection provides a set of functions allowing to manage the FLASH
96      program operations.
97 
98     [..] The FLASH Memory Programming functions, includes the following functions:
99      (+) HAL_FLASH_Unlock(void);
100      (+) HAL_FLASH_Lock(void);
101      (+) HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint32_t Data)
102      (+) HAL_FLASH_Program_IT(uint32_t TypeProgram, uint32_t Address, uint32_t Data)
103 
104      [..] Any operation of erase or program should follow these steps:
105      (#) Call the HAL_FLASH_Unlock() function to enable the flash control register and
106          program memory access.
107      (#) Call the desired function to erase page or program data.
108      (#) Call the HAL_FLASH_Lock() to disable the flash program memory access
109         (recommended to protect the FLASH memory against possible unwanted operation).
110 
111                ##### Option Bytes Programming functions #####
112    ==============================================================================
113 
114      [..] The FLASH_Option Bytes Programming_functions, includes the following functions:
115      (+) HAL_FLASH_OB_Unlock(void);
116      (+) HAL_FLASH_OB_Lock(void);
117      (+) HAL_FLASH_OB_Launch(void);
118      (+) HAL_FLASHEx_OBProgram(FLASH_OBProgramInitTypeDef *pOBInit);
119      (+) HAL_FLASHEx_OBGetConfig(FLASH_OBProgramInitTypeDef *pOBInit);
120 
121      [..] Any operation of erase or program should follow these steps:
122      (#) Call the HAL_FLASH_OB_Unlock() function to enable the Flash option control
123          register access.
124      (#) Call the following functions to program the desired option bytes.
125          (++) HAL_FLASHEx_OBProgram(FLASH_OBProgramInitTypeDef *pOBInit);
126      (#) Once all needed option bytes to be programmed are correctly written, call the
127          HAL_FLASH_OB_Launch(void) function to launch the Option Bytes programming process.
128      (#) Call the HAL_FLASH_OB_Lock() to disable the Flash option control register access (recommended
129          to protect the option Bytes against possible unwanted operations).
130 
131     [..] Proprietary code Read Out Protection (PcROP):
132     (#) The PcROP sector is selected by using the same option bytes as the Write
133         protection. As a result, these 2 options are exclusive each other.
134     (#) To activate PCROP mode for Flash sectors(s), you need to follow the sequence below:
135         (++) Use this function HAL_FLASHEx_AdvOBProgram with PCROPState = OB_PCROP_STATE_ENABLE.
136 
137   @endverbatim
138   ******************************************************************************
139   * @attention
140   *
141   * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
142   *
143   * Redistribution and use in source and binary forms, with or without modification,
144   * are permitted provided that the following conditions are met:
145   *   1. Redistributions of source code must retain the above copyright notice,
146   *      this list of conditions and the following disclaimer.
147   *   2. Redistributions in binary form must reproduce the above copyright notice,
148   *      this list of conditions and the following disclaimer in the documentation
149   *      and/or other materials provided with the distribution.
150   *   3. Neither the name of STMicroelectronics nor the names of its contributors
151   *      may be used to endorse or promote products derived from this software
152   *      without specific prior written permission.
153   *
154   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
155   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
156   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
157   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
158   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
159   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
160   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
161   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
162   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
163   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
164   *
165   ******************************************************************************
166   */
167 
168 /* Includes ------------------------------------------------------------------*/
169 #include "stm32l1xx_hal.h"
170 
171 /** @addtogroup STM32L1xx_HAL_Driver
172   * @{
173   */
174 
175 #ifdef HAL_FLASH_MODULE_ENABLED
176 
177 /** @defgroup FLASH FLASH
178   * @brief FLASH HAL module driver
179   * @{
180   */
181 
182 /* Private typedef -----------------------------------------------------------*/
183 /* Private define ------------------------------------------------------------*/
184 /** @defgroup FLASH_Private_Constants FLASH Private Constants
185   * @{
186   */
187 /**
188   * @}
189   */
190 
191 /* Private macro ---------------------------- ---------------------------------*/
192 /** @defgroup FLASH_Private_Macros FLASH Private Macros
193   * @{
194   */
195 
196 /**
197   * @}
198   */
199 
200 /* Private variables ---------------------------------------------------------*/
201 /** @defgroup FLASH_Private_Variables FLASH Private Variables
202   * @{
203   */
204 /* Variables used for Erase pages under interruption*/
205 FLASH_ProcessTypeDef pFlash;
206 /**
207   * @}
208   */
209 
210 /* Private function prototypes -----------------------------------------------*/
211 /** @defgroup FLASH_Private_Functions FLASH Private Functions
212   * @{
213   */
214 static  void   FLASH_SetErrorCode(void);
215 extern void    FLASH_PageErase(uint32_t PageAddress);
216 /**
217   * @}
218   */
219 
220 /* Exported functions ---------------------------------------------------------*/
221 /** @defgroup FLASH_Exported_Functions FLASH Exported Functions
222   * @{
223   */
224 
225 /** @defgroup FLASH_Exported_Functions_Group1 Programming operation functions
226   *  @brief   Programming operation functions
227   *
228 @verbatim
229 @endverbatim
230   * @{
231   */
232 
233 /**
234   * @brief  Program word at a specified address
235   * @note   To correctly run this function, the HAL_FLASH_Unlock() function
236   *         must be called before.
237   *         Call the HAL_FLASH_Lock() to disable the flash memory access
238   *         (recommended to protect the FLASH memory against possible unwanted operation).
239   *
240   * @param  TypeProgram   Indicate the way to program at a specified address.
241   *                       This parameter can be a value of @ref FLASH_Type_Program
242   * @param  Address       Specifie the address to be programmed.
243   * @param  Data          Specifie the data to be programmed
244   *
245   * @retval HAL_StatusTypeDef HAL Status
246   */
HAL_FLASH_Program(uint32_t TypeProgram,uint32_t Address,uint32_t Data)247 HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint32_t Data)
248 {
249   HAL_StatusTypeDef status = HAL_ERROR;
250 
251   /* Process Locked */
252   __HAL_LOCK(&pFlash);
253 
254   /* Check the parameters */
255   assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
256   assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
257 
258   /* Wait for last operation to be completed */
259   status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
260 
261   if(status == HAL_OK)
262   {
263     /* Clean the error context */
264     pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
265 
266     /*Program word (32-bit) at a specified address.*/
267     *(__IO uint32_t *)Address = Data;
268 
269     /* Wait for last operation to be completed */
270     status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
271   }
272 
273   /* Process Unlocked */
274   __HAL_UNLOCK(&pFlash);
275 
276   return status;
277 }
278 
279 /**
280   * @brief   Program word at a specified address  with interrupt enabled.
281   *
282   * @param  TypeProgram  Indicate the way to program at a specified address.
283   *                      This parameter can be a value of @ref FLASH_Type_Program
284   * @param  Address      Specifie the address to be programmed.
285   * @param  Data         Specifie the data to be programmed
286   *
287   * @retval HAL_StatusTypeDef HAL Status
288   */
HAL_FLASH_Program_IT(uint32_t TypeProgram,uint32_t Address,uint32_t Data)289 HAL_StatusTypeDef HAL_FLASH_Program_IT(uint32_t TypeProgram, uint32_t Address, uint32_t Data)
290 {
291   HAL_StatusTypeDef status = HAL_OK;
292 
293   /* Process Locked */
294   __HAL_LOCK(&pFlash);
295 
296   /* Check the parameters */
297   assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
298   assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
299 
300   /* Enable End of FLASH Operation and Error source interrupts */
301   __HAL_FLASH_ENABLE_IT(FLASH_IT_EOP | FLASH_IT_ERR);
302 
303   pFlash.Address = Address;
304   pFlash.ProcedureOnGoing = FLASH_PROC_PROGRAM;
305   /* Clean the error context */
306   pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
307 
308   if(TypeProgram == FLASH_TYPEPROGRAM_WORD)
309   {
310     /* Program word (32-bit) at a specified address. */
311     *(__IO uint32_t *)Address = Data;
312   }
313   return status;
314 }
315 
316 /**
317   * @brief This function handles FLASH interrupt request.
318   * @retval None
319   */
HAL_FLASH_IRQHandler(void)320 void HAL_FLASH_IRQHandler(void)
321 {
322   uint32_t addresstmp = 0U;
323 
324   /* Check FLASH operation error flags */
325   if( __HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)     ||
326       __HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)     ||
327       __HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)     ||
328 #if defined(FLASH_SR_RDERR)
329       __HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)      ||
330 #endif /* FLASH_SR_RDERR */
331 #if defined(FLASH_SR_OPTVERRUSR)
332       __HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERRUSR) ||
333 #endif /* FLASH_SR_OPTVERRUSR */
334       __HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR) )
335   {
336     if(pFlash.ProcedureOnGoing == FLASH_PROC_PAGEERASE)
337     {
338       /* Return the faulty sector */
339       addresstmp = pFlash.Page;
340       pFlash.Page = 0xFFFFFFFFU;
341     }
342     else
343     {
344       /* Return the faulty address */
345       addresstmp = pFlash.Address;
346     }
347     /* Save the Error code */
348     FLASH_SetErrorCode();
349 
350     /* FLASH error interrupt user callback */
351     HAL_FLASH_OperationErrorCallback(addresstmp);
352 
353     /* Stop the procedure ongoing */
354     pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
355   }
356 
357   /* Check FLASH End of Operation flag  */
358   if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP))
359   {
360     /* Clear FLASH End of Operation pending bit */
361     __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
362 
363     /* Process can continue only if no error detected */
364     if(pFlash.ProcedureOnGoing != FLASH_PROC_NONE)
365     {
366       if(pFlash.ProcedureOnGoing == FLASH_PROC_PAGEERASE)
367       {
368         /* Nb of pages to erased can be decreased */
369         pFlash.NbPagesToErase--;
370 
371         /* Check if there are still pages to erase */
372         if(pFlash.NbPagesToErase != 0U)
373         {
374           addresstmp = pFlash.Page;
375           /*Indicate user which sector has been erased */
376           HAL_FLASH_EndOfOperationCallback(addresstmp);
377 
378           /*Increment sector number*/
379           addresstmp = pFlash.Page + FLASH_PAGE_SIZE;
380           pFlash.Page = addresstmp;
381 
382           /* If the erase operation is completed, disable the ERASE Bit */
383           CLEAR_BIT(FLASH->PECR, FLASH_PECR_ERASE);
384 
385           FLASH_PageErase(addresstmp);
386         }
387         else
388         {
389           /* No more pages to Erase, user callback can be called. */
390           /* Reset Sector and stop Erase pages procedure */
391           pFlash.Page = addresstmp = 0xFFFFFFFFU;
392           pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
393           /* FLASH EOP interrupt user callback */
394           HAL_FLASH_EndOfOperationCallback(addresstmp);
395         }
396       }
397       else
398       {
399           /* If the program operation is completed, disable the PROG Bit */
400           CLEAR_BIT(FLASH->PECR, FLASH_PECR_PROG);
401 
402           /* Program ended. Return the selected address */
403           /* FLASH EOP interrupt user callback */
404           HAL_FLASH_EndOfOperationCallback(pFlash.Address);
405 
406           /* Reset Address and stop Program procedure */
407           pFlash.Address = 0xFFFFFFFFU;
408           pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
409       }
410     }
411   }
412 
413 
414   if(pFlash.ProcedureOnGoing == FLASH_PROC_NONE)
415   {
416     /* Operation is completed, disable the PROG and ERASE */
417     CLEAR_BIT(FLASH->PECR, (FLASH_PECR_ERASE | FLASH_PECR_PROG));
418 
419     /* Disable End of FLASH Operation and Error source interrupts */
420     __HAL_FLASH_DISABLE_IT(FLASH_IT_EOP | FLASH_IT_ERR);
421 
422     /* Process Unlocked */
423     __HAL_UNLOCK(&pFlash);
424   }
425 }
426 
427 /**
428   * @brief  FLASH end of operation interrupt callback
429   * @param  ReturnValue: The value saved in this parameter depends on the ongoing procedure
430   *                 - Pages Erase: Address of the page which has been erased
431   *                    (if 0xFFFFFFFF, it means that all the selected pages have been erased)
432   *                 - Program: Address which was selected for data program
433   * @retval none
434   */
HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue)435 __weak void HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue)
436 {
437   /* Prevent unused argument(s) compilation warning */
438   UNUSED(ReturnValue);
439 
440   /* NOTE : This function Should not be modified, when the callback is needed,
441             the HAL_FLASH_EndOfOperationCallback could be implemented in the user file
442    */
443 }
444 
445 /**
446   * @brief  FLASH operation error interrupt callback
447   * @param  ReturnValue: The value saved in this parameter depends on the ongoing procedure
448   *                 - Pages Erase: Address of the page which returned an error
449   *                 - Program: Address which was selected for data program
450   * @retval none
451   */
HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue)452 __weak void HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue)
453 {
454   /* Prevent unused argument(s) compilation warning */
455   UNUSED(ReturnValue);
456 
457   /* NOTE : This function Should not be modified, when the callback is needed,
458             the HAL_FLASH_OperationErrorCallback could be implemented in the user file
459    */
460 }
461 
462 /**
463   * @}
464   */
465 
466 /** @defgroup FLASH_Exported_Functions_Group2 Peripheral Control functions
467  *  @brief   management functions
468  *
469 @verbatim
470  ===============================================================================
471                       ##### Peripheral Control functions #####
472  ===============================================================================
473     [..]
474     This subsection provides a set of functions allowing to control the FLASH
475     memory operations.
476 
477 @endverbatim
478   * @{
479   */
480 
481 /**
482   * @brief  Unlock the FLASH control register access
483   * @retval HAL Status
484   */
HAL_FLASH_Unlock(void)485 HAL_StatusTypeDef HAL_FLASH_Unlock(void)
486 {
487   if (HAL_IS_BIT_SET(FLASH->PECR, FLASH_PECR_PRGLOCK))
488   {
489     /* Unlocking FLASH_PECR register access*/
490     if(HAL_IS_BIT_SET(FLASH->PECR, FLASH_PECR_PELOCK))
491     {
492       WRITE_REG(FLASH->PEKEYR, FLASH_PEKEY1);
493       WRITE_REG(FLASH->PEKEYR, FLASH_PEKEY2);
494     }
495 
496     /* Unlocking the program memory access */
497     WRITE_REG(FLASH->PRGKEYR, FLASH_PRGKEY1);
498     WRITE_REG(FLASH->PRGKEYR, FLASH_PRGKEY2);
499   }
500   else
501   {
502     return HAL_ERROR;
503   }
504 
505   return HAL_OK;
506 }
507 
508 /**
509   * @brief  Locks the FLASH control register access
510   * @retval HAL Status
511   */
HAL_FLASH_Lock(void)512 HAL_StatusTypeDef HAL_FLASH_Lock(void)
513 {
514   /* Set the PRGLOCK Bit to lock the FLASH Registers access */
515   SET_BIT(FLASH->PECR, FLASH_PECR_PRGLOCK);
516 
517   return HAL_OK;
518 }
519 
520 /**
521   * @brief  Unlock the FLASH Option Control Registers access.
522   * @retval HAL Status
523   */
HAL_FLASH_OB_Unlock(void)524 HAL_StatusTypeDef HAL_FLASH_OB_Unlock(void)
525 {
526   if(HAL_IS_BIT_SET(FLASH->PECR, FLASH_PECR_OPTLOCK))
527   {
528     /* Unlocking FLASH_PECR register access*/
529     if(HAL_IS_BIT_SET(FLASH->PECR, FLASH_PECR_PELOCK))
530     {
531       /* Unlocking FLASH_PECR register access*/
532       WRITE_REG(FLASH->PEKEYR, FLASH_PEKEY1);
533       WRITE_REG(FLASH->PEKEYR, FLASH_PEKEY2);
534     }
535 
536     /* Unlocking the option bytes block access */
537     WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY1);
538     WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY2);
539   }
540   else
541   {
542     return HAL_ERROR;
543   }
544 
545   return HAL_OK;
546 }
547 
548 /**
549   * @brief  Lock the FLASH Option Control Registers access.
550   * @retval HAL Status
551   */
HAL_FLASH_OB_Lock(void)552 HAL_StatusTypeDef HAL_FLASH_OB_Lock(void)
553 {
554   /* Set the OPTLOCK Bit to lock the option bytes block access */
555   SET_BIT(FLASH->PECR, FLASH_PECR_OPTLOCK);
556 
557   return HAL_OK;
558 }
559 
560 /**
561   * @brief  Launch the option byte loading.
562   * @note   This function will reset automatically the MCU.
563   * @retval HAL Status
564   */
HAL_FLASH_OB_Launch(void)565 HAL_StatusTypeDef HAL_FLASH_OB_Launch(void)
566 {
567   /* Set the OBL_Launch bit to launch the option byte loading */
568   SET_BIT(FLASH->PECR, FLASH_PECR_OBL_LAUNCH);
569 
570   /* Wait for last operation to be completed */
571   return(FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE));
572 }
573 
574 /**
575   * @}
576   */
577 
578 /** @defgroup FLASH_Exported_Functions_Group3 Peripheral errors functions
579  *  @brief    Peripheral errors functions
580  *
581 @verbatim
582  ===============================================================================
583                       ##### Peripheral Errors functions #####
584  ===============================================================================
585     [..]
586     This subsection permit to get in run-time errors of  the FLASH peripheral.
587 
588 @endverbatim
589   * @{
590   */
591 
592 /**
593   * @brief  Get the specific FLASH error flag.
594   * @retval FLASH_ErrorCode The returned value can be:
595   *            @ref FLASH_Error_Codes
596   */
HAL_FLASH_GetError(void)597 uint32_t HAL_FLASH_GetError(void)
598 {
599    return pFlash.ErrorCode;
600 }
601 
602 /**
603   * @}
604   */
605 
606 /**
607   * @}
608   */
609 
610 /** @addtogroup FLASH_Private_Functions
611  * @{
612  */
613 
614 /**
615   * @brief  Wait for a FLASH operation to complete.
616   * @param  Timeout  maximum flash operation timeout
617   * @retval HAL Status
618   */
FLASH_WaitForLastOperation(uint32_t Timeout)619 HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout)
620 {
621   /* Wait for the FLASH operation to complete by polling on BUSY flag to be reset.
622      Even if the FLASH operation fails, the BUSY flag will be reset and an error
623      flag will be set */
624 
625   uint32_t tickstart = HAL_GetTick();
626 
627   while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY))
628   {
629     if (Timeout != HAL_MAX_DELAY)
630     {
631       if((Timeout == 0U) || ((HAL_GetTick()-tickstart) > Timeout))
632       {
633         return HAL_TIMEOUT;
634       }
635     }
636   }
637 
638   /* Check FLASH End of Operation flag  */
639   if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP))
640   {
641     /* Clear FLASH End of Operation pending bit */
642     __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
643   }
644 
645   if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)  ||
646      __HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR) ||
647 #if defined(FLASH_SR_RDERR)
648       __HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR) ||
649 #endif /* FLASH_SR_RDERR */
650 #if defined(FLASH_SR_OPTVERRUSR)
651       __HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERRUSR) ||
652 #endif /* FLASH_SR_OPTVERRUSR */
653      __HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))
654   {
655     /*Save the error code*/
656     FLASH_SetErrorCode();
657     return HAL_ERROR;
658   }
659 
660   /* There is no error flag set */
661   return HAL_OK;
662 }
663 
664 
665 /**
666   * @brief  Set the specific FLASH error flag.
667   * @retval None
668   */
FLASH_SetErrorCode(void)669 static void FLASH_SetErrorCode(void)
670 {
671   uint32_t flags = 0U;
672 
673   if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR))
674   {
675     pFlash.ErrorCode |= HAL_FLASH_ERROR_WRP;
676     flags |= FLASH_FLAG_WRPERR;
677   }
678   if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))
679   {
680     pFlash.ErrorCode |= HAL_FLASH_ERROR_PGA;
681     flags |= FLASH_FLAG_PGAERR;
682   }
683   if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR))
684   {
685     pFlash.ErrorCode |= HAL_FLASH_ERROR_OPTV;
686     flags |= FLASH_FLAG_OPTVERR;
687   }
688 
689 #if defined(FLASH_SR_RDERR)
690   if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR))
691   {
692     pFlash.ErrorCode |= HAL_FLASH_ERROR_RD;
693     flags |= FLASH_FLAG_RDERR;
694   }
695 #endif /* FLASH_SR_RDERR */
696 #if defined(FLASH_SR_OPTVERRUSR)
697   if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERRUSR))
698   {
699     pFlash.ErrorCode |= HAL_FLASH_ERROR_OPTVUSR;
700     flags |= FLASH_FLAG_OPTVERRUSR;
701   }
702 #endif /* FLASH_SR_OPTVERRUSR */
703 
704   /* Clear FLASH error pending bits */
705   __HAL_FLASH_CLEAR_FLAG(flags);
706 }
707 /**
708   * @}
709   */
710 
711 /**
712   * @}
713   */
714 
715 #endif /* HAL_FLASH_MODULE_ENABLED */
716 
717 /**
718   * @}
719   */
720 
721 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
722