1 /**
2 ******************************************************************************
3 * @file stm32h7xx_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 AXI I-Code and D-Code accesses
18 to the Flash memory. It implements the erase and program Flash memory operations
19 and the read and write protection mechanisms.
20
21 [..] The FLASH 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 266-bits word
27 (10 bits added per flash 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 STM32H7xx 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: 256-bit word only
39 (++) There 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_FLASH_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_OB_Launch() function.
54 In this case, a reset is generated
55 [..]
56 In addition to these functions, this driver includes a set of macros allowing
57 to handle the following operations:
58 (+) Set the latency
59 (+) Enable/Disable the FLASH interrupts
60 (+) Monitor the FLASH flags status
61 [..]
62 (@) For any Flash memory program operation (erase or program), the CPU clock frequency
63 (HCLK) must be at least 1MHz.
64 (@) The contents of the Flash memory are not guaranteed if a device reset occurs during
65 a Flash memory operation.
66 (@) The application can simultaneously request a read and a write operation through each AXI
67 interface.
68 As the Flash memory is divided into two independent banks, the embedded Flash
69 memory interface can drive different operations at the same time on each bank. For
70 example a read, write or erase operation can be executed on bank 1 while another read,
71 write or erase operation is executed on bank 2.
72
73 @endverbatim
74 ******************************************************************************
75 * @attention
76 *
77 * Copyright (c) 2017 STMicroelectronics.
78 * All rights reserved.
79 *
80 * This software is licensed under terms that can be found in the LICENSE file in
81 * the root directory of this software component.
82 * If no LICENSE file comes with this software, it is provided AS-IS.
83 ******************************************************************************
84 */
85
86 /* Includes ------------------------------------------------------------------*/
87 #include "stm32h7xx_hal.h"
88
89 /** @addtogroup STM32H7xx_HAL_Driver
90 * @{
91 */
92
93 /** @defgroup FLASH FLASH
94 * @brief FLASH HAL module driver
95 * @{
96 */
97
98 #ifdef HAL_FLASH_MODULE_ENABLED
99
100 /* Private typedef -----------------------------------------------------------*/
101 /* Private define ------------------------------------------------------------*/
102 /** @addtogroup FLASH_Private_Constants
103 * @{
104 */
105 #define FLASH_TIMEOUT_VALUE 50000U /* 50 s */
106 /**
107 * @}
108 */
109 /* Private macro -------------------------------------------------------------*/
110 /* Private variables ---------------------------------------------------------*/
111 /** @addtogroup FLASH_Private_Variables
112 * @{
113 */
114 FLASH_ProcessTypeDef pFlash;
115 /**
116 * @}
117 */
118 /* Private function prototypes -----------------------------------------------*/
119 /* Exported functions ---------------------------------------------------------*/
120
121 /** @defgroup FLASH_Exported_Functions FLASH Exported functions
122 * @{
123 */
124
125 /** @defgroup FLASH_Exported_Functions_Group1 Programming operation functions
126 * @brief Programming operation functions
127 *
128 @verbatim
129 ===============================================================================
130 ##### Programming operation functions #####
131 ===============================================================================
132 [..]
133 This subsection provides a set of functions allowing to manage the FLASH
134 program operations.
135
136 @endverbatim
137 * @{
138 */
139
140 /**
141 * @brief Program a flash word at a specified address
142 * @param TypeProgram Indicate the way to program at a specified address.
143 * This parameter can be a value of @ref FLASH_Type_Program
144 * @param FlashAddress specifies the address to be programmed.
145 * This parameter shall be aligned to the Flash word:
146 * - 256 bits for STM32H74x/5X devices (8x 32bits words)
147 * - 128 bits for STM32H7Ax/BX devices (4x 32bits words)
148 * - 256 bits for STM32H72x/3X devices (8x 32bits words)
149 * @param DataAddress specifies the address of data to be programmed.
150 * This parameter shall be 32-bit aligned
151 *
152 * @retval HAL_StatusTypeDef HAL Status
153 */
HAL_FLASH_Program(uint32_t TypeProgram,uint32_t FlashAddress,uint32_t DataAddress)154 HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t FlashAddress, uint32_t DataAddress)
155 {
156 HAL_StatusTypeDef status;
157 __IO uint32_t *dest_addr = (__IO uint32_t *)FlashAddress;
158 __IO uint32_t *src_addr = (__IO uint32_t*)DataAddress;
159 uint32_t bank;
160 uint8_t row_index = FLASH_NB_32BITWORD_IN_FLASHWORD;
161
162 /* Check the parameters */
163 assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
164 assert_param(IS_FLASH_PROGRAM_ADDRESS(FlashAddress));
165
166 /* Process Locked */
167 __HAL_LOCK(&pFlash);
168
169 #if defined (FLASH_OPTCR_PG_OTP)
170 if((IS_FLASH_PROGRAM_ADDRESS_BANK1(FlashAddress)) || (IS_FLASH_PROGRAM_ADDRESS_OTP(FlashAddress)))
171 #else
172 if(IS_FLASH_PROGRAM_ADDRESS_BANK1(FlashAddress))
173 #endif /* FLASH_OPTCR_PG_OTP */
174 {
175 bank = FLASH_BANK_1;
176 }
177 #if defined (DUAL_BANK)
178 else if(IS_FLASH_PROGRAM_ADDRESS_BANK2(FlashAddress))
179 {
180 bank = FLASH_BANK_2;
181 }
182 #endif /* DUAL_BANK */
183 else
184 {
185 return HAL_ERROR;
186 }
187
188 /* Reset error code */
189 pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
190
191 /* Wait for last operation to be completed */
192 status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, bank);
193
194 if(status == HAL_OK)
195 {
196 #if defined (DUAL_BANK)
197 if(bank == FLASH_BANK_1)
198 {
199 #if defined (FLASH_OPTCR_PG_OTP)
200 if (TypeProgram == FLASH_TYPEPROGRAM_OTPWORD)
201 {
202 /* Set OTP_PG bit */
203 SET_BIT(FLASH->OPTCR, FLASH_OPTCR_PG_OTP);
204 }
205 else
206 #endif /* FLASH_OPTCR_PG_OTP */
207 {
208 /* Set PG bit */
209 SET_BIT(FLASH->CR1, FLASH_CR_PG);
210 }
211 }
212 else
213 {
214 /* Set PG bit */
215 SET_BIT(FLASH->CR2, FLASH_CR_PG);
216 }
217 #else /* Single Bank */
218 #if defined (FLASH_OPTCR_PG_OTP)
219 if (TypeProgram == FLASH_TYPEPROGRAM_OTPWORD)
220 {
221 /* Set OTP_PG bit */
222 SET_BIT(FLASH->OPTCR, FLASH_OPTCR_PG_OTP);
223 }
224 else
225 #endif /* FLASH_OPTCR_PG_OTP */
226 {
227 /* Set PG bit */
228 SET_BIT(FLASH->CR1, FLASH_CR_PG);
229 }
230 #endif /* DUAL_BANK */
231
232 __ISB();
233 __DSB();
234
235 #if defined (FLASH_OPTCR_PG_OTP)
236 if (TypeProgram == FLASH_TYPEPROGRAM_OTPWORD)
237 {
238 /* Program an OTP word (16 bits) */
239 *(__IO uint16_t *)FlashAddress = *(__IO uint16_t*)DataAddress;
240 }
241 else
242 #endif /* FLASH_OPTCR_PG_OTP */
243 {
244 /* Program the flash word */
245 do
246 {
247 *dest_addr = *src_addr;
248 dest_addr++;
249 src_addr++;
250 row_index--;
251 } while (row_index != 0U);
252 }
253
254 __ISB();
255 __DSB();
256
257 /* Wait for last operation to be completed */
258 status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, bank);
259
260 #if defined (DUAL_BANK)
261 #if defined (FLASH_OPTCR_PG_OTP)
262 if (TypeProgram == FLASH_TYPEPROGRAM_OTPWORD)
263 {
264 /* If the program operation is completed, disable the OTP_PG */
265 CLEAR_BIT(FLASH->OPTCR, FLASH_OPTCR_PG_OTP);
266 }
267 else
268 #endif /* FLASH_OPTCR_PG_OTP */
269 {
270 if(bank == FLASH_BANK_1)
271 {
272 /* If the program operation is completed, disable the PG */
273 CLEAR_BIT(FLASH->CR1, FLASH_CR_PG);
274 }
275 else
276 {
277 /* If the program operation is completed, disable the PG */
278 CLEAR_BIT(FLASH->CR2, FLASH_CR_PG);
279 }
280 }
281 #else /* Single Bank */
282 #if defined (FLASH_OPTCR_PG_OTP)
283 if (TypeProgram == FLASH_TYPEPROGRAM_OTPWORD)
284 {
285 /* If the program operation is completed, disable the OTP_PG */
286 CLEAR_BIT(FLASH->OPTCR, FLASH_OPTCR_PG_OTP);
287 }
288 else
289 #endif /* FLASH_OPTCR_PG_OTP */
290 {
291 /* If the program operation is completed, disable the PG */
292 CLEAR_BIT(FLASH->CR1, FLASH_CR_PG);
293 }
294 #endif /* DUAL_BANK */
295 }
296
297 /* Process Unlocked */
298 __HAL_UNLOCK(&pFlash);
299
300 return status;
301 }
302
303 /**
304 * @brief Program a flash word at a specified address with interrupt enabled.
305 * @param TypeProgram Indicate the way to program at a specified address.
306 * This parameter can be a value of @ref FLASH_Type_Program
307 * @param FlashAddress specifies the address to be programmed.
308 * This parameter shall be aligned to the Flash word:
309 * - 256 bits for STM32H74x/5X devices (8x 32bits words)
310 * - 128 bits for STM32H7Ax/BX devices (4x 32bits words)
311 * - 256 bits for STM32H72x/3X devices (8x 32bits words)
312 * @param DataAddress specifies the address of data to be programmed.
313 * This parameter shall be 32-bit aligned
314 *
315 * @retval HAL Status
316 */
HAL_FLASH_Program_IT(uint32_t TypeProgram,uint32_t FlashAddress,uint32_t DataAddress)317 HAL_StatusTypeDef HAL_FLASH_Program_IT(uint32_t TypeProgram, uint32_t FlashAddress, uint32_t DataAddress)
318 {
319 HAL_StatusTypeDef status;
320 __IO uint32_t *dest_addr = (__IO uint32_t*)FlashAddress;
321 __IO uint32_t *src_addr = (__IO uint32_t*)DataAddress;
322 uint32_t bank;
323 uint8_t row_index = FLASH_NB_32BITWORD_IN_FLASHWORD;
324
325 /* Check the parameters */
326 assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
327 assert_param(IS_FLASH_PROGRAM_ADDRESS(FlashAddress));
328
329 /* Process Locked */
330 __HAL_LOCK(&pFlash);
331
332 /* Reset error code */
333 pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
334
335 #if defined (FLASH_OPTCR_PG_OTP)
336 if((IS_FLASH_PROGRAM_ADDRESS_BANK1(FlashAddress)) || (IS_FLASH_PROGRAM_ADDRESS_OTP(FlashAddress)))
337 #else
338 if(IS_FLASH_PROGRAM_ADDRESS_BANK1(FlashAddress))
339 #endif /* FLASH_OPTCR_PG_OTP */
340 {
341 bank = FLASH_BANK_1;
342 }
343 #if defined (DUAL_BANK)
344 else if(IS_FLASH_PROGRAM_ADDRESS_BANK2(FlashAddress))
345 {
346 bank = FLASH_BANK_2;
347 }
348 #endif /* DUAL_BANK */
349 else
350 {
351 return HAL_ERROR;
352 }
353
354 /* Wait for last operation to be completed */
355 status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, bank);
356
357 if (status != HAL_OK)
358 {
359 /* Process Unlocked */
360 __HAL_UNLOCK(&pFlash);
361 }
362 else
363 {
364 pFlash.Address = FlashAddress;
365
366 #if defined (DUAL_BANK)
367 if(bank == FLASH_BANK_1)
368 {
369 /* Set internal variables used by the IRQ handler */
370 pFlash.ProcedureOnGoing = FLASH_PROC_PROGRAM_BANK1;
371
372 #if defined (FLASH_OPTCR_PG_OTP)
373 if (TypeProgram == FLASH_TYPEPROGRAM_OTPWORD)
374 {
375 /* Set OTP_PG bit */
376 SET_BIT(FLASH->OPTCR, FLASH_OPTCR_PG_OTP);
377 }
378 else
379 #endif /* FLASH_OPTCR_PG_OTP */
380 {
381 /* Set PG bit */
382 SET_BIT(FLASH->CR1, FLASH_CR_PG);
383 }
384
385 /* Enable End of Operation and Error interrupts for Bank 1 */
386 #if defined (FLASH_CR_OPERRIE)
387 __HAL_FLASH_ENABLE_IT_BANK1(FLASH_IT_EOP_BANK1 | FLASH_IT_WRPERR_BANK1 | FLASH_IT_PGSERR_BANK1 | \
388 FLASH_IT_STRBERR_BANK1 | FLASH_IT_INCERR_BANK1 | FLASH_IT_OPERR_BANK1);
389 #else
390 __HAL_FLASH_ENABLE_IT_BANK1(FLASH_IT_EOP_BANK1 | FLASH_IT_WRPERR_BANK1 | FLASH_IT_PGSERR_BANK1 | \
391 FLASH_IT_STRBERR_BANK1 | FLASH_IT_INCERR_BANK1);
392 #endif /* FLASH_CR_OPERRIE */
393 }
394 else
395 {
396 /* Set internal variables used by the IRQ handler */
397 pFlash.ProcedureOnGoing = FLASH_PROC_PROGRAM_BANK2;
398
399 /* Set PG bit */
400 SET_BIT(FLASH->CR2, FLASH_CR_PG);
401
402 /* Enable End of Operation and Error interrupts for Bank2 */
403 #if defined (FLASH_CR_OPERRIE)
404 __HAL_FLASH_ENABLE_IT_BANK2(FLASH_IT_EOP_BANK2 | FLASH_IT_WRPERR_BANK2 | FLASH_IT_PGSERR_BANK2 | \
405 FLASH_IT_STRBERR_BANK2 | FLASH_IT_INCERR_BANK2 | FLASH_IT_OPERR_BANK2);
406 #else
407 __HAL_FLASH_ENABLE_IT_BANK2(FLASH_IT_EOP_BANK2 | FLASH_IT_WRPERR_BANK2 | FLASH_IT_PGSERR_BANK2 | \
408 FLASH_IT_STRBERR_BANK2 | FLASH_IT_INCERR_BANK2);
409 #endif /* FLASH_CR_OPERRIE */
410 }
411 #else /* Single Bank */
412 /* Set internal variables used by the IRQ handler */
413 pFlash.ProcedureOnGoing = FLASH_PROC_PROGRAM_BANK1;
414
415 #if defined (FLASH_OPTCR_PG_OTP)
416 if (TypeProgram == FLASH_TYPEPROGRAM_OTPWORD)
417 {
418 /* Set OTP_PG bit */
419 SET_BIT(FLASH->OPTCR, FLASH_OPTCR_PG_OTP);
420 }
421 else
422 #endif /* FLASH_OPTCR_PG_OTP */
423 {
424 /* Set PG bit */
425 SET_BIT(FLASH->CR1, FLASH_CR_PG);
426 }
427
428 /* Enable End of Operation and Error interrupts for Bank 1 */
429 #if defined (FLASH_CR_OPERRIE)
430 __HAL_FLASH_ENABLE_IT_BANK1(FLASH_IT_EOP_BANK1 | FLASH_IT_WRPERR_BANK1 | FLASH_IT_PGSERR_BANK1 | \
431 FLASH_IT_STRBERR_BANK1 | FLASH_IT_INCERR_BANK1 | FLASH_IT_OPERR_BANK1);
432 #else
433 __HAL_FLASH_ENABLE_IT_BANK1(FLASH_IT_EOP_BANK1 | FLASH_IT_WRPERR_BANK1 | FLASH_IT_PGSERR_BANK1 | \
434 FLASH_IT_STRBERR_BANK1 | FLASH_IT_INCERR_BANK1);
435 #endif /* FLASH_CR_OPERRIE */
436 #endif /* DUAL_BANK */
437
438 __ISB();
439 __DSB();
440
441 #if defined (FLASH_OPTCR_PG_OTP)
442 if (TypeProgram == FLASH_TYPEPROGRAM_OTPWORD)
443 {
444 /* Program an OTP word (16 bits) */
445 *(__IO uint16_t *)FlashAddress = *(__IO uint16_t*)DataAddress;
446 }
447 else
448 #endif /* FLASH_OPTCR_PG_OTP */
449 {
450 /* Program the flash word */
451 do
452 {
453 *dest_addr = *src_addr;
454 dest_addr++;
455 src_addr++;
456 row_index--;
457 } while (row_index != 0U);
458 }
459
460 __ISB();
461 __DSB();
462 }
463
464 return status;
465 }
466
467 /**
468 * @brief This function handles FLASH interrupt request.
469 * @retval None
470 */
HAL_FLASH_IRQHandler(void)471 void HAL_FLASH_IRQHandler(void)
472 {
473 uint32_t temp;
474 uint32_t errorflag;
475 FLASH_ProcedureTypeDef procedure;
476
477 /* Check FLASH Bank1 End of Operation flag */
478 if(__HAL_FLASH_GET_FLAG_BANK1(FLASH_SR_EOP) != RESET)
479 {
480 if(pFlash.ProcedureOnGoing == FLASH_PROC_SECTERASE_BANK1)
481 {
482 /* Nb of sector to erased can be decreased */
483 pFlash.NbSectorsToErase--;
484
485 /* Check if there are still sectors to erase */
486 if(pFlash.NbSectorsToErase != 0U)
487 {
488 /* Indicate user which sector has been erased */
489 HAL_FLASH_EndOfOperationCallback(pFlash.Sector);
490
491 /* Clear bank 1 End of Operation pending bit */
492 __HAL_FLASH_CLEAR_FLAG_BANK1(FLASH_FLAG_EOP_BANK1);
493
494 /* Increment sector number */
495 pFlash.Sector++;
496 temp = pFlash.Sector;
497 FLASH_Erase_Sector(temp, FLASH_BANK_1, pFlash.VoltageForErase);
498 }
499 else
500 {
501 /* No more sectors to Erase, user callback can be called */
502 /* Reset Sector and stop Erase sectors procedure */
503 pFlash.Sector = 0xFFFFFFFFU;
504 pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
505
506 /* FLASH EOP interrupt user callback */
507 HAL_FLASH_EndOfOperationCallback(pFlash.Sector);
508
509 /* Clear FLASH End of Operation pending bit */
510 __HAL_FLASH_CLEAR_FLAG_BANK1(FLASH_FLAG_EOP_BANK1);
511 }
512 }
513 else
514 {
515 procedure = pFlash.ProcedureOnGoing;
516
517 if((procedure == FLASH_PROC_MASSERASE_BANK1) || (procedure == FLASH_PROC_ALLBANK_MASSERASE))
518 {
519 /* MassErase ended. Return the selected bank */
520 /* FLASH EOP interrupt user callback */
521 HAL_FLASH_EndOfOperationCallback(FLASH_BANK_1);
522 }
523 else if(procedure == FLASH_PROC_PROGRAM_BANK1)
524 {
525 /* Program ended. Return the selected address */
526 /* FLASH EOP interrupt user callback */
527 HAL_FLASH_EndOfOperationCallback(pFlash.Address);
528 }
529 else
530 {
531 /* Nothing to do */
532 }
533
534 if((procedure != FLASH_PROC_SECTERASE_BANK2) && \
535 (procedure != FLASH_PROC_MASSERASE_BANK2) && \
536 (procedure != FLASH_PROC_PROGRAM_BANK2))
537 {
538 pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
539 /* Clear FLASH End of Operation pending bit */
540 __HAL_FLASH_CLEAR_FLAG_BANK1(FLASH_FLAG_EOP_BANK1);
541 }
542 }
543 }
544
545 #if defined (DUAL_BANK)
546 /* Check FLASH Bank2 End of Operation flag */
547 if(__HAL_FLASH_GET_FLAG_BANK2(FLASH_SR_EOP) != RESET)
548 {
549 if(pFlash.ProcedureOnGoing == FLASH_PROC_SECTERASE_BANK2)
550 {
551 /*Nb of sector to erased can be decreased*/
552 pFlash.NbSectorsToErase--;
553
554 /* Check if there are still sectors to erase*/
555 if(pFlash.NbSectorsToErase != 0U)
556 {
557 /*Indicate user which sector has been erased*/
558 HAL_FLASH_EndOfOperationCallback(pFlash.Sector);
559
560 /* Clear bank 2 End of Operation pending bit */
561 __HAL_FLASH_CLEAR_FLAG_BANK2(FLASH_FLAG_EOP_BANK2);
562
563 /*Increment sector number*/
564 pFlash.Sector++;
565 temp = pFlash.Sector;
566 FLASH_Erase_Sector(temp, FLASH_BANK_2, pFlash.VoltageForErase);
567 }
568 else
569 {
570 /* No more sectors to Erase, user callback can be called */
571 /* Reset Sector and stop Erase sectors procedure */
572 pFlash.Sector = 0xFFFFFFFFU;
573 pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
574
575 /* FLASH EOP interrupt user callback */
576 HAL_FLASH_EndOfOperationCallback(pFlash.Sector);
577
578 /* Clear FLASH End of Operation pending bit */
579 __HAL_FLASH_CLEAR_FLAG_BANK2(FLASH_FLAG_EOP_BANK2);
580 }
581 }
582 else
583 {
584 procedure = pFlash.ProcedureOnGoing;
585
586 if((procedure == FLASH_PROC_MASSERASE_BANK2) || (procedure == FLASH_PROC_ALLBANK_MASSERASE))
587 {
588 /*MassErase ended. Return the selected bank*/
589 /* FLASH EOP interrupt user callback */
590 HAL_FLASH_EndOfOperationCallback(FLASH_BANK_2);
591 }
592 else if(procedure == FLASH_PROC_PROGRAM_BANK2)
593 {
594 /* Program ended. Return the selected address */
595 /* FLASH EOP interrupt user callback */
596 HAL_FLASH_EndOfOperationCallback(pFlash.Address);
597 }
598 else
599 {
600 /* Nothing to do */
601 }
602
603 if((procedure != FLASH_PROC_SECTERASE_BANK1) && \
604 (procedure != FLASH_PROC_MASSERASE_BANK1) && \
605 (procedure != FLASH_PROC_PROGRAM_BANK1))
606 {
607 pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
608 /* Clear FLASH End of Operation pending bit */
609 __HAL_FLASH_CLEAR_FLAG_BANK2(FLASH_FLAG_EOP_BANK2);
610 }
611 }
612 }
613 #endif /* DUAL_BANK */
614
615 /* Check FLASH Bank1 operation error flags */
616 #if defined (FLASH_SR_OPERR)
617 errorflag = FLASH->SR1 & (FLASH_FLAG_WRPERR_BANK1 | FLASH_FLAG_PGSERR_BANK1 | FLASH_FLAG_STRBERR_BANK1 | \
618 FLASH_FLAG_INCERR_BANK1 | FLASH_FLAG_OPERR_BANK1);
619 #else
620 errorflag = FLASH->SR1 & (FLASH_FLAG_WRPERR_BANK1 | FLASH_FLAG_PGSERR_BANK1 | FLASH_FLAG_STRBERR_BANK1 | \
621 FLASH_FLAG_INCERR_BANK1);
622 #endif /* FLASH_SR_OPERR */
623
624 if(errorflag != 0U)
625 {
626 /* Save the error code */
627 pFlash.ErrorCode |= errorflag;
628
629 /* Clear error programming flags */
630 __HAL_FLASH_CLEAR_FLAG_BANK1(errorflag);
631
632 procedure = pFlash.ProcedureOnGoing;
633
634 if(procedure == FLASH_PROC_SECTERASE_BANK1)
635 {
636 /* Return the faulty sector */
637 temp = pFlash.Sector;
638 pFlash.Sector = 0xFFFFFFFFU;
639 }
640 else if((procedure == FLASH_PROC_MASSERASE_BANK1) || (procedure == FLASH_PROC_ALLBANK_MASSERASE))
641 {
642 /* Return the faulty bank */
643 temp = FLASH_BANK_1;
644 }
645 else
646 {
647 /* Return the faulty address */
648 temp = pFlash.Address;
649 }
650
651 /* Stop the procedure ongoing*/
652 pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
653
654 /* FLASH error interrupt user callback */
655 HAL_FLASH_OperationErrorCallback(temp);
656 }
657
658 #if defined (DUAL_BANK)
659 /* Check FLASH Bank2 operation error flags */
660 #if defined (FLASH_SR_OPERR)
661 errorflag = FLASH->SR2 & ((FLASH_FLAG_WRPERR_BANK2 | FLASH_FLAG_PGSERR_BANK2 | FLASH_FLAG_STRBERR_BANK2 | \
662 FLASH_FLAG_INCERR_BANK2 | FLASH_FLAG_OPERR_BANK2) & 0x7FFFFFFFU);
663 #else
664 errorflag = FLASH->SR2 & ((FLASH_FLAG_WRPERR_BANK2 | FLASH_FLAG_PGSERR_BANK2 | FLASH_FLAG_STRBERR_BANK2 | \
665 FLASH_FLAG_INCERR_BANK2) & 0x7FFFFFFFU);
666 #endif /* FLASH_SR_OPERR */
667
668 if(errorflag != 0U)
669 {
670 /* Save the error code */
671 pFlash.ErrorCode |= (errorflag | 0x80000000U);
672
673 /* Clear error programming flags */
674 __HAL_FLASH_CLEAR_FLAG_BANK2(errorflag);
675
676 procedure = pFlash.ProcedureOnGoing;
677
678 if(procedure== FLASH_PROC_SECTERASE_BANK2)
679 {
680 /*return the faulty sector*/
681 temp = pFlash.Sector;
682 pFlash.Sector = 0xFFFFFFFFU;
683 }
684 else if((procedure == FLASH_PROC_MASSERASE_BANK2) || (procedure == FLASH_PROC_ALLBANK_MASSERASE))
685 {
686 /*return the faulty bank*/
687 temp = FLASH_BANK_2;
688 }
689 else
690 {
691 /*return the faulty address*/
692 temp = pFlash.Address;
693 }
694
695 /*Stop the procedure ongoing*/
696 pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
697
698 /* FLASH error interrupt user callback */
699 HAL_FLASH_OperationErrorCallback(temp);
700 }
701 #endif /* DUAL_BANK */
702
703 if(pFlash.ProcedureOnGoing == FLASH_PROC_NONE)
704 {
705 #if defined (FLASH_CR_OPERRIE)
706 /* Disable Bank1 Operation and Error source interrupt */
707 __HAL_FLASH_DISABLE_IT_BANK1(FLASH_IT_EOP_BANK1 | FLASH_IT_WRPERR_BANK1 | FLASH_IT_PGSERR_BANK1 | \
708 FLASH_IT_STRBERR_BANK1 | FLASH_IT_INCERR_BANK1 | FLASH_IT_OPERR_BANK1);
709
710 #if defined (DUAL_BANK)
711 /* Disable Bank2 Operation and Error source interrupt */
712 __HAL_FLASH_DISABLE_IT_BANK2(FLASH_IT_EOP_BANK2 | FLASH_IT_WRPERR_BANK2 | FLASH_IT_PGSERR_BANK2 | \
713 FLASH_IT_STRBERR_BANK2 | FLASH_IT_INCERR_BANK2 | FLASH_IT_OPERR_BANK2);
714 #endif /* DUAL_BANK */
715 #else
716 /* Disable Bank1 Operation and Error source interrupt */
717 __HAL_FLASH_DISABLE_IT_BANK1(FLASH_IT_EOP_BANK1 | FLASH_IT_WRPERR_BANK1 | FLASH_IT_PGSERR_BANK1 | \
718 FLASH_IT_STRBERR_BANK1 | FLASH_IT_INCERR_BANK1);
719
720 #if defined (DUAL_BANK)
721 /* Disable Bank2 Operation and Error source interrupt */
722 __HAL_FLASH_DISABLE_IT_BANK2(FLASH_IT_EOP_BANK2 | FLASH_IT_WRPERR_BANK2 | FLASH_IT_PGSERR_BANK2 | \
723 FLASH_IT_STRBERR_BANK2 | FLASH_IT_INCERR_BANK2);
724 #endif /* DUAL_BANK */
725 #endif /* FLASH_CR_OPERRIE */
726
727 /* Process Unlocked */
728 __HAL_UNLOCK(&pFlash);
729 }
730 }
731
732 /**
733 * @brief FLASH end of operation interrupt callback
734 * @param ReturnValue The value saved in this parameter depends on the ongoing procedure
735 * Mass Erase: Bank number which has been requested to erase
736 * Sectors Erase: Sector which has been erased
737 * (if 0xFFFFFFFF, it means that all the selected sectors have been erased)
738 * Program: Address which was selected for data program
739 * @retval None
740 */
HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue)741 __weak void HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue)
742 {
743 /* Prevent unused argument(s) compilation warning */
744 UNUSED(ReturnValue);
745
746 /* NOTE : This function Should not be modified, when the callback is needed,
747 the HAL_FLASH_EndOfOperationCallback could be implemented in the user file
748 */
749 }
750
751 /**
752 * @brief FLASH operation error interrupt callback
753 * @param ReturnValue The value saved in this parameter depends on the ongoing procedure
754 * Mass Erase: Bank number which has been requested to erase
755 * Sectors Erase: Sector number which returned an error
756 * Program: Address which was selected for data program
757 * @retval None
758 */
HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue)759 __weak void HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue)
760 {
761 /* Prevent unused argument(s) compilation warning */
762 UNUSED(ReturnValue);
763
764 /* NOTE : This function Should not be modified, when the callback is needed,
765 the HAL_FLASH_OperationErrorCallback could be implemented in the user file
766 */
767 }
768
769 /**
770 * @}
771 */
772
773 /** @defgroup FLASH_Exported_Functions_Group2 Peripheral Control functions
774 * @brief Management functions
775 *
776 @verbatim
777 ===============================================================================
778 ##### Peripheral Control functions #####
779 ===============================================================================
780 [..]
781 This subsection provides a set of functions allowing to control the FLASH
782 memory operations.
783
784 @endverbatim
785 * @{
786 */
787
788 /**
789 * @brief Unlock the FLASH control registers access
790 * @retval HAL Status
791 */
HAL_FLASH_Unlock(void)792 HAL_StatusTypeDef HAL_FLASH_Unlock(void)
793 {
794 if(READ_BIT(FLASH->CR1, FLASH_CR_LOCK) != 0U)
795 {
796 /* Authorize the FLASH Bank1 Registers access */
797 WRITE_REG(FLASH->KEYR1, FLASH_KEY1);
798 WRITE_REG(FLASH->KEYR1, FLASH_KEY2);
799
800 /* Verify Flash Bank1 is unlocked */
801 if (READ_BIT(FLASH->CR1, FLASH_CR_LOCK) != 0U)
802 {
803 return HAL_ERROR;
804 }
805 }
806
807 #if defined (DUAL_BANK)
808 if(READ_BIT(FLASH->CR2, FLASH_CR_LOCK) != 0U)
809 {
810 /* Authorize the FLASH Bank2 Registers access */
811 WRITE_REG(FLASH->KEYR2, FLASH_KEY1);
812 WRITE_REG(FLASH->KEYR2, FLASH_KEY2);
813
814 /* Verify Flash Bank2 is unlocked */
815 if (READ_BIT(FLASH->CR2, FLASH_CR_LOCK) != 0U)
816 {
817 return HAL_ERROR;
818 }
819 }
820 #endif /* DUAL_BANK */
821
822 return HAL_OK;
823 }
824
825 /**
826 * @brief Locks the FLASH control registers access
827 * @retval HAL Status
828 */
HAL_FLASH_Lock(void)829 HAL_StatusTypeDef HAL_FLASH_Lock(void)
830 {
831 /* Set the LOCK Bit to lock the FLASH Bank1 Control Register access */
832 SET_BIT(FLASH->CR1, FLASH_CR_LOCK);
833
834 /* Verify Flash Bank1 is locked */
835 if (READ_BIT(FLASH->CR1, FLASH_CR_LOCK) == 0U)
836 {
837 return HAL_ERROR;
838 }
839
840 #if defined (DUAL_BANK)
841 /* Set the LOCK Bit to lock the FLASH Bank2 Control Register access */
842 SET_BIT(FLASH->CR2, FLASH_CR_LOCK);
843
844 /* Verify Flash Bank2 is locked */
845 if (READ_BIT(FLASH->CR2, FLASH_CR_LOCK) == 0U)
846 {
847 return HAL_ERROR;
848 }
849 #endif /* DUAL_BANK */
850
851 return HAL_OK;
852 }
853
854 /**
855 * @brief Unlock the FLASH Option Control Registers access.
856 * @retval HAL Status
857 */
HAL_FLASH_OB_Unlock(void)858 HAL_StatusTypeDef HAL_FLASH_OB_Unlock(void)
859 {
860 if(READ_BIT(FLASH->OPTCR, FLASH_OPTCR_OPTLOCK) != 0U)
861 {
862 /* Authorizes the Option Byte registers programming */
863 WRITE_REG(FLASH->OPTKEYR, FLASH_OPT_KEY1);
864 WRITE_REG(FLASH->OPTKEYR, FLASH_OPT_KEY2);
865
866 /* Verify that the Option Bytes are unlocked */
867 if (READ_BIT(FLASH->OPTCR, FLASH_OPTCR_OPTLOCK) != 0U)
868 {
869 return HAL_ERROR;
870 }
871 }
872
873 return HAL_OK;
874 }
875
876 /**
877 * @brief Lock the FLASH Option Control Registers access.
878 * @retval HAL Status
879 */
HAL_FLASH_OB_Lock(void)880 HAL_StatusTypeDef HAL_FLASH_OB_Lock(void)
881 {
882 /* Set the OPTLOCK Bit to lock the FLASH Option Byte Registers access */
883 SET_BIT(FLASH->OPTCR, FLASH_OPTCR_OPTLOCK);
884
885 /* Verify that the Option Bytes are locked */
886 if (READ_BIT(FLASH->OPTCR, FLASH_OPTCR_OPTLOCK) == 0U)
887 {
888 return HAL_ERROR;
889 }
890
891 return HAL_OK;
892 }
893
894 /**
895 * @brief Launch the option bytes loading.
896 * @retval HAL Status
897 */
HAL_FLASH_OB_Launch(void)898 HAL_StatusTypeDef HAL_FLASH_OB_Launch(void)
899 {
900 HAL_StatusTypeDef status;
901
902 /* Wait for CRC computation to be completed */
903 if (FLASH_CRC_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, FLASH_BANK_1) != HAL_OK)
904 {
905 status = HAL_ERROR;
906 }
907 #if defined (DUAL_BANK)
908 else if (FLASH_CRC_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, FLASH_BANK_2) != HAL_OK)
909 {
910 status = HAL_ERROR;
911 }
912 #endif /* DUAL_BANK */
913 else
914 {
915 status = HAL_OK;
916 }
917
918 if (status == HAL_OK)
919 {
920 /* Set OPTSTRT Bit */
921 SET_BIT(FLASH->OPTCR, FLASH_OPTCR_OPTSTART);
922
923 /* Wait for OB change operation to be completed */
924 status = FLASH_OB_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
925 }
926
927 return status;
928 }
929
930 /**
931 * @}
932 */
933
934 /** @defgroup FLASH_Exported_Functions_Group3 Peripheral State and Errors functions
935 * @brief Peripheral Errors functions
936 *
937 @verbatim
938 ===============================================================================
939 ##### Peripheral Errors functions #####
940 ===============================================================================
941 [..]
942 This subsection permits to get in run-time Errors of the FLASH peripheral.
943
944 @endverbatim
945 * @{
946 */
947
948 /**
949 * @brief Get the specific FLASH error flag.
950 * @retval HAL_FLASH_ERRORCode The returned value can be:
951 * @arg HAL_FLASH_ERROR_NONE : No error set
952 *
953 * @arg HAL_FLASH_ERROR_WRP_BANK1 : Write Protection Error on Bank 1
954 * @arg HAL_FLASH_ERROR_PGS_BANK1 : Program Sequence Error on Bank 1
955 * @arg HAL_FLASH_ERROR_STRB_BANK1 : Strobe Error on Bank 1
956 * @arg HAL_FLASH_ERROR_INC_BANK1 : Inconsistency Error on Bank 1
957 * @arg HAL_FLASH_ERROR_OPE_BANK1 : Operation Error on Bank 1
958 * @arg HAL_FLASH_ERROR_RDP_BANK1 : Read Protection Error on Bank 1
959 * @arg HAL_FLASH_ERROR_RDS_BANK1 : Read Secured Error on Bank 1
960 * @arg HAL_FLASH_ERROR_SNECC_BANK1: ECC Single Correction Error on Bank 1
961 * @arg HAL_FLASH_ERROR_DBECC_BANK1: ECC Double Detection Error on Bank 1
962 * @arg HAL_FLASH_ERROR_CRCRD_BANK1: CRC Read Error on Bank 1
963 *
964 * @arg HAL_FLASH_ERROR_WRP_BANK2 : Write Protection Error on Bank 2
965 * @arg HAL_FLASH_ERROR_PGS_BANK2 : Program Sequence Error on Bank 2
966 * @arg HAL_FLASH_ERROR_STRB_BANK2 : Strobe Error on Bank 2
967 * @arg HAL_FLASH_ERROR_INC_BANK2 : Inconsistency Error on Bank 2
968 * @arg HAL_FLASH_ERROR_OPE_BANK2 : Operation Error on Bank 2
969 * @arg HAL_FLASH_ERROR_RDP_BANK2 : Read Protection Error on Bank 2
970 * @arg HAL_FLASH_ERROR_RDS_BANK2 : Read Secured Error on Bank 2
971 * @arg HAL_FLASH_ERROR_SNECC_BANK2: SNECC Error on Bank 2
972 * @arg HAL_FLASH_ERROR_DBECC_BANK2: Double Detection ECC on Bank 2
973 * @arg HAL_FLASH_ERROR_CRCRD_BANK2: CRC Read Error on Bank 2
974 */
975
HAL_FLASH_GetError(void)976 uint32_t HAL_FLASH_GetError(void)
977 {
978 return pFlash.ErrorCode;
979 }
980
981 /**
982 * @}
983 */
984
985 /**
986 * @}
987 */
988
989 /* Private functions ---------------------------------------------------------*/
990
991 /** @addtogroup FLASH_Private_Functions
992 * @{
993 */
994
995 /**
996 * @brief Wait for a FLASH operation to complete.
997 * @param Timeout maximum flash operation timeout
998 * @param Bank flash FLASH_BANK_1 or FLASH_BANK_2
999 * @retval HAL_StatusTypeDef HAL Status
1000 */
FLASH_WaitForLastOperation(uint32_t Timeout,uint32_t Bank)1001 HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout, uint32_t Bank)
1002 {
1003 /* Wait for the FLASH operation to complete by polling on QW flag to be reset.
1004 Even if the FLASH operation fails, the QW flag will be reset and an error
1005 flag will be set */
1006
1007 uint32_t bsyflag = FLASH_FLAG_QW_BANK1;
1008 uint32_t errorflag = 0;
1009 uint32_t tickstart = HAL_GetTick();
1010
1011 assert_param(IS_FLASH_BANK_EXCLUSIVE(Bank));
1012
1013 #if defined (DUAL_BANK)
1014
1015 if (Bank == FLASH_BANK_2)
1016 {
1017 /* Select bsyflag depending on Bank */
1018 bsyflag = FLASH_FLAG_QW_BANK2;
1019 }
1020 #endif /* DUAL_BANK */
1021
1022 while(__HAL_FLASH_GET_FLAG(bsyflag))
1023 {
1024 if(Timeout != HAL_MAX_DELAY)
1025 {
1026 if(((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
1027 {
1028 return HAL_TIMEOUT;
1029 }
1030 }
1031 }
1032
1033 /* Get Error Flags */
1034 if (Bank == FLASH_BANK_1)
1035 {
1036 errorflag = FLASH->SR1 & FLASH_FLAG_ALL_ERRORS_BANK1;
1037 }
1038 #if defined (DUAL_BANK)
1039 else
1040 {
1041 errorflag = (FLASH->SR2 & FLASH_FLAG_ALL_ERRORS_BANK2) | 0x80000000U;
1042 }
1043 #endif /* DUAL_BANK */
1044
1045 /* In case of error reported in Flash SR1 or SR2 register */
1046 if((errorflag & 0x7FFFFFFFU) != 0U)
1047 {
1048 /*Save the error code*/
1049 pFlash.ErrorCode |= errorflag;
1050
1051 /* Clear error programming flags */
1052 __HAL_FLASH_CLEAR_FLAG(errorflag);
1053
1054 return HAL_ERROR;
1055 }
1056
1057 /* Check FLASH End of Operation flag */
1058 if(Bank == FLASH_BANK_1)
1059 {
1060 if (__HAL_FLASH_GET_FLAG_BANK1(FLASH_FLAG_EOP_BANK1))
1061 {
1062 /* Clear FLASH End of Operation pending bit */
1063 __HAL_FLASH_CLEAR_FLAG_BANK1(FLASH_FLAG_EOP_BANK1);
1064 }
1065 }
1066 #if defined (DUAL_BANK)
1067 else
1068 {
1069 if (__HAL_FLASH_GET_FLAG_BANK2(FLASH_FLAG_EOP_BANK2))
1070 {
1071 /* Clear FLASH End of Operation pending bit */
1072 __HAL_FLASH_CLEAR_FLAG_BANK2(FLASH_FLAG_EOP_BANK2);
1073 }
1074 }
1075 #endif /* DUAL_BANK */
1076
1077 return HAL_OK;
1078 }
1079
1080 /**
1081 * @brief Wait for a FLASH Option Bytes change operation to complete.
1082 * @param Timeout maximum flash operation timeout
1083 * @retval HAL_StatusTypeDef HAL Status
1084 */
FLASH_OB_WaitForLastOperation(uint32_t Timeout)1085 HAL_StatusTypeDef FLASH_OB_WaitForLastOperation(uint32_t Timeout)
1086 {
1087 /* Get timeout */
1088 uint32_t tickstart = HAL_GetTick();
1089
1090 /* Wait for the FLASH Option Bytes change operation to complete by polling on OPT_BUSY flag to be reset */
1091 while(READ_BIT(FLASH->OPTSR_CUR, FLASH_OPTSR_OPT_BUSY) != 0U)
1092 {
1093 if(Timeout != HAL_MAX_DELAY)
1094 {
1095 if(((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
1096 {
1097 return HAL_TIMEOUT;
1098 }
1099 }
1100 }
1101
1102 /* Check option byte change error */
1103 if(READ_BIT(FLASH->OPTSR_CUR, FLASH_OPTSR_OPTCHANGEERR) != 0U)
1104 {
1105 /* Save the error code */
1106 pFlash.ErrorCode |= HAL_FLASH_ERROR_OB_CHANGE;
1107
1108 /* Clear the OB error flag */
1109 FLASH->OPTCCR |= FLASH_OPTCCR_CLR_OPTCHANGEERR;
1110
1111 return HAL_ERROR;
1112 }
1113
1114 /* If there is no error flag set */
1115 return HAL_OK;
1116 }
1117
1118 /**
1119 * @brief Wait for a FLASH CRC computation to complete.
1120 * @param Timeout maximum flash operation timeout
1121 * @param Bank flash FLASH_BANK_1 or FLASH_BANK_2
1122 * @retval HAL_StatusTypeDef HAL Status
1123 */
FLASH_CRC_WaitForLastOperation(uint32_t Timeout,uint32_t Bank)1124 HAL_StatusTypeDef FLASH_CRC_WaitForLastOperation(uint32_t Timeout, uint32_t Bank)
1125 {
1126 uint32_t bsyflag;
1127 uint32_t tickstart = HAL_GetTick();
1128
1129 assert_param(IS_FLASH_BANK_EXCLUSIVE(Bank));
1130
1131 /* Select bsyflag depending on Bank */
1132 if(Bank == FLASH_BANK_1)
1133 {
1134 bsyflag = FLASH_FLAG_CRC_BUSY_BANK1;
1135 }
1136 else
1137 {
1138 bsyflag = FLASH_FLAG_CRC_BUSY_BANK2;
1139 }
1140
1141 /* Wait for the FLASH CRC computation to complete by polling on CRC_BUSY flag to be reset */
1142 while(__HAL_FLASH_GET_FLAG(bsyflag))
1143 {
1144 if(Timeout != HAL_MAX_DELAY)
1145 {
1146 if(((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
1147 {
1148 return HAL_TIMEOUT;
1149 }
1150 }
1151 }
1152
1153 /* Check FLASH CRC read error flag */
1154 if(Bank == FLASH_BANK_1)
1155 {
1156 if (__HAL_FLASH_GET_FLAG_BANK1(FLASH_FLAG_CRCRDERR_BANK1))
1157 {
1158 /* Save the error code */
1159 pFlash.ErrorCode |= HAL_FLASH_ERROR_CRCRD_BANK1;
1160
1161 /* Clear FLASH CRC read error pending bit */
1162 __HAL_FLASH_CLEAR_FLAG_BANK1(FLASH_FLAG_CRCRDERR_BANK1);
1163
1164 return HAL_ERROR;
1165 }
1166 }
1167 #if defined (DUAL_BANK)
1168 else
1169 {
1170 if (__HAL_FLASH_GET_FLAG_BANK2(FLASH_FLAG_CRCRDERR_BANK2))
1171 {
1172 /* Save the error code */
1173 pFlash.ErrorCode |= HAL_FLASH_ERROR_CRCRD_BANK2;
1174
1175 /* Clear FLASH CRC read error pending bit */
1176 __HAL_FLASH_CLEAR_FLAG_BANK2(FLASH_FLAG_CRCRDERR_BANK2);
1177
1178 return HAL_ERROR;
1179 }
1180 }
1181 #endif /* DUAL_BANK */
1182
1183 /* If there is no error flag set */
1184 return HAL_OK;
1185 }
1186
1187 /**
1188 * @}
1189 */
1190
1191 #endif /* HAL_FLASH_MODULE_ENABLED */
1192
1193 /**
1194 * @}
1195 */
1196
1197 /**
1198 * @}
1199 */
1200
1201