1 /**
2   ******************************************************************************
3   * @file    stm32g0xx_hal_flash_ex.c
4   * @author  MCD Application Team
5   * @brief   Extended FLASH HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          functionalities of the FLASH extended peripheral:
8   *           + Extended programming operations functions
9   *
10  @verbatim
11  ==============================================================================
12                    ##### Flash Extended features #####
13   ==============================================================================
14 
15   [..] Comparing to other previous devices, the FLASH interface for STM32G0xx
16        devices contains the following additional features
17 
18        (+) Capacity up to 128 Kbytes with single bank architecture supporting read-while-write
19            capability (RWW)
20        (+) Single bank memory organization
21        (+) PCROP protection
22 
23                         ##### How to use this driver #####
24  ==============================================================================
25   [..] This driver provides functions to configure and program the FLASH memory
26        of all STM32G0xx devices. It includes
27       (#) Flash Memory Erase functions:
28            (++) Lock and Unlock the FLASH interface using HAL_FLASH_Unlock() and
29                 HAL_FLASH_Lock() functions
30            (++) Erase function: Erase page, erase all sectors
31            (++) There are two modes of erase :
32              (+++) Polling Mode using HAL_FLASHEx_Erase()
33              (+++) Interrupt Mode using HAL_FLASHEx_Erase_IT()
34 
35       (#) Option Bytes Programming function: Use HAL_FLASHEx_OBProgram() to :
36         (++) Set/Reset the write protection
37         (++) Set the Read protection Level
38         (++) Program the user Option Bytes
39         (++) Configure the PCROP protection
40         (++) Set Securable memory area and boot entry point
41 
42       (#) Get Option Bytes Configuration function: Use HAL_FLASHEx_OBGetConfig() to :
43         (++) Get the value of a write protection area
44         (++) Know if the read protection is activated
45         (++) Get the value of the user Option Bytes
46         (++) Get Securable memory area and boot entry point information
47 
48       (#) Enable or disable debugger usage using HAL_FLASHEx_EnableDebugger and
49           HAL_FLASHEx_DisableDebugger.
50 
51       (#) Check is flash content is empty or not using HAL_FLASHEx_FlashEmptyCheck.
52           and modify this setting (for flash loader purpose e.g.) using
53           HAL_FLASHEx_ForceFlashEmpty.
54 
55       (#) Enable securable memory area protectionusing HAL_FLASHEx_EnableSecMemProtection
56 
57  @endverbatim
58   ******************************************************************************
59   * @attention
60   *
61   * Copyright (c) 2018 STMicroelectronics.
62   * All rights reserved.
63   *
64   * This software is licensed under terms that can be found in the LICENSE file in
65   * the root directory of this software component.
66   * If no LICENSE file comes with this software, it is provided AS-IS.
67   ******************************************************************************
68   */
69 
70 /* Includes ------------------------------------------------------------------*/
71 #include "stm32g0xx_hal.h"
72 
73 /** @addtogroup STM32G0xx_HAL_Driver
74   * @{
75   */
76 
77 /** @defgroup FLASHEx FLASHEx
78   * @brief FLASH Extended HAL module driver
79   * @{
80   */
81 
82 #ifdef HAL_FLASH_MODULE_ENABLED
83 
84 /* Private typedef -----------------------------------------------------------*/
85 /* Private define ------------------------------------------------------------*/
86 /* Private macro -------------------------------------------------------------*/
87 /* Private variables ---------------------------------------------------------*/
88 /* Private function prototypes -----------------------------------------------*/
89 /** @defgroup FLASHEx_Private_Functions FLASHEx Private Functions
90   * @{
91   */
92 static void               FLASH_MassErase(uint32_t Banks);
93 void                      FLASH_FlushCaches(void);
94 static void               FLASH_OB_WRPConfig(uint32_t WRPArea, uint32_t WRPStartOffset, uint32_t WRDPEndOffset);
95 static void               FLASH_OB_GetWRP(uint32_t WRPArea, uint32_t *WRPStartOffset, uint32_t *WRDPEndOffset);
96 static void               FLASH_OB_OptrConfig(uint32_t UserType, uint32_t UserConfig, uint32_t RDPLevel);
97 static uint32_t           FLASH_OB_GetRDP(void);
98 static uint32_t           FLASH_OB_GetUser(void);
99 #if defined(FLASH_PCROP_SUPPORT)
100 static void               FLASH_OB_PCROP1AConfig(uint32_t PCROPConfig, uint32_t PCROP1AStartAddr,
101                                                  uint32_t PCROP1AEndAddr);
102 static void               FLASH_OB_PCROP1BConfig(uint32_t PCROP1BStartAddr, uint32_t PCROP1BEndAddr);
103 static void               FLASH_OB_GetPCROP1A(uint32_t *PCROPConfig, uint32_t *PCROP1AStartAddr,
104                                               uint32_t *PCROP1AEndAddr);
105 static void               FLASH_OB_GetPCROP1B(uint32_t *PCROP1BStartAddr, uint32_t *PCROP1BEndAddr);
106 #if defined(FLASH_DBANK_SUPPORT)
107 static void               FLASH_OB_PCROP2AConfig(uint32_t PCROP2AStartAddr, uint32_t PCROP2AEndAddr);
108 static void               FLASH_OB_PCROP2BConfig(uint32_t PCROP2BStartAddr, uint32_t PCROP2BEndAddr);
109 static void               FLASH_OB_GetPCROP2A(uint32_t *PCROP2AStartAddr, uint32_t *PCROP2AEndAddr);
110 static void               FLASH_OB_GetPCROP2B(uint32_t *PCROP2BStartAddr, uint32_t *PCROP2BEndAddr);
111 #endif /* FLASH_DBANK_SUPPORT */
112 #endif /* FLASH_PCROP_SUPPORT */
113 #if defined(FLASH_SECURABLE_MEMORY_SUPPORT)
114 #if defined(FLASH_DBANK_SUPPORT)
115 static void               FLASH_OB_SecMemConfig(uint32_t BootEntry, uint32_t SecSize, uint32_t SecSize2);
116 static void               FLASH_OB_GetSecMem(uint32_t *BootEntry, uint32_t *SecSize, uint32_t *SecSize2);
117 #else
118 static void               FLASH_OB_SecMemConfig(uint32_t BootEntry, uint32_t SecSize);
119 static void               FLASH_OB_GetSecMem(uint32_t *BootEntry, uint32_t *SecSize);
120 #endif /* FLASH_DBANK_SUPPORT */
121 #endif /* FLASH_SECURABLE_MEMORY_SUPPORT */
122 /**
123   * @}
124   */
125 
126 /* Exported functions -------------------------------------------------------*/
127 /** @defgroup FLASHEx_Exported_Functions FLASH Extended Exported Functions
128   * @{
129   */
130 
131 /** @defgroup FLASHEx_Exported_Functions_Group1 Extended IO operation functions
132   *  @brief   Extended IO operation functions
133   *
134 @verbatim
135  ===============================================================================
136                 ##### Extended programming operation functions #####
137  ===============================================================================
138     [..]
139     This subsection provides a set of functions allowing to manage the Extended FLASH
140     programming operations Operations.
141 
142 @endverbatim
143   * @{
144   */
145 /**
146   * @brief  Perform a mass erase or erase the specified FLASH memory pages.
147   * @param[in]  pEraseInit Pointer to an @ref FLASH_EraseInitTypeDef structure that
148   *         contains the configuration information for the erasing.
149   * @param[out]  PageError Pointer to variable that contains the configuration
150   *         information on faulty page in case of error (0xFFFFFFFF means that all
151   *         the pages have been correctly erased)
152   * @retval HAL Status
153   */
HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef * pEraseInit,uint32_t * PageError)154 HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *PageError)
155 {
156   HAL_StatusTypeDef status;
157   uint32_t index;
158 
159   /* Check the parameters */
160   assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase));
161 
162   /* Process Locked */
163   __HAL_LOCK(&pFlash);
164 
165   /* Reset error code */
166   pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
167 
168   /* Wait for last operation to be completed */
169   status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
170 
171   if (status == HAL_OK)
172   {
173 #if !defined(FLASH_DBANK_SUPPORT)
174     /* For single bank product force Banks to Bank 1 */
175     pEraseInit->Banks = FLASH_BANK_1;
176 #endif /* FLASH_DBANK_SUPPORT */
177 
178     if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASS)
179     {
180       /* Proceed to Mass Erase */
181       FLASH_MassErase(pEraseInit->Banks);
182 
183       /* Wait for last operation to be completed */
184       status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
185     }
186     else
187     {
188       /*Initialization of PageError variable*/
189       *PageError = 0xFFFFFFFFU;
190 
191       for (index = pEraseInit->Page; index < (pEraseInit->Page + pEraseInit->NbPages); index++)
192       {
193         /* Start erase page */
194         FLASH_PageErase(pEraseInit->Banks, index);
195 
196         /* Wait for last operation to be completed */
197         status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
198 
199         if (status != HAL_OK)
200         {
201           /* In case of error, stop erase procedure and return the faulty address */
202           *PageError = index;
203           break;
204         }
205       }
206 
207       /* If operation is completed or interrupted, disable the Page Erase Bit */
208       CLEAR_BIT(FLASH->CR, FLASH_CR_PER);
209     }
210   }
211 
212   /* Process Unlocked */
213   __HAL_UNLOCK(&pFlash);
214 
215   /* return status */
216   return status;
217 }
218 
219 
220 /**
221   * @brief  Perform a mass erase or erase the specified FLASH memory pages with interrupt enabled.
222   * @param  pEraseInit Pointer to an @ref FLASH_EraseInitTypeDef structure that
223   *         contains the configuration information for the erasing.
224   * @retval HAL Status
225   */
HAL_FLASHEx_Erase_IT(FLASH_EraseInitTypeDef * pEraseInit)226 HAL_StatusTypeDef HAL_FLASHEx_Erase_IT(FLASH_EraseInitTypeDef *pEraseInit)
227 {
228   HAL_StatusTypeDef status;
229 
230   /* Check the parameters */
231   assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase));
232 
233   /* Process Locked */
234   __HAL_LOCK(&pFlash);
235 
236   /* Reset error code */
237   pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
238 
239   /* save procedure for interrupt treatment */
240   pFlash.ProcedureOnGoing = pEraseInit->TypeErase;
241 
242   /* Wait for last operation to be completed */
243   status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
244 
245   if (status != HAL_OK)
246   {
247     /* Process Unlocked */
248     __HAL_UNLOCK(&pFlash);
249   }
250   else
251   {
252 #if !defined(FLASH_DBANK_SUPPORT)
253     /* For single bank product force Banks to Bank 1 */
254     pEraseInit->Banks = FLASH_BANK_1;
255 #endif /* FLASH_DBANK_SUPPORT */
256     /* Store Bank number */
257     pFlash.Banks = pEraseInit->Banks;
258 
259     /* Enable End of Operation and Error interrupts */
260     FLASH->CR |= FLASH_CR_EOPIE | FLASH_CR_ERRIE;
261 
262     if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASS)
263     {
264       /* Set Page to 0 for Interrupt callback management */
265       pFlash.Page = 0;
266 
267       /* Proceed to Mass Erase */
268       FLASH_MassErase(pEraseInit->Banks);
269     }
270     else
271     {
272       /* Erase by page to be done */
273       pFlash.NbPagesToErase = pEraseInit->NbPages;
274       pFlash.Page = pEraseInit->Page;
275 
276       /*Erase 1st page and wait for IT */
277       FLASH_PageErase(pEraseInit->Banks, pEraseInit->Page);
278     }
279   }
280 
281   /* return status */
282   return status;
283 }
284 
285 /**
286   * @brief  Program Option bytes.
287   * @param  pOBInit Pointer to an @ref FLASH_OBProgramInitTypeDef structure that
288   *         contains the configuration information for the programming.
289   * @note   To configure any option bytes, the option lock bit OPTLOCK must be
290   *         cleared with the call of @ref HAL_FLASH_OB_Unlock() function.
291   * @note   New option bytes configuration will be taken into account only
292   *         - after an option bytes launch through the call of @ref HAL_FLASH_OB_Launch()
293   *         - a Power On Reset
294   *         - an exit from Standby or Shutdown mode.
295   * @retval HAL Status
296   */
HAL_FLASHEx_OBProgram(FLASH_OBProgramInitTypeDef * pOBInit)297 HAL_StatusTypeDef HAL_FLASHEx_OBProgram(FLASH_OBProgramInitTypeDef *pOBInit)
298 {
299   uint32_t optr;
300   HAL_StatusTypeDef status;
301 
302   /* Check the parameters */
303   assert_param(IS_OPTIONBYTE(pOBInit->OptionType));
304 
305   /* Process Locked */
306   __HAL_LOCK(&pFlash);
307 
308   pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
309 
310   /* Write protection configuration */
311   if ((pOBInit->OptionType & OPTIONBYTE_WRP) != 0x00U)
312   {
313     /* Configure of Write protection on the selected area */
314     FLASH_OB_WRPConfig(pOBInit->WRPArea, pOBInit->WRPStartOffset, pOBInit->WRPEndOffset);
315   }
316 
317   /* Option register */
318   if ((pOBInit->OptionType & (OPTIONBYTE_RDP | OPTIONBYTE_USER)) == (OPTIONBYTE_RDP | OPTIONBYTE_USER))
319   {
320     /* Fully modify OPTR register with RDP & user data */
321     FLASH_OB_OptrConfig(pOBInit->USERType, pOBInit->USERConfig, pOBInit->RDPLevel);
322   }
323   else if ((pOBInit->OptionType & OPTIONBYTE_RDP) != 0x00U)
324   {
325     /* Only modify RDP so get current user data */
326     optr = FLASH_OB_GetUser();
327     FLASH_OB_OptrConfig(optr, optr, pOBInit->RDPLevel);
328   }
329   else if ((pOBInit->OptionType & OPTIONBYTE_USER) != 0x00U)
330   {
331     /* Only modify user so get current RDP level */
332     optr = FLASH_OB_GetRDP();
333     FLASH_OB_OptrConfig(pOBInit->USERType, pOBInit->USERConfig, optr);
334   }
335   else
336   {
337     /* nothing to do */
338   }
339 
340 #if defined(FLASH_PCROP_SUPPORT)
341   /* PCROP Configuration */
342   if ((pOBInit->OptionType & OPTIONBYTE_PCROP) != 0x00U)
343   {
344     /* Check the parameters */
345     assert_param(IS_OB_PCROP_CONFIG(pOBInit->PCROPConfig));
346 
347     if ((pOBInit->PCROPConfig & (OB_PCROP_ZONE_A | OB_PCROP_RDP_ERASE)) != 0x00U)
348     {
349       /* Configure the 1A Proprietary code readout protection */
350       FLASH_OB_PCROP1AConfig(pOBInit->PCROPConfig, pOBInit->PCROP1AStartAddr, pOBInit->PCROP1AEndAddr);
351     }
352 
353     if ((pOBInit->PCROPConfig & OB_PCROP_ZONE_B) != 0x00U)
354     {
355       /* Configure the 1B Proprietary code readout protection */
356       FLASH_OB_PCROP1BConfig(pOBInit->PCROP1BStartAddr, pOBInit->PCROP1BEndAddr);
357     }
358 
359 #if defined(FLASH_DBANK_SUPPORT)
360     if ((pOBInit->PCROPConfig & OB_PCROP_ZONE2_A) != 0x00U)
361     {
362       /* Configure the 2A Proprietary code readout protection */
363       FLASH_OB_PCROP2AConfig(pOBInit->PCROP2AStartAddr, pOBInit->PCROP2AEndAddr);
364     }
365 
366     if ((pOBInit->PCROPConfig & OB_PCROP_ZONE2_B) != 0x00U)
367     {
368       /* Configure the 2B Proprietary code readout protection */
369       FLASH_OB_PCROP2BConfig(pOBInit->PCROP2BStartAddr, pOBInit->PCROP2BEndAddr);
370     }
371 #endif /* FLASH_DBANK_SUPPORT */
372   }
373 #endif /* FLASH_PCROP_SUPPORT */
374 
375 #if defined(FLASH_SECURABLE_MEMORY_SUPPORT)
376   /* Securable Memory Area Configuration */
377   if ((pOBInit->OptionType & OPTIONBYTE_SEC) != 0x00U)
378   {
379 #if defined(FLASH_DBANK_SUPPORT)
380     /* Configure the securable memory area protection */
381     FLASH_OB_SecMemConfig(pOBInit->BootEntryPoint, pOBInit->SecSize, pOBInit->SecSize2);
382 #else
383     /* Configure the securable memory area protection */
384     FLASH_OB_SecMemConfig(pOBInit->BootEntryPoint, pOBInit->SecSize);
385 #endif /* FLASH_DBANK_SUPPORT */
386   }
387 #endif /* FLASH_SECURABLE_MEMORY_SUPPORT */
388 
389   /* Wait for last operation to be completed */
390   status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
391 
392   if (status == HAL_OK)
393   {
394     /* Set OPTSTRT Bit */
395     SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
396 
397     /* Wait for last operation to be completed */
398     status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
399 
400     /* If the option byte program operation is completed, disable the OPTSTRT Bit */
401     CLEAR_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
402   }
403 
404   /* Process Unlocked */
405   __HAL_UNLOCK(&pFlash);
406 
407   /* return status */
408   return status;
409 }
410 
411 /**
412   * @brief  Get the Option bytes configuration.
413   * @note   warning: this API only read flash register, it does not reflect any
414   *         change that would have been programmed between previous Option byte
415   *         loading and current call.
416   * @param  pOBInit Pointer to an @ref FLASH_OBProgramInitTypeDef structure that contains the
417   *                  configuration information. The fields pOBInit->WRPArea should
418   *                  indicate which area is requested for the WRP.
419   * @retval None
420   */
HAL_FLASHEx_OBGetConfig(FLASH_OBProgramInitTypeDef * pOBInit)421 void HAL_FLASHEx_OBGetConfig(FLASH_OBProgramInitTypeDef *pOBInit)
422 {
423   pOBInit->OptionType = OPTIONBYTE_ALL;
424 
425   /* Get write protection on the selected area */
426   FLASH_OB_GetWRP(pOBInit->WRPArea, &(pOBInit->WRPStartOffset), &(pOBInit->WRPEndOffset));
427 
428   /* Get Read protection level */
429   pOBInit->RDPLevel = FLASH_OB_GetRDP();
430 
431   /* Get the user option bytes */
432   pOBInit->USERConfig = FLASH_OB_GetUser();
433   pOBInit->USERType = OB_USER_ALL;
434 
435 #if defined(FLASH_PCROP_SUPPORT)
436   /* Get the Proprietary code readout protection */
437   FLASH_OB_GetPCROP1A(&(pOBInit->PCROPConfig), &(pOBInit->PCROP1AStartAddr), &(pOBInit->PCROP1AEndAddr));
438   FLASH_OB_GetPCROP1B(&(pOBInit->PCROP1BStartAddr), &(pOBInit->PCROP1BEndAddr));
439   pOBInit->PCROPConfig |= (OB_PCROP_ZONE_A | OB_PCROP_ZONE_B);
440 #if defined(FLASH_DBANK_SUPPORT)
441   FLASH_OB_GetPCROP2A(&(pOBInit->PCROP2AStartAddr), &(pOBInit->PCROP2AEndAddr));
442   FLASH_OB_GetPCROP2B(&(pOBInit->PCROP2BStartAddr), &(pOBInit->PCROP2BEndAddr));
443   pOBInit->PCROPConfig |= (OB_PCROP_ZONE2_A | OB_PCROP_ZONE2_B);
444 #endif /* FLASH_DBANK_SUPPORT */
445 #endif /* FLASH_PCROP_SUPPORT */
446 
447 #if defined(FLASH_SECURABLE_MEMORY_SUPPORT)
448 #if defined(FLASH_DBANK_SUPPORT)
449   /* Get the Securable Memory Area protection */
450   FLASH_OB_GetSecMem(&(pOBInit->BootEntryPoint), &(pOBInit->SecSize), &(pOBInit->SecSize2));
451 #else
452   /* Get the Securable Memory Area protection */
453   FLASH_OB_GetSecMem(&(pOBInit->BootEntryPoint), &(pOBInit->SecSize));
454 #endif /* FLASH_DBANK_SUPPORT */
455 #endif /* FLASH_SECURABLE_MEMORY_SUPPORT */
456 }
457 
458 #if defined(FLASH_ACR_DBG_SWEN)
459 /**
460   * @brief  Enable Debugger.
461   * @note   After calling this API, flash interface allow debugger intrusion.
462   * @retval None
463   */
HAL_FLASHEx_EnableDebugger(void)464 void HAL_FLASHEx_EnableDebugger(void)
465 {
466   FLASH->ACR |= FLASH_ACR_DBG_SWEN;
467 }
468 
469 
470 /**
471   * @brief  Disable Debugger.
472   * @note   After calling this API, Debugger is disabled: it is no more possible to
473   *         break, see CPU register, etc...
474   * @retval None
475   */
HAL_FLASHEx_DisableDebugger(void)476 void HAL_FLASHEx_DisableDebugger(void)
477 {
478   FLASH->ACR &= ~FLASH_ACR_DBG_SWEN;
479 }
480 #endif /* FLASH_ACR_DBG_SWEN */
481 
482 /**
483   * @brief  Flash Empty check
484   * @note   This API checks if first location in Flash is programmed or not.
485   *         This check is done once by Option Byte Loader.
486   * @retval 0 if 1st location is not programmed else
487   */
HAL_FLASHEx_FlashEmptyCheck(void)488 uint32_t HAL_FLASHEx_FlashEmptyCheck(void)
489 {
490   return ((FLASH->ACR & FLASH_ACR_PROGEMPTY));
491 }
492 
493 
494 /**
495   * @brief  Force Empty check value.
496   * @note   Allows to modify program empty check value in order to force this
497   *         infrmation in Flash Interface, for all next reset that do not launch
498   *         Option Byte Loader.
499   * @param  FlashEmpty this parameter can be a value of @ref FLASHEx_Empty_Check
500   * @retval None
501   */
HAL_FLASHEx_ForceFlashEmpty(uint32_t FlashEmpty)502 void HAL_FLASHEx_ForceFlashEmpty(uint32_t FlashEmpty)
503 {
504   uint32_t acr;
505   assert_param(IS_FLASH_EMPTY_CHECK(FlashEmpty));
506 
507   acr = (FLASH->ACR & ~FLASH_ACR_PROGEMPTY);
508   FLASH->ACR = (acr | FlashEmpty);
509 }
510 
511 
512 #if defined(FLASH_SECURABLE_MEMORY_SUPPORT)
513 /**
514   * @brief  Securable memory area protection enable
515   * @param  Banks Select Bank to be secured.
516   *         This parameter can be a value of @ref FLASH_Banks
517   * @note   On some devices, there is only 1 bank so parameter has to be set FLASH_BANK_1.
518   * @note   This API locks Securable memory area which is defined in SEC_SIZE option byte
519   *         (that can be retrieved calling HAL_FLASHEx_OBGetConfig API and checking
520   *         Secsize).
521   * @note   SEC_PROT bit can only be set, it will be reset by system reset.
522   * @retval None
523   */
HAL_FLASHEx_EnableSecMemProtection(uint32_t Banks)524 void HAL_FLASHEx_EnableSecMemProtection(uint32_t Banks)
525 {
526 #if defined(FLASH_DBANK_SUPPORT)
527   assert_param(IS_FLASH_BANK(Banks));
528 
529   if (Banks == (FLASH_BANK_2  | FLASH_BANK_1))
530   {
531     FLASH->CR |= (FLASH_CR_SEC_PROT2 | FLASH_CR_SEC_PROT);
532   }
533   else if (Banks == FLASH_BANK_2)
534   {
535     FLASH->CR |= FLASH_CR_SEC_PROT2;
536   }
537   else
538 #else
539   UNUSED(Banks);
540 #endif /* FLASH_DBANK_SUPPORT */
541   {
542     FLASH->CR |= FLASH_CR_SEC_PROT;
543   }
544 }
545 #endif /* FLASH_SECURABLE_MEMORY_SUPPORT */
546 /**
547   * @}
548   */
549 
550 /**
551   * @}
552   */
553 
554 /* Private functions ---------------------------------------------------------*/
555 /** @addtogroup FLASHEx_Private_Functions
556   * @{
557   */
558 
559 /**
560   * @brief  Mass erase of FLASH memory.
561   * @param  Banks: Banks to be erased
562   *         This parameter can be a combination of the following values:
563   *            @arg FLASH_BANK_1: Bank1 to be erased
564   *            @arg FLASH_BANK_2: Bank2 to be erased*
565   * @note (*) availability depends on devices
566   * @retval None
567   */
FLASH_MassErase(uint32_t Banks)568 static void FLASH_MassErase(uint32_t Banks)
569 {
570   /* Check the parameters */
571   assert_param(IS_FLASH_BANK(Banks));
572 
573   /* Set the Mass Erase Bit and start bit */
574   FLASH->CR |= (FLASH_CR_STRT | Banks);
575 }
576 
577 /**
578   * @brief  Erase the specified FLASH memory page.
579   * @param  Banks: Banks to be erased
580   *         This parameter can one of the following values:
581   *            @arg FLASH_BANK_1: Bank1 to be erased
582   *            @arg FLASH_BANK_2: Bank2 to be erased*
583   * @param  Page FLASH page to erase
584   *         This parameter must be a value between 0 and (max number of pages in Flash - 1)
585   * @note (*) availability depends on devices
586   * @retval None
587   */
FLASH_PageErase(uint32_t Banks,uint32_t Page)588 void FLASH_PageErase(uint32_t Banks, uint32_t Page)
589 {
590   uint32_t tmp;
591 
592   /* Check the parameters */
593   assert_param(IS_FLASH_BANK(Banks));
594   assert_param(IS_FLASH_PAGE(Page));
595 
596   /* Get configuration register, then clear page number */
597   tmp = (FLASH->CR & ~FLASH_CR_PNB);
598 
599 #if defined(FLASH_DBANK_SUPPORT)
600   /* Check if page has to be erased in bank 1 or 2 */
601   if (Banks != FLASH_BANK_1)
602   {
603     tmp |= FLASH_CR_BKER;
604   }
605   else
606   {
607     tmp &= ~FLASH_CR_BKER;
608   }
609 #endif /* FLASH_DBANK_SUPPORT */
610 
611   /* Set page number, Page Erase bit & Start bit */
612   FLASH->CR = (tmp | (FLASH_CR_STRT | (Page <<  FLASH_CR_PNB_Pos) | FLASH_CR_PER));
613 }
614 
615 /**
616   * @brief  Flush the instruction cache.
617   * @retval None
618   */
FLASH_FlushCaches(void)619 void FLASH_FlushCaches(void)
620 {
621   /* Flush instruction cache  */
622   if (READ_BIT(FLASH->ACR, FLASH_ACR_ICEN) != 0U)
623   {
624     /* Disable instruction cache  */
625     __HAL_FLASH_INSTRUCTION_CACHE_DISABLE();
626     /* Reset instruction cache */
627     __HAL_FLASH_INSTRUCTION_CACHE_RESET();
628     /* Enable instruction cache */
629     __HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
630   }
631 }
632 
633 
634 /**
635   * @brief  Configure the write protection of the desired pages.
636   * @note   When WRP is active in a zone, it cannot be erased or programmed.
637   *         Consequently, a software mass erase cannot be performed if one zone
638   *         is write-protected.
639   * @note   When the memory read protection level is selected (RDP level = 1),
640   *         it is not possible to program or erase Flash memory if the CPU debug
641   *         features are connected (JTAG or single wire) or boot code is being
642   *         executed from RAM or System flash, even if WRP is not activated.
643   * @param  WRPArea  Specifies the area to be configured.
644   *         This parameter can be one of the following values:
645   *           @arg @ref OB_WRPAREA_ZONE_A Flash Zone A
646   *           @arg @ref OB_WRPAREA_ZONE_B Flash Zone B
647   *           @arg @ref OB_WRPAREA_ZONE2_A Flash Bank 2 Zone A (*)
648   *           @arg @ref OB_WRPAREA_ZONE2_B Flash Bank 2 Zone B (*)
649   * @note  (*) availability depends on devices
650   * @param  WRPStartOffset  Specifies the start page of the write protected area
651   *         This parameter can be page number between 0 and (max number of pages in the Flash Bank - 1)
652   * @param  WRDPEndOffset  Specifies the end page of the write protected area
653   *         This parameter can be page number between WRPStartOffset and (max number of pages in the Flash Bank - 1)
654   * @retval None
655   */
FLASH_OB_WRPConfig(uint32_t WRPArea,uint32_t WRPStartOffset,uint32_t WRDPEndOffset)656 static void FLASH_OB_WRPConfig(uint32_t WRPArea, uint32_t WRPStartOffset, uint32_t WRDPEndOffset)
657 {
658   /* Check the parameters */
659   assert_param(IS_OB_WRPAREA(WRPArea));
660   assert_param(IS_FLASH_PAGE(WRPStartOffset));
661   assert_param(IS_FLASH_PAGE(WRDPEndOffset));
662 
663   /* Configure the write protected area */
664   if (WRPArea == OB_WRPAREA_ZONE_A)
665   {
666     FLASH->WRP1AR = ((WRDPEndOffset << FLASH_WRP1AR_WRP1A_END_Pos) | WRPStartOffset);
667   }
668 #if defined(FLASH_DBANK_SUPPORT)
669   else if (WRPArea == OB_WRPAREA_ZONE2_A)
670   {
671     FLASH->WRP2AR = ((WRDPEndOffset << FLASH_WRP2AR_WRP2A_END_Pos) | WRPStartOffset);
672   }
673   else if (WRPArea == OB_WRPAREA_ZONE2_B)
674   {
675     FLASH->WRP2BR = ((WRDPEndOffset << FLASH_WRP2BR_WRP2B_END_Pos) | WRPStartOffset);
676   }
677 #endif /* FLASH_DBANK_SUPPORT */
678   else
679   {
680     FLASH->WRP1BR = ((WRDPEndOffset << FLASH_WRP1BR_WRP1B_END_Pos) | WRPStartOffset);
681   }
682 }
683 
684 /**
685   * @brief  Return the FLASH Write Protection Option Bytes value.
686   * @param[in]  WRPArea Specifies the area to be returned.
687   *             This parameter can be one of the following values:
688   *               @arg @ref OB_WRPAREA_ZONE_A Flash Zone A
689   *               @arg @ref OB_WRPAREA_ZONE_B Flash Zone B
690   *               @arg @ref OB_WRPAREA_ZONE2_A Flash Bank 2 Zone A (*)
691   *               @arg @ref OB_WRPAREA_ZONE2_B Flash Bank 2 Zone B (*)
692   * @note  (*) availability depends on devices
693   * @param[out]  WRPStartOffset  Specifies the address where to copied the start page
694   *                         of the write protected area
695   * @param[out]  WRDPEndOffset  Dpecifies the address where to copied the end page of
696   *                        the write protected area
697   * @retval None
698   */
FLASH_OB_GetWRP(uint32_t WRPArea,uint32_t * WRPStartOffset,uint32_t * WRDPEndOffset)699 static void FLASH_OB_GetWRP(uint32_t WRPArea, uint32_t *WRPStartOffset, uint32_t *WRDPEndOffset)
700 {
701   /* Check the parameters */
702   assert_param(IS_OB_WRPAREA(WRPArea));
703 
704   /* Get the configuration of the write protected area */
705   if (WRPArea == OB_WRPAREA_ZONE_A)
706   {
707     *WRPStartOffset = READ_BIT(FLASH->WRP1AR, FLASH_WRP1AR_WRP1A_STRT);
708     *WRDPEndOffset = (READ_BIT(FLASH->WRP1AR, FLASH_WRP1AR_WRP1A_END) >> FLASH_WRP1AR_WRP1A_END_Pos);
709   }
710 #if defined(FLASH_DBANK_SUPPORT)
711   else if (WRPArea == OB_WRPAREA_ZONE2_A)
712   {
713     *WRPStartOffset = READ_BIT(FLASH->WRP2AR, FLASH_WRP2AR_WRP2A_STRT);
714     *WRDPEndOffset = (READ_BIT(FLASH->WRP2AR, FLASH_WRP2AR_WRP2A_END) >> FLASH_WRP2AR_WRP2A_END_Pos);
715   }
716   else if (WRPArea == OB_WRPAREA_ZONE2_B)
717   {
718     *WRPStartOffset = READ_BIT(FLASH->WRP2BR, FLASH_WRP2BR_WRP2B_STRT);
719     *WRDPEndOffset = (READ_BIT(FLASH->WRP2BR, FLASH_WRP2BR_WRP2B_END) >> FLASH_WRP2BR_WRP2B_END_Pos);
720   }
721 #endif /* FLASH_DBANK_SUPPORT */
722   else
723   {
724     *WRPStartOffset = READ_BIT(FLASH->WRP1BR, FLASH_WRP1BR_WRP1B_STRT);
725     *WRDPEndOffset = (READ_BIT(FLASH->WRP1BR, FLASH_WRP1BR_WRP1B_END) >> FLASH_WRP1BR_WRP1B_END_Pos);
726   }
727 }
728 
729 /**
730   * @brief  Set user & RDP configuration
731   * @note   !!! Warning : When enabling OB_RDP level 2 it is no more possible
732   *         to go back to level 1 or 0 !!!
733   * @param  UserType  The FLASH User Option Bytes to be modified.
734   *         This parameter can be a combination of @ref FLASH_OB_USER_Type
735   * @param  UserConfig  The FLASH User Option Bytes values.
736   *         This parameter can be a combination of:
737   *           @arg @ref FLASH_OB_USER_BOR_ENABLE(*)
738   *           @arg @ref FLASH_OB_USER_BOR_LEVEL(*)
739   *           @arg @ref FLASH_OB_USER_RESET_CONFIG(*)
740   *           @arg @ref FLASH_OB_USER_nRST_STOP
741   *           @arg @ref FLASH_OB_USER_nRST_STANDBY
742   *           @arg @ref FLASH_OB_USER_nRST_SHUTDOWN(*)
743   *           @arg @ref FLASH_OB_USER_IWDG_SW
744   *           @arg @ref FLASH_OB_USER_IWDG_STOP
745   *           @arg @ref FLASH_OB_USER_IWDG_STANDBY
746   *           @arg @ref FLASH_OB_USER_WWDG_SW
747   *           @arg @ref FLASH_OB_USER_SRAM_PARITY
748   *           @arg @ref FLASH_OB_USER_BANK_SWAP(*)
749   *           @arg @ref FLASH_OB_USER_DUAL_BANK(*)
750   *           @arg @ref FLASH_OB_USER_nBOOT_SEL
751   *           @arg @ref FLASH_OB_USER_nBOOT1
752   *           @arg @ref FLASH_OB_USER_nBOOT0
753   *           @arg @ref FLASH_OB_USER_INPUT_RESET_HOLDER(*)
754   * @param  RDPLevel  specifies the read protection level.
755   *         This parameter can be one of the following values:
756   *           @arg @ref OB_RDP_LEVEL_0 No protection
757   *           @arg @ref OB_RDP_LEVEL_1 Memory Read protection
758   *           @arg @ref OB_RDP_LEVEL_2 Full chip protection
759   * @note  (*) availability depends on devices
760   * @retval None
761   */
FLASH_OB_OptrConfig(uint32_t UserType,uint32_t UserConfig,uint32_t RDPLevel)762 static void FLASH_OB_OptrConfig(uint32_t UserType, uint32_t UserConfig, uint32_t RDPLevel)
763 {
764   uint32_t optr;
765 
766   /* Check the parameters */
767   assert_param(IS_OB_USER_TYPE(UserType));
768   assert_param(IS_OB_USER_CONFIG(UserType, UserConfig));
769   assert_param(IS_OB_RDP_LEVEL(RDPLevel));
770 
771   /* Configure the RDP level in the option bytes register */
772   optr = FLASH->OPTR;
773   optr &= ~(UserType | FLASH_OPTR_RDP);
774   FLASH->OPTR = (optr | UserConfig | RDPLevel);
775 }
776 
777 /**
778   * @brief  Return the FLASH Read Protection level.
779   * @retval FLASH ReadOut Protection Status:
780   *         This return value can be one of the following values:
781   *           @arg @ref OB_RDP_LEVEL_0 No protection
782   *           @arg @ref OB_RDP_LEVEL_1 Read protection of the memory
783   *           @arg @ref OB_RDP_LEVEL_2 Full chip protection
784   */
FLASH_OB_GetRDP(void)785 static uint32_t FLASH_OB_GetRDP(void)
786 {
787   uint32_t rdplvl = READ_BIT(FLASH->OPTR, FLASH_OPTR_RDP);
788 
789   if ((rdplvl != OB_RDP_LEVEL_0) && (rdplvl != OB_RDP_LEVEL_2))
790   {
791     return (OB_RDP_LEVEL_1);
792   }
793   else
794   {
795     return rdplvl;
796   }
797 }
798 
799 /**
800   * @brief  Return the FLASH User Option Byte value.
801   * @retval The FLASH User Option Bytes values. It will be a combination of all the following values:
802   *           @arg @ref FLASH_OB_USER_BOR_ENABLE(*)
803   *           @arg @ref FLASH_OB_USER_BOR_LEVEL(*)
804   *           @arg @ref FLASH_OB_USER_RESET_CONFIG(*)
805   *           @arg @ref FLASH_OB_USER_nRST_STOP
806   *           @arg @ref FLASH_OB_USER_nRST_STANDBY
807   *           @arg @ref FLASH_OB_USER_nRST_SHUTDOWN(*)
808   *           @arg @ref FLASH_OB_USER_IWDG_SW
809   *           @arg @ref FLASH_OB_USER_IWDG_STOP
810   *           @arg @ref FLASH_OB_USER_IWDG_STANDBY
811   *           @arg @ref FLASH_OB_USER_WWDG_SW
812   *           @arg @ref FLASH_OB_USER_SRAM_PARITY
813   *           @arg @ref FLASH_OB_USER_BANK_SWAP(*)
814   *           @arg @ref FLASH_OB_USER_DUAL_BANK(*)
815   *           @arg @ref FLASH_OB_USER_nBOOT_SEL
816   *           @arg @ref FLASH_OB_USER_nBOOT1
817   *           @arg @ref FLASH_OB_USER_nBOOT0
818   *           @arg @ref FLASH_OB_USER_INPUT_RESET_HOLDER(*)
819   * @note  (*) availability depends on devices
820   */
FLASH_OB_GetUser(void)821 static uint32_t FLASH_OB_GetUser(void)
822 {
823   uint32_t user = ((FLASH->OPTR & ~FLASH_OPTR_RDP) & OB_USER_ALL);
824   return user;
825 }
826 
827 #if defined(FLASH_PCROP_SUPPORT)
828 /**
829   * @brief  Configure the 1A Proprietary code readout protection & erase configuration on RDP regression.
830   * @note   It is recommended to align PCROP zone with page granularity when using PCROP_RDP or avoid
831   *         having some executable code in a page where PCROP zone starts or ends.
832   * @note   Minimum PCROP area size is 2 times the chosen granularity: PCROPA_STRT and PCROPA_END.
833   *         So if the requirement is to be able to read-protect 1KB areas, the ROP granularity
834   *         has to be set to 512 Bytes
835   * @param  PCROPConfig  specifies the erase configuration (OB_PCROP_RDP_NOT_ERASE or OB_PCROP_RDP_ERASE)
836   *         on RDP level 1 regression.
837   * @param  PCROP1AStartAddr Specifies the Zone 1A Start address of the Proprietary code readout protection
838   *          This parameter can be an address between begin and end of the flash
839   * @param  PCROP1AEndAddr Specifies the Zone 1A end address of the Proprietary code readout protection
840   *          This parameter can be an address between PCROP1AStartAddr and end of the flash
841   * @retval None
842   */
FLASH_OB_PCROP1AConfig(uint32_t PCROPConfig,uint32_t PCROP1AStartAddr,uint32_t PCROP1AEndAddr)843 static void FLASH_OB_PCROP1AConfig(uint32_t PCROPConfig, uint32_t PCROP1AStartAddr, uint32_t PCROP1AEndAddr)
844 {
845   uint32_t startoffset;
846   uint32_t endoffset;
847   uint32_t pcrop1aend;
848   uint32_t ropbase;
849 
850   /* Check the parameters */
851   assert_param(IS_OB_PCROP_CONFIG(PCROPConfig));
852 
853 #if defined(FLASH_DBANK_SUPPORT)
854   /* Check if banks are swapped (valid if only one bank) */
855   if (((FLASH->OPTR & FLASH_OPTR_nSWAP_BANK) != FLASH_OPTR_nSWAP_BANK) && (FLASH_BANK_NB == 2U))
856   {
857     /* Check the parameters */
858     assert_param(IS_FLASH_MAIN_SECONDHALF_MEM_ADDRESS(PCROP1AStartAddr));
859     assert_param(IS_FLASH_MAIN_SECONDHALF_MEM_ADDRESS(PCROP1AEndAddr));
860 
861     /* Bank swap, bank 1 read only protection is on second half of Flash */
862     ropbase = (FLASH_BASE + FLASH_BANK_SIZE);
863   }
864   else
865 #endif /* FLASH_DBANK_SUPPORT */
866   {
867     /* Check the parameters */
868     assert_param(IS_FLASH_MAIN_FIRSTHALF_MEM_ADDRESS(PCROP1AStartAddr));
869     assert_param(IS_FLASH_MAIN_FIRSTHALF_MEM_ADDRESS(PCROP1AEndAddr));
870 
871     /* No Bank swap, bank 1 read only protection is on first half of Flash */
872     ropbase = FLASH_BASE;
873   }
874 
875   /* get pcrop 1A end register */
876   pcrop1aend = FLASH->PCROP1AER;
877 
878   /* Configure the Proprietary code readout protection offset */
879   if ((PCROPConfig & OB_PCROP_ZONE_A) != 0x00U)
880   {
881     /* Compute offset depending on pcrop granularity */
882     startoffset = ((PCROP1AStartAddr - ropbase) >> FLASH_PCROP_GRANULARITY_OFFSET);
883     endoffset = ((PCROP1AEndAddr - ropbase) >> FLASH_PCROP_GRANULARITY_OFFSET);
884 
885     /* Set Zone A start offset */
886     FLASH->PCROP1ASR = startoffset;
887 
888     /* Set Zone A end offset */
889     pcrop1aend &= ~FLASH_PCROP1AER_PCROP1A_END;
890     pcrop1aend |= endoffset;
891   }
892 
893   /* Set RDP erase protection if needed. This bit is only set & will be reset by mass erase */
894   if ((PCROPConfig & OB_PCROP_RDP_ERASE) != 0x00U)
895   {
896     pcrop1aend |= FLASH_PCROP1AER_PCROP_RDP;
897   }
898 
899   /* set 1A End register */
900   FLASH->PCROP1AER = pcrop1aend;
901 }
902 
903 /**
904   * @brief  Configure the 1B Proprietary code readout protection.
905   * @note   It is recommended to align PCROP zone with page granularity when using PCROP_RDP or avoid
906   *         having some executable code in a page where PCROP zone starts or ends.
907   * @note   Minimum PCROP area size is 2 times the chosen granularity: PCROPB_STRT and PCROPB_END.
908   *         So if the requirement is to be able to read-protect 1KB areas, the ROP granularity
909   *         has to be set to 512 Bytes
910   * @param  PCROP1BStartAddr  Specifies the Zone 1B Start address of the Proprietary code readout protection
911   *         This parameter can be an address between begin and end of the flash
912   * @param  PCROP1BEndAddr  Specifies the Zone 1B end address of the Proprietary code readout protection
913   *         This parameter can be an address between PCROP1BStartAddr and end of the flash
914   * @retval None
915   */
FLASH_OB_PCROP1BConfig(uint32_t PCROP1BStartAddr,uint32_t PCROP1BEndAddr)916 static void FLASH_OB_PCROP1BConfig(uint32_t PCROP1BStartAddr, uint32_t PCROP1BEndAddr)
917 {
918   uint32_t startoffset;
919   uint32_t endoffset;
920   uint32_t ropbase;
921 
922 #if defined(FLASH_DBANK_SUPPORT)
923   /* Check if banks are swapped (valid if only one bank) */
924   if (((FLASH->OPTR & FLASH_OPTR_nSWAP_BANK) != FLASH_OPTR_nSWAP_BANK) && (FLASH_BANK_NB == 2U))
925   {
926     /* Check the parameters */
927     assert_param(IS_FLASH_MAIN_SECONDHALF_MEM_ADDRESS(PCROP1BStartAddr));
928     assert_param(IS_FLASH_MAIN_SECONDHALF_MEM_ADDRESS(PCROP1BEndAddr));
929 
930     /* Bank swap, bank 1 read only protection is on second half of Flash */
931     ropbase = (FLASH_BASE + FLASH_BANK_SIZE);
932   }
933   else
934 #endif /* FLASH_DBANK_SUPPORT */
935   {
936     /* Check the parameters */
937     assert_param(IS_FLASH_MAIN_FIRSTHALF_MEM_ADDRESS(PCROP1BStartAddr));
938     assert_param(IS_FLASH_MAIN_FIRSTHALF_MEM_ADDRESS(PCROP1BEndAddr));
939 
940     /* No Bank swap, bank 1 read only protection is on first half of Flash */
941     ropbase = FLASH_BASE;
942   }
943 
944   /* Configure the Proprietary code readout protection offset */
945   startoffset = ((PCROP1BStartAddr - ropbase) >> FLASH_PCROP_GRANULARITY_OFFSET);
946   endoffset = ((PCROP1BEndAddr - ropbase) >> FLASH_PCROP_GRANULARITY_OFFSET);
947 
948   /* Set Zone B start offset */
949   FLASH->PCROP1BSR = startoffset;
950   /* Set Zone B end offset */
951   FLASH->PCROP1BER = endoffset;
952 }
953 
954 /**
955   * @brief  Return the FLASH PCROP Protection Option Bytes value.
956   * @param  PCROPConfig [out]  specifies the configuration of PCROP_RDP option.
957   * @param  PCROP1AStartAddr [out]  Specifies the address where to copied the start address
958   *         of the 1A Proprietary code readout protection
959   * @param  PCROP1AEndAddr [out]  Specifies the address where to copied the end address of
960   *         the 1A Proprietary code readout protection
961   * @retval None
962   */
FLASH_OB_GetPCROP1A(uint32_t * PCROPConfig,uint32_t * PCROP1AStartAddr,uint32_t * PCROP1AEndAddr)963 static void FLASH_OB_GetPCROP1A(uint32_t *PCROPConfig, uint32_t *PCROP1AStartAddr, uint32_t *PCROP1AEndAddr)
964 {
965   uint32_t pcrop;
966   uint32_t ropbase;
967 
968 #if defined(FLASH_DBANK_SUPPORT)
969   /* Check if banks are swapped (valid if only one bank) */
970   if (((FLASH->OPTR & FLASH_OPTR_nSWAP_BANK) != FLASH_OPTR_nSWAP_BANK) && (FLASH_BANK_NB == 2U))
971   {
972     /* Bank swap, bank 1 read only protection is on second half of Flash */
973     ropbase = (FLASH_BASE + FLASH_BANK_SIZE);
974   }
975   else
976 #endif /* FLASH_DBANK_SUPPORT */
977   {
978     /* No Bank swap, bank 1 read only protection is on first half of Flash */
979     ropbase = FLASH_BASE;
980   }
981 
982   pcrop = (FLASH->PCROP1ASR & FLASH_PCROP1ASR_PCROP1A_STRT);
983   *PCROP1AStartAddr = (pcrop << FLASH_PCROP_GRANULARITY_OFFSET);
984   *PCROP1AStartAddr += ropbase;
985 
986   pcrop = FLASH->PCROP1AER;
987   *PCROP1AEndAddr = ((pcrop & FLASH_PCROP1AER_PCROP1A_END) << FLASH_PCROP_GRANULARITY_OFFSET);
988   *PCROP1AEndAddr += (ropbase + FLASH_PCROP_GRANULARITY - 1U);
989 
990   *PCROPConfig &= ~OB_PCROP_RDP_ERASE;
991   *PCROPConfig |= (pcrop & FLASH_PCROP1AER_PCROP_RDP);
992 }
993 
994 /**
995   * @brief  Return the FLASH PCROP Protection Option Bytes value.
996   * @param  PCROP1BStartAddr [out]  Specifies the address where to copied the start address
997   *         of the 1B Proprietary code readout protection
998   * @param  PCROP1BEndAddr [out]  Specifies the address where to copied the end address of
999   *         the 1B Proprietary code readout protection
1000   * @retval None
1001   */
FLASH_OB_GetPCROP1B(uint32_t * PCROP1BStartAddr,uint32_t * PCROP1BEndAddr)1002 static void FLASH_OB_GetPCROP1B(uint32_t *PCROP1BStartAddr, uint32_t *PCROP1BEndAddr)
1003 {
1004   uint32_t pcrop;
1005   uint32_t ropbase;
1006 
1007 #if defined(FLASH_DBANK_SUPPORT)
1008   /* Check if banks are swapped (valid if only one bank) */
1009   if (((FLASH->OPTR & FLASH_OPTR_nSWAP_BANK) != FLASH_OPTR_nSWAP_BANK) && (FLASH_BANK_NB == 2U))
1010   {
1011     /* Bank swap, bank 1 read only protection is on second half of Flash */
1012     ropbase = (FLASH_BASE + FLASH_BANK_SIZE);
1013   }
1014   else
1015 #endif /* FLASH_DBANK_SUPPORT */
1016   {
1017     /* No Bank swap, bank 1 read only protection is on first half of Flash */
1018     ropbase = FLASH_BASE;
1019   }
1020 
1021   pcrop = (FLASH->PCROP1BSR & FLASH_PCROP1BSR_PCROP1B_STRT);
1022   *PCROP1BStartAddr = (pcrop << FLASH_PCROP_GRANULARITY_OFFSET);
1023   *PCROP1BStartAddr += ropbase;
1024 
1025   pcrop = (FLASH->PCROP1BER & FLASH_PCROP1BER_PCROP1B_END);
1026   *PCROP1BEndAddr = (pcrop << FLASH_PCROP_GRANULARITY_OFFSET);
1027   *PCROP1BEndAddr += (ropbase + FLASH_PCROP_GRANULARITY - 1U);
1028 }
1029 
1030 #if defined(FLASH_DBANK_SUPPORT)
1031 /**
1032   * @brief  Configure the 2A Proprietary code readout protection.
1033   * @note   It is recommended to align PCROP zone with page granularity when using PCROP_RDP or avoid
1034   *         having some executable code in a page where PCROP zone starts or ends.
1035   * @note   Minimum PCROP area size is 2 times the chosen granularity: PCROPA_STRT and PCROPA_END.
1036   *         So if the requirement is to be able to read-protect 1KB areas, the ROP granularity
1037   *         has to be set to 512 Bytes
1038   * @param  PCROP2AStartAddr  Specifies the Zone 2A Start address of the Proprietary code readout protection
1039   *         This parameter can be an address between begin and end of the flash
1040   * @param  PCROP2AEndAddr  Specifies the Zone 2A end address of the Proprietary code readout protection
1041   *         This parameter can be an address between PCROP2AStartAddr and end of the flash
1042   * @retval None
1043   */
FLASH_OB_PCROP2AConfig(uint32_t PCROP2AStartAddr,uint32_t PCROP2AEndAddr)1044 static void FLASH_OB_PCROP2AConfig(uint32_t PCROP2AStartAddr, uint32_t PCROP2AEndAddr)
1045 {
1046   uint32_t startoffset;
1047   uint32_t endoffset;
1048   uint32_t ropbase;
1049 
1050   /* Check if banks are swapped */
1051   if ((FLASH->OPTR & FLASH_OPTR_nSWAP_BANK) != 0x00u)
1052   {
1053     /* Check the parameters */
1054     assert_param(IS_FLASH_MAIN_SECONDHALF_MEM_ADDRESS(PCROP2AStartAddr));
1055     assert_param(IS_FLASH_MAIN_SECONDHALF_MEM_ADDRESS(PCROP2AEndAddr));
1056 
1057     /* No Bank swap, bank 2 read only protection is on second half of Flash */
1058     ropbase = (FLASH_BASE + FLASH_BANK_SIZE);
1059   }
1060   else
1061   {
1062     /* Check the parameters */
1063     assert_param(IS_FLASH_MAIN_FIRSTHALF_MEM_ADDRESS(PCROP2AStartAddr));
1064     assert_param(IS_FLASH_MAIN_FIRSTHALF_MEM_ADDRESS(PCROP2AEndAddr));
1065 
1066     /* Bank swap, bank 2 read only protection is on first half of Flash */
1067     ropbase = FLASH_BASE;
1068   }
1069 
1070   /* Configure the Proprietary code readout protection offset */
1071   startoffset = ((PCROP2AStartAddr - ropbase) >> FLASH_PCROP_GRANULARITY_OFFSET);
1072   endoffset = ((PCROP2AEndAddr - ropbase) >> FLASH_PCROP_GRANULARITY_OFFSET);
1073 
1074   /* Set Zone A start offset */
1075   FLASH->PCROP2ASR = startoffset;
1076   /* Set Zone A end offset */
1077   FLASH->PCROP2AER = endoffset;
1078 }
1079 
1080 /**
1081   * @brief  Configure the 2B Proprietary code readout protection.
1082   * @note   It is recommended to align PCROP zone with page granularity when using PCROP_RDP or avoid
1083   *         having some executable code in a page where PCROP zone starts or ends.
1084   * @note   Minimum PCROP area size is 2 times the chosen granularity: PCROP_STRT and PCROP_END.
1085   *         So if the requirement is to be able to read-protect 1KB areas, the ROP granularity
1086   *         has to be set to 512 Bytes
1087   * @param  PCROP2BStartAddr  Specifies the Zone 2B Start address of the Proprietary code readout protection
1088   *         This parameter can be an address between begin and end of the flash
1089   * @param  PCROP2BEndAddr  Specifies the Zone 2B end address of the Proprietary code readout protection
1090   *         This parameter can be an address between PCROP2BStartAddr and end of the flash
1091   * @retval None
1092   */
FLASH_OB_PCROP2BConfig(uint32_t PCROP2BStartAddr,uint32_t PCROP2BEndAddr)1093 static void FLASH_OB_PCROP2BConfig(uint32_t PCROP2BStartAddr, uint32_t PCROP2BEndAddr)
1094 {
1095   uint32_t startoffset;
1096   uint32_t endoffset;
1097   uint32_t ropbase;
1098 
1099   /* Check if banks are swapped */
1100   if ((FLASH->OPTR & FLASH_OPTR_nSWAP_BANK) != 0x00u)
1101   {
1102     /* Check the parameters */
1103     assert_param(IS_FLASH_MAIN_SECONDHALF_MEM_ADDRESS(PCROP2BStartAddr));
1104     assert_param(IS_FLASH_MAIN_SECONDHALF_MEM_ADDRESS(PCROP2BEndAddr));
1105 
1106     /* No Bank swap, bank 2 read only protection is on second half of Flash */
1107     ropbase = (FLASH_BASE + FLASH_BANK_SIZE);
1108   }
1109   else
1110   {
1111     /* Check the parameters */
1112     assert_param(IS_FLASH_MAIN_FIRSTHALF_MEM_ADDRESS(PCROP2BStartAddr));
1113     assert_param(IS_FLASH_MAIN_FIRSTHALF_MEM_ADDRESS(PCROP2BEndAddr));
1114 
1115     /* Bank swap, bank 2 read only protection is on first half of Flash */
1116     ropbase = FLASH_BASE;
1117   }
1118 
1119   /* Configure the Proprietary code readout protection offset */
1120   startoffset = ((PCROP2BStartAddr - ropbase) >> FLASH_PCROP_GRANULARITY_OFFSET);
1121   endoffset = ((PCROP2BEndAddr - ropbase) >> FLASH_PCROP_GRANULARITY_OFFSET);
1122 
1123   /* Set Zone B start offset */
1124   FLASH->PCROP2BSR = startoffset;
1125   /* Set Zone B end offset */
1126   FLASH->PCROP2BER = endoffset;
1127 }
1128 
1129 /**
1130   * @brief  Return the FLASH PCROP Protection Option Bytes value.
1131   * @param  PCROP2AStartAddr [out]  Specifies the address where to copied the start address
1132   *         of the 2A Proprietary code readout protection
1133   * @param  PCROP2AEndAddr [out]  Specifies the address where to copied the end address of
1134   *         the 2A Proprietary code readout protection
1135   * @retval None
1136   */
FLASH_OB_GetPCROP2A(uint32_t * PCROP2AStartAddr,uint32_t * PCROP2AEndAddr)1137 static void FLASH_OB_GetPCROP2A(uint32_t *PCROP2AStartAddr, uint32_t *PCROP2AEndAddr)
1138 {
1139   uint32_t pcrop;
1140   uint32_t ropbase;
1141 
1142   /* Check if banks are swapped */
1143   if ((FLASH->OPTR & FLASH_OPTR_nSWAP_BANK) != 0x00u)
1144   {
1145     /* No Bank swap, bank 2 read only protection is on second half of Flash */
1146     ropbase = (FLASH_BASE + FLASH_BANK_SIZE);
1147   }
1148   else
1149   {
1150     /* Bank swap, bank 2 read only protection is on first half of Flash */
1151     ropbase = FLASH_BASE;
1152   }
1153 
1154   pcrop = (FLASH->PCROP2ASR & FLASH_PCROP2ASR_PCROP2A_STRT);
1155   *PCROP2AStartAddr = (pcrop << FLASH_PCROP_GRANULARITY_OFFSET);
1156   *PCROP2AStartAddr += ropbase;
1157 
1158   pcrop = (FLASH->PCROP2AER & FLASH_PCROP2AER_PCROP2A_END);
1159   *PCROP2AEndAddr = (pcrop << FLASH_PCROP_GRANULARITY_OFFSET);
1160   *PCROP2AEndAddr += (ropbase + FLASH_PCROP_GRANULARITY - 1U);
1161 }
1162 
1163 /**
1164   * @brief  Return the FLASH PCROP Protection Option Bytes value.
1165   * @param  PCROP2BStartAddr [out]  Specifies the address where to copied the start address
1166   *         of the 2B Proprietary code readout protection
1167   * @param  PCROP2BEndAddr [out]  Specifies the address where to copied the end address of
1168   *         the 2B Proprietary code readout protection
1169   * @retval None
1170   */
FLASH_OB_GetPCROP2B(uint32_t * PCROP2BStartAddr,uint32_t * PCROP2BEndAddr)1171 static void FLASH_OB_GetPCROP2B(uint32_t *PCROP2BStartAddr, uint32_t *PCROP2BEndAddr)
1172 {
1173   uint32_t pcrop;
1174   uint32_t ropbase;
1175 
1176   /* Check if banks are swapped */
1177   if ((FLASH->OPTR & FLASH_OPTR_nSWAP_BANK) != 0x00u)
1178   {
1179     /* No Bank swap, bank 2 read only protection is on second half of Flash */
1180     ropbase = (FLASH_BASE + FLASH_BANK_SIZE);
1181   }
1182   else
1183   {
1184     /* Bank swap, bank 2 read only protection is on first half of Flash */
1185     ropbase = FLASH_BASE;
1186   }
1187 
1188   pcrop = (FLASH->PCROP2BSR & FLASH_PCROP2BSR_PCROP2B_STRT);
1189   *PCROP2BStartAddr = (pcrop << FLASH_PCROP_GRANULARITY_OFFSET);
1190   *PCROP2BStartAddr += ropbase;
1191 
1192   pcrop = (FLASH->PCROP2BER & FLASH_PCROP2BER_PCROP2B_END);
1193   *PCROP2BEndAddr = (pcrop << FLASH_PCROP_GRANULARITY_OFFSET);
1194   *PCROP2BEndAddr += (ropbase + FLASH_PCROP_GRANULARITY - 1U);
1195 }
1196 #endif /* FLASH_DBANK_SUPPORT */
1197 #endif /* FLASH_PCROP_SUPPORT */
1198 
1199 #if defined(FLASH_SECURABLE_MEMORY_SUPPORT)
1200 #if defined(FLASH_DBANK_SUPPORT)
1201 /**
1202   * @brief  Configure Securable Memory area feature.
1203   * @param  BootEntry  specifies if boot scheme is forced to Flash (System or user) or not
1204   *         This parameter can be one of the following values:
1205   *           @arg @ref OB_BOOT_ENTRY_FORCED_NONE No boot entry forced
1206   *           @arg @ref OB_BOOT_ENTRY_FORCED_FLASH Flash selected as unique entry boot
1207   * @param  SecSize specifies number of pages to protect as securable memory area, starting from
1208   *         beginning of Bank1 (page 0).
1209   * @param  SecSize2 specifies number of pages to protect as securable memory area, starting from
1210   *         beginning of Bank2 (page 0).
1211   * @retval None
1212   */
FLASH_OB_SecMemConfig(uint32_t BootEntry,uint32_t SecSize,uint32_t SecSize2)1213 static void FLASH_OB_SecMemConfig(uint32_t BootEntry, uint32_t SecSize, uint32_t SecSize2)
1214 {
1215   uint32_t secmem;
1216 
1217   /* Check the parameters */
1218   assert_param(IS_OB_SEC_BOOT_LOCK(BootEntry));
1219   assert_param(IS_OB_SEC_SIZE(SecSize));
1220 
1221   if ((FLASH_BANK_NB == 2U))
1222   {
1223     assert_param(IS_OB_SEC_SIZE(SecSize2));
1224   }
1225 
1226   /* Set securable memory area configuration */
1227   secmem = (FLASH->SECR & ~(FLASH_SECR_BOOT_LOCK | FLASH_SECR_SEC_SIZE | FLASH_SECR_SEC_SIZE2));
1228   FLASH->SECR = (secmem | BootEntry | SecSize | (SecSize2 << FLASH_SECR_SEC_SIZE2_Pos));
1229 }
1230 
1231 /**
1232   * @brief  Return the FLASH Securable memory area protection Option Bytes value.
1233   * @param  BootEntry  specifies boot scheme configuration
1234   * @param  SecSize specifies number of pages to protect as secure memory area, starting from
1235   *         beginning of Bank1 (page 0).
1236   * @param  SecSize2 specifies number of pages to protect as secure memory area, starting from
1237   *         beginning of Bank2 (page 0).
1238   * @retval None
1239   */
FLASH_OB_GetSecMem(uint32_t * BootEntry,uint32_t * SecSize,uint32_t * SecSize2)1240 static void FLASH_OB_GetSecMem(uint32_t *BootEntry, uint32_t *SecSize, uint32_t *SecSize2)
1241 {
1242   uint32_t secmem = FLASH->SECR;
1243 
1244   *BootEntry = (secmem & FLASH_SECR_BOOT_LOCK);
1245   *SecSize = (secmem & FLASH_SECR_SEC_SIZE);
1246   *SecSize2 = (secmem & FLASH_SECR_SEC_SIZE2) >> FLASH_SECR_SEC_SIZE2_Pos;
1247 }
1248 
1249 #else
1250 /**
1251   * @brief  Configure Securable Memory area feature.
1252   * @param  BootEntry  specifies if boot scheme is forced to Flash (System or user) or not
1253   *         This parameter can be one of the following values:
1254   *           @arg @ref OB_BOOT_ENTRY_FORCED_NONE No boot entry forced
1255   *           @arg @ref OB_BOOT_ENTRY_FORCED_FLASH FLash selected as unique entry boot
1256   * @param  SecSize specifies number of pages to protect as securable memory area, starting from
1257   *         beginning of the Flash (page 0).
1258   * @retval None
1259   */
FLASH_OB_SecMemConfig(uint32_t BootEntry,uint32_t SecSize)1260 static void FLASH_OB_SecMemConfig(uint32_t BootEntry, uint32_t SecSize)
1261 {
1262   uint32_t secmem;
1263 
1264   /* Check the parameters */
1265   assert_param(IS_OB_SEC_BOOT_LOCK(BootEntry));
1266   assert_param(IS_OB_SEC_SIZE(SecSize));
1267 
1268   /* Set securable memory area configuration */
1269   secmem = (FLASH->SECR & ~(FLASH_SECR_BOOT_LOCK | FLASH_SECR_SEC_SIZE));
1270   FLASH->SECR = (secmem | BootEntry | SecSize);
1271 }
1272 
1273 /**
1274   * @brief  Return the FLASH Securable memory area protection Option Bytes value.
1275   * @param  BootEntry  specifies boot scheme configuration
1276   * @param  SecSize specifies number of pages to protect as secure memory area, starting from
1277   *         beginning of the Flash (page 0).
1278   * @retval None
1279   */
FLASH_OB_GetSecMem(uint32_t * BootEntry,uint32_t * SecSize)1280 static void FLASH_OB_GetSecMem(uint32_t *BootEntry, uint32_t *SecSize)
1281 {
1282   uint32_t secmem = FLASH->SECR;
1283 
1284   *BootEntry = (secmem & FLASH_SECR_BOOT_LOCK);
1285   *SecSize = (secmem & FLASH_SECR_SEC_SIZE);
1286 }
1287 #endif /* FLASH_DBANK_SUPPORT */
1288 #endif /* FLASH_SECURABLE_MEMORY_SUPPORT */
1289 
1290 /**
1291   * @}
1292   */
1293 
1294 /**
1295   * @}
1296   */
1297 
1298 #endif /* HAL_FLASH_MODULE_ENABLED */
1299 
1300 /**
1301   * @}
1302   */
1303 
1304 /**
1305   * @}
1306   */
1307 
1308