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