1 /**
2   ******************************************************************************
3   * @file    stm32l0xx_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 STM32L0xx 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 preread buffer
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   * Copyright (c) 2016 STMicroelectronics.
142   * All rights reserved.
143   *
144   * This software is licensed under terms that can be found in the LICENSE file in
145   * the root directory of this software component.
146   * If no LICENSE file comes with this software, it is provided AS-IS.
147   ******************************************************************************
148   */
149 
150 /* Includes ------------------------------------------------------------------*/
151 #include "stm32l0xx_hal.h"
152 
153 /** @addtogroup STM32L0xx_HAL_Driver
154   * @{
155   */
156 
157 #ifdef HAL_FLASH_MODULE_ENABLED
158 
159 /** @defgroup FLASH FLASH
160   * @brief FLASH HAL module driver
161   * @{
162   */
163 
164 /* Private typedef -----------------------------------------------------------*/
165 /* Private define ------------------------------------------------------------*/
166 /** @defgroup FLASH_Private_Constants FLASH Private Constants
167   * @{
168   */
169 /**
170   * @}
171   */
172 
173 /* Private macro ---------------------------- ---------------------------------*/
174 /** @defgroup FLASH_Private_Macros FLASH Private Macros
175   * @{
176   */
177 
178 /**
179   * @}
180   */
181 
182 /* Private variables ---------------------------------------------------------*/
183 /** @defgroup FLASH_Private_Variables FLASH Private Variables
184   * @{
185   */
186 /* Variables used for Erase pages under interruption*/
187 FLASH_ProcessTypeDef pFlash;
188 /**
189   * @}
190   */
191 
192 /* Private function prototypes -----------------------------------------------*/
193 /** @defgroup FLASH_Private_Functions FLASH Private Functions
194   * @{
195   */
196 static  void   FLASH_SetErrorCode(void);
197 /**
198   * @}
199   */
200 
201 /* Exported functions ---------------------------------------------------------*/
202 /** @defgroup FLASH_Exported_Functions FLASH Exported Functions
203   * @{
204   */
205 
206 /** @defgroup FLASH_Exported_Functions_Group1 Programming operation functions
207   *  @brief   Programming operation functions
208   *
209 @verbatim
210 @endverbatim
211   * @{
212   */
213 
214 /**
215   * @brief  Program word at a specified address
216   * @note   To correctly run this function, the HAL_FLASH_Unlock() function
217   *         must be called before.
218   *         Call the HAL_FLASH_Lock() to disable the flash memory access
219   *         (recommended to protect the FLASH memory against possible unwanted operation).
220   *
221   * @param  TypeProgram   Indicate the way to program at a specified address.
222   *                       This parameter can be a value of @ref FLASH_Type_Program
223   * @param  Address       Specifie the address to be programmed.
224   * @param  Data          Specifie the data to be programmed
225   *
226   * @retval HAL_StatusTypeDef HAL Status
227   */
HAL_FLASH_Program(uint32_t TypeProgram,uint32_t Address,uint32_t Data)228 HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint32_t Data)
229 {
230   HAL_StatusTypeDef status = HAL_ERROR;
231 
232   /* Process Locked */
233   __HAL_LOCK(&pFlash);
234 
235   /* Check the parameters */
236   assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
237   assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
238 
239   /* Wait for last operation to be completed */
240   status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
241 
242   if(status == HAL_OK)
243   {
244     /* Clean the error context */
245     pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
246 
247     /*Program word (32-bit) at a specified address.*/
248     *(__IO uint32_t *)Address = Data;
249 
250     /* Wait for last operation to be completed */
251     status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
252   }
253 
254   /* Process Unlocked */
255   __HAL_UNLOCK(&pFlash);
256 
257   return status;
258 }
259 
260 /**
261   * @brief   Program word at a specified address  with interrupt enabled.
262   *
263   * @param  TypeProgram  Indicate the way to program at a specified address.
264   *                      This parameter can be a value of @ref FLASH_Type_Program
265   * @param  Address      Specifie the address to be programmed.
266   * @param  Data         Specifie the data to be programmed
267   *
268   * @retval HAL_StatusTypeDef HAL Status
269   */
HAL_FLASH_Program_IT(uint32_t TypeProgram,uint32_t Address,uint32_t Data)270 HAL_StatusTypeDef HAL_FLASH_Program_IT(uint32_t TypeProgram, uint32_t Address, uint32_t Data)
271 {
272   HAL_StatusTypeDef status = HAL_OK;
273 
274   /* Process Locked */
275   __HAL_LOCK(&pFlash);
276 
277   /* Check the parameters */
278   assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
279   assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
280 
281   /* Enable End of FLASH Operation and Error source interrupts */
282   __HAL_FLASH_ENABLE_IT(FLASH_IT_EOP | FLASH_IT_ERR);
283 
284   pFlash.Address = Address;
285   pFlash.ProcedureOnGoing = FLASH_PROC_PROGRAM;
286   /* Clean the error context */
287   pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
288   /* Program word (32-bit) at a specified address. */
289   *(__IO uint32_t *)Address = Data;
290 
291   return status;
292 }
293 
294 /**
295   * @brief This function handles FLASH interrupt request.
296   * @retval None
297   */
HAL_FLASH_IRQHandler(void)298 void HAL_FLASH_IRQHandler(void)
299 {
300   uint32_t addresstmp = 0;
301 
302   /* Check FLASH operation error flags */
303 
304   /* WARNING : On the first cut of STM32L031xx and STM32L041xx devices,
305    *           (RefID = 0x1000) the FLASH_FLAG_OPTVERR bit was not behaving
306    *           as expected. If the user run an application using the first
307    *           cut of the STM32L031xx device or the first cut of the STM32L041xx
308    *           device, the check on the FLASH_FLAG_OPTVERR bit should be ignored.
309    *
310    *           Note :The revId of the device can be retrieved via the HAL_GetREVID()
311    *           function.
312    *
313    */
314 
315   if( __HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)     ||
316       __HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)     ||
317       __HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)     ||
318       __HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)    ||
319       __HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)      ||
320       __HAL_FLASH_GET_FLAG(FLASH_FLAG_FWWERR)     ||
321       __HAL_FLASH_GET_FLAG(FLASH_FLAG_NOTZEROERR) )
322   {
323     if(pFlash.ProcedureOnGoing == FLASH_PROC_PAGEERASE)
324     {
325       /* Return the faulty sector */
326       addresstmp = pFlash.Page;
327       pFlash.Page = 0xFFFFFFFFU;
328     }
329     else
330     {
331       /* Return the faulty address */
332       addresstmp = pFlash.Address;
333     }
334     /* Save the Error code */
335     FLASH_SetErrorCode();
336 
337     /* FLASH error interrupt user callback */
338     HAL_FLASH_OperationErrorCallback(addresstmp);
339 
340     /* Stop the procedure ongoing */
341     pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
342   }
343 
344   /* Check FLASH End of Operation flag  */
345   if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP))
346   {
347     /* Clear FLASH End of Operation pending bit */
348     __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
349 
350     /* Process can continue only if no error detected */
351     if(pFlash.ProcedureOnGoing != FLASH_PROC_NONE)
352     {
353       if(pFlash.ProcedureOnGoing == FLASH_PROC_PAGEERASE)
354       {
355         /* Nb of pages to erased can be decreased */
356         pFlash.NbPagesToErase--;
357 
358         /* Check if there are still pages to erase */
359         if(pFlash.NbPagesToErase != 0U)
360         {
361           addresstmp = pFlash.Page;
362           /*Indicate user which sector has been erased */
363           HAL_FLASH_EndOfOperationCallback(addresstmp);
364 
365           /*Increment sector number*/
366           addresstmp = pFlash.Page + FLASH_PAGE_SIZE;
367           pFlash.Page = addresstmp;
368 
369           /* If the erase operation is completed, disable the ERASE Bit */
370           CLEAR_BIT(FLASH->PECR, FLASH_PECR_ERASE);
371 
372           FLASH_PageErase(addresstmp);
373         }
374         else
375         {
376           /* No more pages to Erase, user callback can be called. */
377           /* Reset Sector and stop Erase pages procedure */
378           pFlash.Page = addresstmp = 0xFFFFFFFFU;
379           pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
380           /* FLASH EOP interrupt user callback */
381           HAL_FLASH_EndOfOperationCallback(addresstmp);
382         }
383       }
384       else
385       {
386           /* If the program operation is completed, disable the PROG Bit */
387           CLEAR_BIT(FLASH->PECR, FLASH_PECR_PROG);
388 
389           /* Program ended. Return the selected address */
390           /* FLASH EOP interrupt user callback */
391           HAL_FLASH_EndOfOperationCallback(pFlash.Address);
392 
393           /* Reset Address and stop Program procedure */
394           pFlash.Address = 0xFFFFFFFFU;
395           pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
396       }
397     }
398   }
399 
400 
401   if(pFlash.ProcedureOnGoing == FLASH_PROC_NONE)
402   {
403     /* Operation is completed, disable the PROG and ERASE */
404     CLEAR_BIT(FLASH->PECR, (FLASH_PECR_ERASE | FLASH_PECR_PROG));
405 
406     /* Disable End of FLASH Operation and Error source interrupts */
407     __HAL_FLASH_DISABLE_IT(FLASH_IT_EOP | FLASH_IT_ERR);
408 
409     /* Process Unlocked */
410     __HAL_UNLOCK(&pFlash);
411   }
412 }
413 
414 /**
415   * @brief  FLASH end of operation interrupt callback
416   * @param  ReturnValue The value saved in this parameter depends on the ongoing procedure
417   *                 - Pages Erase: Address of the page which has been erased
418   *                    (if 0xFFFFFFFF, it means that all the selected pages have been erased)
419   *                 - Program: Address which was selected for data program
420   * @retval none
421   */
HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue)422 __weak void HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue)
423 {
424   /* Prevent unused argument(s) compilation warning */
425   UNUSED(ReturnValue);
426 
427   /* NOTE : This function Should not be modified, when the callback is needed,
428             the HAL_FLASH_EndOfOperationCallback could be implemented in the user file
429    */
430 }
431 
432 /**
433   * @brief  FLASH operation error interrupt callback
434   * @param  ReturnValue The value saved in this parameter depends on the ongoing procedure
435   *                 - Pages Erase: Address of the page which returned an error
436   *                 - Program: Address which was selected for data program
437   * @retval none
438   */
HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue)439 __weak void HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue)
440 {
441   /* Prevent unused argument(s) compilation warning */
442   UNUSED(ReturnValue);
443 
444   /* NOTE : This function Should not be modified, when the callback is needed,
445             the HAL_FLASH_OperationErrorCallback could be implemented in the user file
446    */
447 }
448 
449 /**
450   * @}
451   */
452 
453 /** @defgroup FLASH_Exported_Functions_Group2 Peripheral Control functions
454  *  @brief   management functions
455  *
456 @verbatim
457  ===============================================================================
458                       ##### Peripheral Control functions #####
459  ===============================================================================
460     [..]
461     This subsection provides a set of functions allowing to control the FLASH
462     memory operations.
463 
464 @endverbatim
465   * @{
466   */
467 
468 /**
469   * @brief  Unlock the FLASH control register access
470   * @retval HAL Status
471   */
HAL_FLASH_Unlock(void)472 HAL_StatusTypeDef HAL_FLASH_Unlock(void)
473 {
474   uint32_t primask_bit;
475 
476   /* Unlocking FLASH_PECR register access*/
477   if(HAL_IS_BIT_SET(FLASH->PECR, FLASH_PECR_PELOCK))
478   {
479     /* Disable interrupts to avoid any interruption during unlock sequence */
480     primask_bit = __get_PRIMASK();
481     __disable_irq();
482 
483     WRITE_REG(FLASH->PEKEYR, FLASH_PEKEY1);
484     WRITE_REG(FLASH->PEKEYR, FLASH_PEKEY2);
485 
486     /* Re-enable the interrupts: restore previous priority mask */
487     __set_PRIMASK(primask_bit);
488 
489     if(HAL_IS_BIT_SET(FLASH->PECR, FLASH_PECR_PELOCK))
490     {
491       return HAL_ERROR;
492     }
493   }
494 
495   if (HAL_IS_BIT_SET(FLASH->PECR, FLASH_PECR_PRGLOCK))
496   {
497     /* Disable interrupts to avoid any interruption during unlock sequence */
498     primask_bit = __get_PRIMASK();
499     __disable_irq();
500 
501     /* Unlocking the program memory access */
502     WRITE_REG(FLASH->PRGKEYR, FLASH_PRGKEY1);
503     WRITE_REG(FLASH->PRGKEYR, FLASH_PRGKEY2);
504 
505     /* Re-enable the interrupts: restore previous priority mask */
506     __set_PRIMASK(primask_bit);
507 
508     if (HAL_IS_BIT_SET(FLASH->PECR, FLASH_PECR_PRGLOCK))
509     {
510       return HAL_ERROR;
511     }
512   }
513 
514   return HAL_OK;
515 }
516 
517 /**
518   * @brief  Locks the FLASH control register access
519   * @retval HAL Status
520   */
HAL_FLASH_Lock(void)521 HAL_StatusTypeDef HAL_FLASH_Lock(void)
522 {
523   /* Set the PRGLOCK Bit to lock the FLASH Registers access */
524   SET_BIT(FLASH->PECR, FLASH_PECR_PRGLOCK);
525 
526   /* Set the PELOCK Bit to lock the PECR Register access */
527   SET_BIT(FLASH->PECR, FLASH_PECR_PELOCK);
528 
529   return HAL_OK;
530 }
531 
532 /**
533   * @brief  Unlock the FLASH Option Control Registers access.
534   * @retval HAL Status
535   */
HAL_FLASH_OB_Unlock(void)536 HAL_StatusTypeDef HAL_FLASH_OB_Unlock(void)
537 {
538   uint32_t primask_bit;
539 
540   if(HAL_IS_BIT_SET(FLASH->PECR, FLASH_PECR_OPTLOCK))
541   {
542     /* Disable interrupts to avoid any interruption during unlock sequence */
543     primask_bit = __get_PRIMASK();
544     __disable_irq();
545 
546     /* Unlocking FLASH_PECR register access*/
547     if(HAL_IS_BIT_SET(FLASH->PECR, FLASH_PECR_PELOCK))
548     {
549       /* Unlocking FLASH_PECR register access*/
550       WRITE_REG(FLASH->PEKEYR, FLASH_PEKEY1);
551       WRITE_REG(FLASH->PEKEYR, FLASH_PEKEY2);
552     }
553 
554     /* Unlocking the option bytes block access */
555     WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY1);
556     WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY2);
557 
558     /* Re-enable the interrupts: restore previous priority mask */
559     __set_PRIMASK(primask_bit);
560   }
561   else
562   {
563     return HAL_ERROR;
564   }
565 
566   return HAL_OK;
567 }
568 
569 /**
570   * @brief  Lock the FLASH Option Control Registers access.
571   * @retval HAL Status
572   */
HAL_FLASH_OB_Lock(void)573 HAL_StatusTypeDef HAL_FLASH_OB_Lock(void)
574 {
575   /* Set the OPTLOCK Bit to lock the option bytes block access */
576   SET_BIT(FLASH->PECR, FLASH_PECR_OPTLOCK);
577 
578   return HAL_OK;
579 }
580 
581 /**
582   * @brief  Launch the option byte loading.
583   * @note   This function will reset automatically the MCU.
584   * @retval HAL Status
585   */
HAL_FLASH_OB_Launch(void)586 HAL_StatusTypeDef HAL_FLASH_OB_Launch(void)
587 {
588   /* Set the OBL_Launch bit to launch the option byte loading */
589   SET_BIT(FLASH->PECR, FLASH_PECR_OBL_LAUNCH);
590 
591   /* Wait for last operation to be completed */
592   return(FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE));
593 }
594 
595 /**
596   * @}
597   */
598 
599 /** @defgroup FLASH_Exported_Functions_Group3 Peripheral errors functions
600  *  @brief    Peripheral errors functions
601  *
602 @verbatim
603  ===============================================================================
604                       ##### Peripheral Errors functions #####
605  ===============================================================================
606     [..]
607     This subsection permit to get in run-time errors of  the FLASH peripheral.
608 
609 @endverbatim
610   * @{
611   */
612 
613 /**
614   * @brief  Get the specific FLASH error flag.
615   * @retval FLASH_ErrorCode The returned value can be:
616   *            @ref FLASH_Error_Codes
617   */
HAL_FLASH_GetError(void)618 uint32_t HAL_FLASH_GetError(void)
619 {
620    return pFlash.ErrorCode;
621 }
622 
623 /**
624   * @}
625   */
626 
627 /**
628   * @}
629   */
630 
631 /** @addtogroup FLASH_Private_Functions
632  * @{
633  */
634 
635 /**
636   * @brief  Wait for a FLASH operation to complete.
637   * @param  Timeout  maximum flash operation timeout
638   * @retval HAL Status
639   */
FLASH_WaitForLastOperation(uint32_t Timeout)640 HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout)
641 {
642   /* Wait for the FLASH operation to complete by polling on BUSY flag to be reset.
643      Even if the FLASH operation fails, the BUSY flag will be reset and an error
644      flag will be set */
645 
646   uint32_t tickstart = HAL_GetTick();
647 
648   while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY))
649   {
650     if (Timeout != HAL_MAX_DELAY)
651     {
652       if((Timeout == 0U) || ((HAL_GetTick()-tickstart) > Timeout))
653       {
654         return HAL_TIMEOUT;
655       }
656     }
657   }
658 
659   /* Check FLASH End of Operation flag  */
660   if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP))
661   {
662     /* Clear FLASH End of Operation pending bit */
663     __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
664   }
665 
666   if( __HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)     ||
667       __HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)     ||
668       __HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)     ||
669       __HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)    ||
670       __HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)      ||
671       __HAL_FLASH_GET_FLAG(FLASH_FLAG_FWWERR)     ||
672       __HAL_FLASH_GET_FLAG(FLASH_FLAG_NOTZEROERR) )
673   {
674     /*Save the error code*/
675 
676     /* WARNING : On the first cut of STM32L031xx and STM32L041xx devices,
677      *           (RefID = 0x1000) the FLASH_FLAG_OPTVERR bit was not behaving
678      *           as expected. If the user run an application using the first
679      *           cut of the STM32L031xx device or the first cut of the STM32L041xx
680      *           device, this error should be ignored. The revId of the device
681      *           can be retrieved via the HAL_GetREVID() function.
682      *
683      */
684     FLASH_SetErrorCode();
685     return HAL_ERROR;
686   }
687 
688   /* There is no error flag set */
689   return HAL_OK;
690 }
691 
692 
693 /**
694   * @brief  Set the specific FLASH error flag.
695   * @retval None
696   */
FLASH_SetErrorCode(void)697 static void FLASH_SetErrorCode(void)
698 {
699   uint32_t flags = 0;
700 
701   if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR))
702   {
703     pFlash.ErrorCode |= HAL_FLASH_ERROR_WRP;
704     flags |= FLASH_FLAG_WRPERR;
705   }
706   if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))
707   {
708     pFlash.ErrorCode |= HAL_FLASH_ERROR_PGA;
709     flags |= FLASH_FLAG_PGAERR;
710   }
711   if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR))
712   {
713     pFlash.ErrorCode |= HAL_FLASH_ERROR_SIZE;
714     flags |= FLASH_FLAG_SIZERR;
715   }
716   if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR))
717   {
718     /* WARNING : On the first cut of STM32L031xx and STM32L041xx devices,
719      *           (RefID = 0x1000) the FLASH_FLAG_OPTVERR bit was not behaving
720      *           as expected. If the user run an application using the first
721      *           cut of the STM32L031xx device or the first cut of the STM32L041xx
722      *           device, this error should be ignored. The revId of the device
723      *           can be retrieved via the HAL_GetREVID() function.
724      *
725      */
726     pFlash.ErrorCode |= HAL_FLASH_ERROR_OPTV;
727     flags |= FLASH_FLAG_OPTVERR;
728   }
729 
730   if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR))
731   {
732     pFlash.ErrorCode |= HAL_FLASH_ERROR_RD;
733     flags |= FLASH_FLAG_RDERR;
734   }
735   if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_FWWERR))
736   {
737     pFlash.ErrorCode |= HAL_FLASH_ERROR_FWWERR;
738     flags |= HAL_FLASH_ERROR_FWWERR;
739   }
740   if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_NOTZEROERR))
741   {
742     pFlash.ErrorCode |= HAL_FLASH_ERROR_NOTZERO;
743     flags |= FLASH_FLAG_NOTZEROERR;
744   }
745 
746   /* Clear FLASH error pending bits */
747   __HAL_FLASH_CLEAR_FLAG(flags);
748 }
749 /**
750   * @}
751   */
752 
753 /**
754   * @}
755   */
756 
757 #endif /* HAL_FLASH_MODULE_ENABLED */
758 
759 /**
760   * @}
761   */
762 
763