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 #else
610   /* Prevent unused argument(s) compilation warning */
611   UNUSED(Banks);
612 #endif /* FLASH_DBANK_SUPPORT */
613 
614   /* Set page number, Page Erase bit & Start bit */
615   FLASH->CR = (tmp | (FLASH_CR_STRT | (Page <<  FLASH_CR_PNB_Pos) | FLASH_CR_PER));
616 }
617 
618 /**
619   * @brief  Flush the instruction cache.
620   * @retval None
621   */
FLASH_FlushCaches(void)622 void FLASH_FlushCaches(void)
623 {
624   /* Flush instruction cache  */
625   if (READ_BIT(FLASH->ACR, FLASH_ACR_ICEN) != 0U)
626   {
627     /* Disable instruction cache  */
628     __HAL_FLASH_INSTRUCTION_CACHE_DISABLE();
629     /* Reset instruction cache */
630     __HAL_FLASH_INSTRUCTION_CACHE_RESET();
631     /* Enable instruction cache */
632     __HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
633   }
634 }
635 
636 /**
637   * @brief  Configure the write protection of the desired pages.
638   * @note   When WRP is active in a zone, it cannot be erased or programmed.
639   *         Consequently, a software mass erase cannot be performed if one zone
640   *         is write-protected.
641   * @note   When the memory read protection level is selected (RDP level = 1),
642   *         it is not possible to program or erase Flash memory if the CPU debug
643   *         features are connected (JTAG or single wire) or boot code is being
644   *         executed from RAM or System flash, even if WRP is not activated.
645   * @param  WRPArea  Specifies the area to be configured.
646   *         This parameter can be one of the following values:
647   *           @arg @ref OB_WRPAREA_ZONE_A Flash Zone A
648   *           @arg @ref OB_WRPAREA_ZONE_B Flash Zone B
649   *           @arg @ref OB_WRPAREA_ZONE2_A Flash Bank 2 Zone A (*)
650   *           @arg @ref OB_WRPAREA_ZONE2_B Flash Bank 2 Zone B (*)
651   * @note  (*) availability depends on devices
652   * @param  WRPStartOffset  Specifies the start page of the write protected area
653   *         This parameter can be page number between 0 and (max number of pages in the Flash Bank - 1)
654   * @param  WRDPEndOffset  Specifies the end page of the write protected area
655   *         This parameter can be page number between WRPStartOffset and (max number of pages in the Flash Bank - 1)
656   * @retval None
657   */
FLASH_OB_WRPConfig(uint32_t WRPArea,uint32_t WRPStartOffset,uint32_t WRDPEndOffset)658 static void FLASH_OB_WRPConfig(uint32_t WRPArea, uint32_t WRPStartOffset, uint32_t WRDPEndOffset)
659 {
660   /* Check the parameters */
661   assert_param(IS_OB_WRPAREA(WRPArea));
662   assert_param(IS_FLASH_PAGE(WRPStartOffset));
663   assert_param(IS_FLASH_PAGE(WRDPEndOffset));
664 
665   /* Configure the write protected area */
666   if (WRPArea == OB_WRPAREA_ZONE_A)
667   {
668     FLASH->WRP1AR = ((WRDPEndOffset << FLASH_WRP1AR_WRP1A_END_Pos) | WRPStartOffset);
669   }
670 #if defined(FLASH_DBANK_SUPPORT)
671   else if (WRPArea == OB_WRPAREA_ZONE2_A)
672   {
673     FLASH->WRP2AR = ((WRDPEndOffset << FLASH_WRP2AR_WRP2A_END_Pos) | WRPStartOffset);
674   }
675   else if (WRPArea == OB_WRPAREA_ZONE2_B)
676   {
677     FLASH->WRP2BR = ((WRDPEndOffset << FLASH_WRP2BR_WRP2B_END_Pos) | WRPStartOffset);
678   }
679 #endif /* FLASH_DBANK_SUPPORT */
680   else
681   {
682     FLASH->WRP1BR = ((WRDPEndOffset << FLASH_WRP1BR_WRP1B_END_Pos) | WRPStartOffset);
683   }
684 }
685 
686 /**
687   * @brief  Return the FLASH Write Protection Option Bytes value.
688   * @param[in]  WRPArea Specifies the area to be returned.
689   *             This parameter can be one of the following values:
690   *               @arg @ref OB_WRPAREA_ZONE_A Flash Zone A
691   *               @arg @ref OB_WRPAREA_ZONE_B Flash Zone B
692   *               @arg @ref OB_WRPAREA_ZONE2_A Flash Bank 2 Zone A (*)
693   *               @arg @ref OB_WRPAREA_ZONE2_B Flash Bank 2 Zone B (*)
694   * @note  (*) availability depends on devices
695   * @param[out]  WRPStartOffset  Specifies the address where to copied the start page
696   *                         of the write protected area
697   * @param[out]  WRDPEndOffset  Dpecifies the address where to copied the end page of
698   *                        the write protected area
699   * @retval None
700   */
FLASH_OB_GetWRP(uint32_t WRPArea,uint32_t * WRPStartOffset,uint32_t * WRDPEndOffset)701 static void FLASH_OB_GetWRP(uint32_t WRPArea, uint32_t *WRPStartOffset, uint32_t *WRDPEndOffset)
702 {
703   /* Check the parameters */
704   assert_param(IS_OB_WRPAREA(WRPArea));
705 
706   /* Get the configuration of the write protected area */
707   if (WRPArea == OB_WRPAREA_ZONE_A)
708   {
709     *WRPStartOffset = READ_BIT(FLASH->WRP1AR, FLASH_WRP1AR_WRP1A_STRT);
710     *WRDPEndOffset = (READ_BIT(FLASH->WRP1AR, FLASH_WRP1AR_WRP1A_END) >> FLASH_WRP1AR_WRP1A_END_Pos);
711   }
712 #if defined(FLASH_DBANK_SUPPORT)
713   else if (WRPArea == OB_WRPAREA_ZONE2_A)
714   {
715     *WRPStartOffset = READ_BIT(FLASH->WRP2AR, FLASH_WRP2AR_WRP2A_STRT);
716     *WRDPEndOffset = (READ_BIT(FLASH->WRP2AR, FLASH_WRP2AR_WRP2A_END) >> FLASH_WRP2AR_WRP2A_END_Pos);
717   }
718   else if (WRPArea == OB_WRPAREA_ZONE2_B)
719   {
720     *WRPStartOffset = READ_BIT(FLASH->WRP2BR, FLASH_WRP2BR_WRP2B_STRT);
721     *WRDPEndOffset = (READ_BIT(FLASH->WRP2BR, FLASH_WRP2BR_WRP2B_END) >> FLASH_WRP2BR_WRP2B_END_Pos);
722   }
723 #endif /* FLASH_DBANK_SUPPORT */
724   else
725   {
726     *WRPStartOffset = READ_BIT(FLASH->WRP1BR, FLASH_WRP1BR_WRP1B_STRT);
727     *WRDPEndOffset = (READ_BIT(FLASH->WRP1BR, FLASH_WRP1BR_WRP1B_END) >> FLASH_WRP1BR_WRP1B_END_Pos);
728   }
729 }
730 
731 /**
732   * @brief  Set user & RDP configuration
733   * @note   !!! Warning : When enabling OB_RDP level 2 it is no more possible
734   *         to go back to level 1 or 0 !!!
735   * @param  UserType  The FLASH User Option Bytes to be modified.
736   *         This parameter can be a combination of @ref FLASH_OB_USER_Type
737   * @param  UserConfig  The FLASH User Option Bytes values.
738   *         This parameter can be a combination of:
739   *           @arg @ref FLASH_OB_USER_BOR_ENABLE(*)
740   *           @arg @ref FLASH_OB_USER_BOR_LEVEL(*)
741   *           @arg @ref FLASH_OB_USER_RESET_CONFIG(*)
742   *           @arg @ref FLASH_OB_USER_nRST_STOP
743   *           @arg @ref FLASH_OB_USER_nRST_STANDBY
744   *           @arg @ref FLASH_OB_USER_nRST_SHUTDOWN(*)
745   *           @arg @ref FLASH_OB_USER_IWDG_SW
746   *           @arg @ref FLASH_OB_USER_IWDG_STOP
747   *           @arg @ref FLASH_OB_USER_IWDG_STANDBY
748   *           @arg @ref FLASH_OB_USER_WWDG_SW
749   *           @arg @ref FLASH_OB_USER_SRAM_PARITY
750   *           @arg @ref FLASH_OB_USER_BANK_SWAP(*)
751   *           @arg @ref FLASH_OB_USER_DUAL_BANK(*)
752   *           @arg @ref FLASH_OB_USER_nBOOT_SEL
753   *           @arg @ref FLASH_OB_USER_nBOOT1
754   *           @arg @ref FLASH_OB_USER_nBOOT0
755   *           @arg @ref FLASH_OB_USER_INPUT_RESET_HOLDER(*)
756   * @param  RDPLevel  specifies the read protection level.
757   *         This parameter can be one of the following values:
758   *           @arg @ref OB_RDP_LEVEL_0 No protection
759   *           @arg @ref OB_RDP_LEVEL_1 Memory Read protection
760   *           @arg @ref OB_RDP_LEVEL_2 Full chip protection
761   * @note  (*) availability depends on devices
762   * @retval None
763   */
FLASH_OB_OptrConfig(uint32_t UserType,uint32_t UserConfig,uint32_t RDPLevel)764 static void FLASH_OB_OptrConfig(uint32_t UserType, uint32_t UserConfig, uint32_t RDPLevel)
765 {
766   uint32_t optr;
767 
768   /* Check the parameters */
769   assert_param(IS_OB_USER_TYPE(UserType));
770   assert_param(IS_OB_USER_CONFIG(UserType, UserConfig));
771   assert_param(IS_OB_RDP_LEVEL(RDPLevel));
772 
773   /* Configure the RDP level in the option bytes register */
774   optr = FLASH->OPTR;
775   optr &= ~(UserType | FLASH_OPTR_RDP);
776   FLASH->OPTR = (optr | UserConfig | RDPLevel);
777 }
778 
779 /**
780   * @brief  Return the FLASH Read Protection level.
781   * @retval FLASH ReadOut Protection Status:
782   *         This return value can be one of the following values:
783   *           @arg @ref OB_RDP_LEVEL_0 No protection
784   *           @arg @ref OB_RDP_LEVEL_1 Read protection of the memory
785   *           @arg @ref OB_RDP_LEVEL_2 Full chip protection
786   */
FLASH_OB_GetRDP(void)787 static uint32_t FLASH_OB_GetRDP(void)
788 {
789   uint32_t rdplvl = READ_BIT(FLASH->OPTR, FLASH_OPTR_RDP);
790 
791   if ((rdplvl != OB_RDP_LEVEL_0) && (rdplvl != OB_RDP_LEVEL_2))
792   {
793     return (OB_RDP_LEVEL_1);
794   }
795   else
796   {
797     return rdplvl;
798   }
799 }
800 
801 /**
802   * @brief  Return the FLASH User Option Byte value.
803   * @retval The FLASH User Option Bytes values. It will be a combination of all the following values:
804   *           @arg @ref FLASH_OB_USER_BOR_ENABLE(*)
805   *           @arg @ref FLASH_OB_USER_BOR_LEVEL(*)
806   *           @arg @ref FLASH_OB_USER_RESET_CONFIG(*)
807   *           @arg @ref FLASH_OB_USER_nRST_STOP
808   *           @arg @ref FLASH_OB_USER_nRST_STANDBY
809   *           @arg @ref FLASH_OB_USER_nRST_SHUTDOWN(*)
810   *           @arg @ref FLASH_OB_USER_IWDG_SW
811   *           @arg @ref FLASH_OB_USER_IWDG_STOP
812   *           @arg @ref FLASH_OB_USER_IWDG_STANDBY
813   *           @arg @ref FLASH_OB_USER_WWDG_SW
814   *           @arg @ref FLASH_OB_USER_SRAM_PARITY
815   *           @arg @ref FLASH_OB_USER_BANK_SWAP(*)
816   *           @arg @ref FLASH_OB_USER_DUAL_BANK(*)
817   *           @arg @ref FLASH_OB_USER_nBOOT_SEL
818   *           @arg @ref FLASH_OB_USER_nBOOT1
819   *           @arg @ref FLASH_OB_USER_nBOOT0
820   *           @arg @ref FLASH_OB_USER_INPUT_RESET_HOLDER(*)
821   * @note  (*) availability depends on devices
822   */
FLASH_OB_GetUser(void)823 static uint32_t FLASH_OB_GetUser(void)
824 {
825   uint32_t user = ((FLASH->OPTR & ~FLASH_OPTR_RDP) & OB_USER_ALL);
826   return user;
827 }
828 
829 #if defined(FLASH_PCROP_SUPPORT)
830 /**
831   * @brief  Configure the 1A Proprietary code readout protection & erase configuration on RDP regression.
832   * @note   It is recommended to align PCROP zone with page granularity when using PCROP_RDP or avoid
833   *         having some executable code in a page where PCROP zone starts or ends.
834   * @note   Minimum PCROP area size is 2 times the chosen granularity: PCROPA_STRT and PCROPA_END.
835   *         So if the requirement is to be able to read-protect 1KB areas, the ROP granularity
836   *         has to be set to 512 Bytes
837   * @param  PCROPConfig  specifies the erase configuration (OB_PCROP_RDP_NOT_ERASE or OB_PCROP_RDP_ERASE)
838   *         on RDP level 1 regression.
839   * @param  PCROP1AStartAddr Specifies the Zone 1A Start address of the Proprietary code readout protection
840   *          This parameter can be an address between begin and end of the flash
841   * @param  PCROP1AEndAddr Specifies the Zone 1A end address of the Proprietary code readout protection
842   *          This parameter can be an address between PCROP1AStartAddr and end of the flash
843   * @retval None
844   */
FLASH_OB_PCROP1AConfig(uint32_t PCROPConfig,uint32_t PCROP1AStartAddr,uint32_t PCROP1AEndAddr)845 static void FLASH_OB_PCROP1AConfig(uint32_t PCROPConfig, uint32_t PCROP1AStartAddr, uint32_t PCROP1AEndAddr)
846 {
847   uint32_t startoffset;
848   uint32_t endoffset;
849   uint32_t pcrop1aend;
850   uint32_t ropbase;
851 
852   /* Check the parameters */
853   assert_param(IS_OB_PCROP_CONFIG(PCROPConfig));
854 
855 #if defined(FLASH_DBANK_SUPPORT)
856   /* Check if banks are swapped (valid if only one bank) */
857   if (((FLASH->OPTR & FLASH_OPTR_nSWAP_BANK) != FLASH_OPTR_nSWAP_BANK) && (FLASH_BANK_NB == 2U))
858   {
859     /* Check the parameters */
860     assert_param(IS_FLASH_MAIN_SECONDHALF_MEM_ADDRESS(PCROP1AStartAddr));
861     assert_param(IS_FLASH_MAIN_SECONDHALF_MEM_ADDRESS(PCROP1AEndAddr));
862 
863     /* Bank swap, bank 1 read only protection is on second half of Flash */
864     ropbase = (FLASH_BASE + FLASH_BANK_SIZE);
865   }
866   else
867 #endif /* FLASH_DBANK_SUPPORT */
868   {
869     /* Check the parameters */
870     assert_param(IS_FLASH_MAIN_FIRSTHALF_MEM_ADDRESS(PCROP1AStartAddr));
871     assert_param(IS_FLASH_MAIN_FIRSTHALF_MEM_ADDRESS(PCROP1AEndAddr));
872 
873     /* No Bank swap, bank 1 read only protection is on first half of Flash */
874     ropbase = FLASH_BASE;
875   }
876 
877   /* get pcrop 1A end register */
878   pcrop1aend = FLASH->PCROP1AER;
879 
880   /* Configure the Proprietary code readout protection offset */
881   if ((PCROPConfig & OB_PCROP_ZONE_A) != 0x00U)
882   {
883     /* Compute offset depending on pcrop granularity */
884     startoffset = ((PCROP1AStartAddr - ropbase) >> FLASH_PCROP_GRANULARITY_OFFSET);
885     endoffset = ((PCROP1AEndAddr - ropbase) >> FLASH_PCROP_GRANULARITY_OFFSET);
886 
887     /* Set Zone A start offset */
888     FLASH->PCROP1ASR = startoffset;
889 
890     /* Set Zone A end offset */
891     pcrop1aend &= ~FLASH_PCROP1AER_PCROP1A_END;
892     pcrop1aend |= endoffset;
893   }
894 
895   /* Set RDP erase protection if needed. This bit is only set & will be reset by mass erase */
896   if ((PCROPConfig & OB_PCROP_RDP_ERASE) != 0x00U)
897   {
898     pcrop1aend |= FLASH_PCROP1AER_PCROP_RDP;
899   }
900 
901   /* set 1A End register */
902   FLASH->PCROP1AER = pcrop1aend;
903 }
904 
905 /**
906   * @brief  Configure the 1B Proprietary code readout protection.
907   * @note   It is recommended to align PCROP zone with page granularity when using PCROP_RDP or avoid
908   *         having some executable code in a page where PCROP zone starts or ends.
909   * @note   Minimum PCROP area size is 2 times the chosen granularity: PCROPB_STRT and PCROPB_END.
910   *         So if the requirement is to be able to read-protect 1KB areas, the ROP granularity
911   *         has to be set to 512 Bytes
912   * @param  PCROP1BStartAddr  Specifies the Zone 1B Start address of the Proprietary code readout protection
913   *         This parameter can be an address between begin and end of the flash
914   * @param  PCROP1BEndAddr  Specifies the Zone 1B end address of the Proprietary code readout protection
915   *         This parameter can be an address between PCROP1BStartAddr and end of the flash
916   * @retval None
917   */
FLASH_OB_PCROP1BConfig(uint32_t PCROP1BStartAddr,uint32_t PCROP1BEndAddr)918 static void FLASH_OB_PCROP1BConfig(uint32_t PCROP1BStartAddr, uint32_t PCROP1BEndAddr)
919 {
920   uint32_t startoffset;
921   uint32_t endoffset;
922   uint32_t ropbase;
923 
924 #if defined(FLASH_DBANK_SUPPORT)
925   /* Check if banks are swapped (valid if only one bank) */
926   if (((FLASH->OPTR & FLASH_OPTR_nSWAP_BANK) != FLASH_OPTR_nSWAP_BANK) && (FLASH_BANK_NB == 2U))
927   {
928     /* Check the parameters */
929     assert_param(IS_FLASH_MAIN_SECONDHALF_MEM_ADDRESS(PCROP1BStartAddr));
930     assert_param(IS_FLASH_MAIN_SECONDHALF_MEM_ADDRESS(PCROP1BEndAddr));
931 
932     /* Bank swap, bank 1 read only protection is on second half of Flash */
933     ropbase = (FLASH_BASE + FLASH_BANK_SIZE);
934   }
935   else
936 #endif /* FLASH_DBANK_SUPPORT */
937   {
938     /* Check the parameters */
939     assert_param(IS_FLASH_MAIN_FIRSTHALF_MEM_ADDRESS(PCROP1BStartAddr));
940     assert_param(IS_FLASH_MAIN_FIRSTHALF_MEM_ADDRESS(PCROP1BEndAddr));
941 
942     /* No Bank swap, bank 1 read only protection is on first half of Flash */
943     ropbase = FLASH_BASE;
944   }
945 
946   /* Configure the Proprietary code readout protection offset */
947   startoffset = ((PCROP1BStartAddr - ropbase) >> FLASH_PCROP_GRANULARITY_OFFSET);
948   endoffset = ((PCROP1BEndAddr - ropbase) >> FLASH_PCROP_GRANULARITY_OFFSET);
949 
950   /* Set Zone B start offset */
951   FLASH->PCROP1BSR = startoffset;
952   /* Set Zone B end offset */
953   FLASH->PCROP1BER = endoffset;
954 }
955 
956 /**
957   * @brief  Return the FLASH PCROP Protection Option Bytes value.
958   * @param  PCROPConfig [out]  specifies the configuration of PCROP_RDP option.
959   * @param  PCROP1AStartAddr [out]  Specifies the address where to copied the start address
960   *         of the 1A Proprietary code readout protection
961   * @param  PCROP1AEndAddr [out]  Specifies the address where to copied the end address of
962   *         the 1A Proprietary code readout protection
963   * @retval None
964   */
FLASH_OB_GetPCROP1A(uint32_t * PCROPConfig,uint32_t * PCROP1AStartAddr,uint32_t * PCROP1AEndAddr)965 static void FLASH_OB_GetPCROP1A(uint32_t *PCROPConfig, uint32_t *PCROP1AStartAddr, uint32_t *PCROP1AEndAddr)
966 {
967   uint32_t pcrop;
968   uint32_t ropbase;
969 
970 #if defined(FLASH_DBANK_SUPPORT)
971   /* Check if banks are swapped (valid if only one bank) */
972   if (((FLASH->OPTR & FLASH_OPTR_nSWAP_BANK) != FLASH_OPTR_nSWAP_BANK) && (FLASH_BANK_NB == 2U))
973   {
974     /* Bank swap, bank 1 read only protection is on second half of Flash */
975     ropbase = (FLASH_BASE + FLASH_BANK_SIZE);
976   }
977   else
978 #endif /* FLASH_DBANK_SUPPORT */
979   {
980     /* No Bank swap, bank 1 read only protection is on first half of Flash */
981     ropbase = FLASH_BASE;
982   }
983 
984   pcrop = (FLASH->PCROP1ASR & FLASH_PCROP1ASR_PCROP1A_STRT);
985   *PCROP1AStartAddr = (pcrop << FLASH_PCROP_GRANULARITY_OFFSET);
986   *PCROP1AStartAddr += ropbase;
987 
988   pcrop = FLASH->PCROP1AER;
989   *PCROP1AEndAddr = ((pcrop & FLASH_PCROP1AER_PCROP1A_END) << FLASH_PCROP_GRANULARITY_OFFSET);
990   *PCROP1AEndAddr += (ropbase + FLASH_PCROP_GRANULARITY - 1U);
991 
992   *PCROPConfig &= ~OB_PCROP_RDP_ERASE;
993   *PCROPConfig |= (pcrop & FLASH_PCROP1AER_PCROP_RDP);
994 }
995 
996 /**
997   * @brief  Return the FLASH PCROP Protection Option Bytes value.
998   * @param  PCROP1BStartAddr [out]  Specifies the address where to copied the start address
999   *         of the 1B Proprietary code readout protection
1000   * @param  PCROP1BEndAddr [out]  Specifies the address where to copied the end address of
1001   *         the 1B Proprietary code readout protection
1002   * @retval None
1003   */
FLASH_OB_GetPCROP1B(uint32_t * PCROP1BStartAddr,uint32_t * PCROP1BEndAddr)1004 static void FLASH_OB_GetPCROP1B(uint32_t *PCROP1BStartAddr, uint32_t *PCROP1BEndAddr)
1005 {
1006   uint32_t pcrop;
1007   uint32_t ropbase;
1008 
1009 #if defined(FLASH_DBANK_SUPPORT)
1010   /* Check if banks are swapped (valid if only one bank) */
1011   if (((FLASH->OPTR & FLASH_OPTR_nSWAP_BANK) != FLASH_OPTR_nSWAP_BANK) && (FLASH_BANK_NB == 2U))
1012   {
1013     /* Bank swap, bank 1 read only protection is on second half of Flash */
1014     ropbase = (FLASH_BASE + FLASH_BANK_SIZE);
1015   }
1016   else
1017 #endif /* FLASH_DBANK_SUPPORT */
1018   {
1019     /* No Bank swap, bank 1 read only protection is on first half of Flash */
1020     ropbase = FLASH_BASE;
1021   }
1022 
1023   pcrop = (FLASH->PCROP1BSR & FLASH_PCROP1BSR_PCROP1B_STRT);
1024   *PCROP1BStartAddr = (pcrop << FLASH_PCROP_GRANULARITY_OFFSET);
1025   *PCROP1BStartAddr += ropbase;
1026 
1027   pcrop = (FLASH->PCROP1BER & FLASH_PCROP1BER_PCROP1B_END);
1028   *PCROP1BEndAddr = (pcrop << FLASH_PCROP_GRANULARITY_OFFSET);
1029   *PCROP1BEndAddr += (ropbase + FLASH_PCROP_GRANULARITY - 1U);
1030 }
1031 
1032 #if defined(FLASH_DBANK_SUPPORT)
1033 /**
1034   * @brief  Configure the 2A Proprietary code readout protection.
1035   * @note   It is recommended to align PCROP zone with page granularity when using PCROP_RDP or avoid
1036   *         having some executable code in a page where PCROP zone starts or ends.
1037   * @note   Minimum PCROP area size is 2 times the chosen granularity: PCROPA_STRT and PCROPA_END.
1038   *         So if the requirement is to be able to read-protect 1KB areas, the ROP granularity
1039   *         has to be set to 512 Bytes
1040   * @param  PCROP2AStartAddr  Specifies the Zone 2A Start address of the Proprietary code readout protection
1041   *         This parameter can be an address between begin and end of the flash
1042   * @param  PCROP2AEndAddr  Specifies the Zone 2A end address of the Proprietary code readout protection
1043   *         This parameter can be an address between PCROP2AStartAddr and end of the flash
1044   * @retval None
1045   */
FLASH_OB_PCROP2AConfig(uint32_t PCROP2AStartAddr,uint32_t PCROP2AEndAddr)1046 static void FLASH_OB_PCROP2AConfig(uint32_t PCROP2AStartAddr, uint32_t PCROP2AEndAddr)
1047 {
1048   uint32_t startoffset;
1049   uint32_t endoffset;
1050   uint32_t ropbase;
1051 
1052   /* Check if banks are swapped */
1053   if ((FLASH->OPTR & FLASH_OPTR_nSWAP_BANK) != 0x00u)
1054   {
1055     /* Check the parameters */
1056     assert_param(IS_FLASH_MAIN_SECONDHALF_MEM_ADDRESS(PCROP2AStartAddr));
1057     assert_param(IS_FLASH_MAIN_SECONDHALF_MEM_ADDRESS(PCROP2AEndAddr));
1058 
1059     /* No Bank swap, bank 2 read only protection is on second half of Flash */
1060     ropbase = (FLASH_BASE + FLASH_BANK_SIZE);
1061   }
1062   else
1063   {
1064     /* Check the parameters */
1065     assert_param(IS_FLASH_MAIN_FIRSTHALF_MEM_ADDRESS(PCROP2AStartAddr));
1066     assert_param(IS_FLASH_MAIN_FIRSTHALF_MEM_ADDRESS(PCROP2AEndAddr));
1067 
1068     /* Bank swap, bank 2 read only protection is on first half of Flash */
1069     ropbase = FLASH_BASE;
1070   }
1071 
1072   /* Configure the Proprietary code readout protection offset */
1073   startoffset = ((PCROP2AStartAddr - ropbase) >> FLASH_PCROP_GRANULARITY_OFFSET);
1074   endoffset = ((PCROP2AEndAddr - ropbase) >> FLASH_PCROP_GRANULARITY_OFFSET);
1075 
1076   /* Set Zone A start offset */
1077   FLASH->PCROP2ASR = startoffset;
1078   /* Set Zone A end offset */
1079   FLASH->PCROP2AER = endoffset;
1080 }
1081 
1082 /**
1083   * @brief  Configure the 2B Proprietary code readout protection.
1084   * @note   It is recommended to align PCROP zone with page granularity when using PCROP_RDP or avoid
1085   *         having some executable code in a page where PCROP zone starts or ends.
1086   * @note   Minimum PCROP area size is 2 times the chosen granularity: PCROP_STRT and PCROP_END.
1087   *         So if the requirement is to be able to read-protect 1KB areas, the ROP granularity
1088   *         has to be set to 512 Bytes
1089   * @param  PCROP2BStartAddr  Specifies the Zone 2B Start address of the Proprietary code readout protection
1090   *         This parameter can be an address between begin and end of the flash
1091   * @param  PCROP2BEndAddr  Specifies the Zone 2B end address of the Proprietary code readout protection
1092   *         This parameter can be an address between PCROP2BStartAddr and end of the flash
1093   * @retval None
1094   */
FLASH_OB_PCROP2BConfig(uint32_t PCROP2BStartAddr,uint32_t PCROP2BEndAddr)1095 static void FLASH_OB_PCROP2BConfig(uint32_t PCROP2BStartAddr, uint32_t PCROP2BEndAddr)
1096 {
1097   uint32_t startoffset;
1098   uint32_t endoffset;
1099   uint32_t ropbase;
1100 
1101   /* Check if banks are swapped */
1102   if ((FLASH->OPTR & FLASH_OPTR_nSWAP_BANK) != 0x00u)
1103   {
1104     /* Check the parameters */
1105     assert_param(IS_FLASH_MAIN_SECONDHALF_MEM_ADDRESS(PCROP2BStartAddr));
1106     assert_param(IS_FLASH_MAIN_SECONDHALF_MEM_ADDRESS(PCROP2BEndAddr));
1107 
1108     /* No Bank swap, bank 2 read only protection is on second half of Flash */
1109     ropbase = (FLASH_BASE + FLASH_BANK_SIZE);
1110   }
1111   else
1112   {
1113     /* Check the parameters */
1114     assert_param(IS_FLASH_MAIN_FIRSTHALF_MEM_ADDRESS(PCROP2BStartAddr));
1115     assert_param(IS_FLASH_MAIN_FIRSTHALF_MEM_ADDRESS(PCROP2BEndAddr));
1116 
1117     /* Bank swap, bank 2 read only protection is on first half of Flash */
1118     ropbase = FLASH_BASE;
1119   }
1120 
1121   /* Configure the Proprietary code readout protection offset */
1122   startoffset = ((PCROP2BStartAddr - ropbase) >> FLASH_PCROP_GRANULARITY_OFFSET);
1123   endoffset = ((PCROP2BEndAddr - ropbase) >> FLASH_PCROP_GRANULARITY_OFFSET);
1124 
1125   /* Set Zone B start offset */
1126   FLASH->PCROP2BSR = startoffset;
1127   /* Set Zone B end offset */
1128   FLASH->PCROP2BER = endoffset;
1129 }
1130 
1131 /**
1132   * @brief  Return the FLASH PCROP Protection Option Bytes value.
1133   * @param  PCROP2AStartAddr [out]  Specifies the address where to copied the start address
1134   *         of the 2A Proprietary code readout protection
1135   * @param  PCROP2AEndAddr [out]  Specifies the address where to copied the end address of
1136   *         the 2A Proprietary code readout protection
1137   * @retval None
1138   */
FLASH_OB_GetPCROP2A(uint32_t * PCROP2AStartAddr,uint32_t * PCROP2AEndAddr)1139 static void FLASH_OB_GetPCROP2A(uint32_t *PCROP2AStartAddr, uint32_t *PCROP2AEndAddr)
1140 {
1141   uint32_t pcrop;
1142   uint32_t ropbase;
1143 
1144   /* Check if banks are swapped */
1145   if ((FLASH->OPTR & FLASH_OPTR_nSWAP_BANK) != 0x00u)
1146   {
1147     /* No Bank swap, bank 2 read only protection is on second half of Flash */
1148     ropbase = (FLASH_BASE + FLASH_BANK_SIZE);
1149   }
1150   else
1151   {
1152     /* Bank swap, bank 2 read only protection is on first half of Flash */
1153     ropbase = FLASH_BASE;
1154   }
1155 
1156   pcrop = (FLASH->PCROP2ASR & FLASH_PCROP2ASR_PCROP2A_STRT);
1157   *PCROP2AStartAddr = (pcrop << FLASH_PCROP_GRANULARITY_OFFSET);
1158   *PCROP2AStartAddr += ropbase;
1159 
1160   pcrop = (FLASH->PCROP2AER & FLASH_PCROP2AER_PCROP2A_END);
1161   *PCROP2AEndAddr = (pcrop << FLASH_PCROP_GRANULARITY_OFFSET);
1162   *PCROP2AEndAddr += (ropbase + FLASH_PCROP_GRANULARITY - 1U);
1163 }
1164 
1165 /**
1166   * @brief  Return the FLASH PCROP Protection Option Bytes value.
1167   * @param  PCROP2BStartAddr [out]  Specifies the address where to copied the start address
1168   *         of the 2B Proprietary code readout protection
1169   * @param  PCROP2BEndAddr [out]  Specifies the address where to copied the end address of
1170   *         the 2B Proprietary code readout protection
1171   * @retval None
1172   */
FLASH_OB_GetPCROP2B(uint32_t * PCROP2BStartAddr,uint32_t * PCROP2BEndAddr)1173 static void FLASH_OB_GetPCROP2B(uint32_t *PCROP2BStartAddr, uint32_t *PCROP2BEndAddr)
1174 {
1175   uint32_t pcrop;
1176   uint32_t ropbase;
1177 
1178   /* Check if banks are swapped */
1179   if ((FLASH->OPTR & FLASH_OPTR_nSWAP_BANK) != 0x00u)
1180   {
1181     /* No Bank swap, bank 2 read only protection is on second half of Flash */
1182     ropbase = (FLASH_BASE + FLASH_BANK_SIZE);
1183   }
1184   else
1185   {
1186     /* Bank swap, bank 2 read only protection is on first half of Flash */
1187     ropbase = FLASH_BASE;
1188   }
1189 
1190   pcrop = (FLASH->PCROP2BSR & FLASH_PCROP2BSR_PCROP2B_STRT);
1191   *PCROP2BStartAddr = (pcrop << FLASH_PCROP_GRANULARITY_OFFSET);
1192   *PCROP2BStartAddr += ropbase;
1193 
1194   pcrop = (FLASH->PCROP2BER & FLASH_PCROP2BER_PCROP2B_END);
1195   *PCROP2BEndAddr = (pcrop << FLASH_PCROP_GRANULARITY_OFFSET);
1196   *PCROP2BEndAddr += (ropbase + FLASH_PCROP_GRANULARITY - 1U);
1197 }
1198 #endif /* FLASH_DBANK_SUPPORT */
1199 #endif /* FLASH_PCROP_SUPPORT */
1200 
1201 #if defined(FLASH_SECURABLE_MEMORY_SUPPORT)
1202 #if defined(FLASH_DBANK_SUPPORT)
1203 /**
1204   * @brief  Configure Securable Memory area feature.
1205   * @param  BootEntry  specifies if boot scheme is forced to Flash (System or user) or not
1206   *         This parameter can be one of the following values:
1207   *           @arg @ref OB_BOOT_ENTRY_FORCED_NONE No boot entry forced
1208   *           @arg @ref OB_BOOT_ENTRY_FORCED_FLASH Flash selected as unique entry boot
1209   * @param  SecSize specifies number of pages to protect as securable memory area, starting from
1210   *         beginning of Bank1 (page 0).
1211   * @param  SecSize2 specifies number of pages to protect as securable memory area, starting from
1212   *         beginning of Bank2 (page 0).
1213   * @retval None
1214   */
FLASH_OB_SecMemConfig(uint32_t BootEntry,uint32_t SecSize,uint32_t SecSize2)1215 static void FLASH_OB_SecMemConfig(uint32_t BootEntry, uint32_t SecSize, uint32_t SecSize2)
1216 {
1217   uint32_t secmem;
1218 
1219   /* Check the parameters */
1220   assert_param(IS_OB_SEC_BOOT_LOCK(BootEntry));
1221   assert_param(IS_OB_SEC_SIZE(SecSize));
1222 
1223   if ((FLASH_BANK_NB == 2U))
1224   {
1225     assert_param(IS_OB_SEC_SIZE(SecSize2));
1226   }
1227 
1228   /* Set securable memory area configuration */
1229   secmem = (FLASH->SECR & ~(FLASH_SECR_BOOT_LOCK | FLASH_SECR_SEC_SIZE | FLASH_SECR_SEC_SIZE2));
1230   FLASH->SECR = (secmem | BootEntry | SecSize | (SecSize2 << FLASH_SECR_SEC_SIZE2_Pos));
1231 }
1232 
1233 /**
1234   * @brief  Return the FLASH Securable memory area protection Option Bytes value.
1235   * @param  BootEntry  specifies boot scheme configuration
1236   * @param  SecSize specifies number of pages to protect as secure memory area, starting from
1237   *         beginning of Bank1 (page 0).
1238   * @param  SecSize2 specifies number of pages to protect as secure memory area, starting from
1239   *         beginning of Bank2 (page 0).
1240   * @retval None
1241   */
FLASH_OB_GetSecMem(uint32_t * BootEntry,uint32_t * SecSize,uint32_t * SecSize2)1242 static void FLASH_OB_GetSecMem(uint32_t *BootEntry, uint32_t *SecSize, uint32_t *SecSize2)
1243 {
1244   uint32_t secmem = FLASH->SECR;
1245 
1246   *BootEntry = (secmem & FLASH_SECR_BOOT_LOCK);
1247   *SecSize = (secmem & FLASH_SECR_SEC_SIZE);
1248   *SecSize2 = (secmem & FLASH_SECR_SEC_SIZE2) >> FLASH_SECR_SEC_SIZE2_Pos;
1249 }
1250 
1251 #else
1252 /**
1253   * @brief  Configure Securable Memory area feature.
1254   * @param  BootEntry  specifies if boot scheme is forced to Flash (System or user) or not
1255   *         This parameter can be one of the following values:
1256   *           @arg @ref OB_BOOT_ENTRY_FORCED_NONE No boot entry forced
1257   *           @arg @ref OB_BOOT_ENTRY_FORCED_FLASH FLash selected as unique entry boot
1258   * @param  SecSize specifies number of pages to protect as securable memory area, starting from
1259   *         beginning of the Flash (page 0).
1260   * @retval None
1261   */
FLASH_OB_SecMemConfig(uint32_t BootEntry,uint32_t SecSize)1262 static void FLASH_OB_SecMemConfig(uint32_t BootEntry, uint32_t SecSize)
1263 {
1264   uint32_t secmem;
1265 
1266   /* Check the parameters */
1267   assert_param(IS_OB_SEC_BOOT_LOCK(BootEntry));
1268   assert_param(IS_OB_SEC_SIZE(SecSize));
1269 
1270   /* Set securable memory area configuration */
1271   secmem = (FLASH->SECR & ~(FLASH_SECR_BOOT_LOCK | FLASH_SECR_SEC_SIZE));
1272   FLASH->SECR = (secmem | BootEntry | SecSize);
1273 }
1274 
1275 /**
1276   * @brief  Return the FLASH Securable memory area protection Option Bytes value.
1277   * @param  BootEntry  specifies boot scheme configuration
1278   * @param  SecSize specifies number of pages to protect as secure memory area, starting from
1279   *         beginning of the Flash (page 0).
1280   * @retval None
1281   */
FLASH_OB_GetSecMem(uint32_t * BootEntry,uint32_t * SecSize)1282 static void FLASH_OB_GetSecMem(uint32_t *BootEntry, uint32_t *SecSize)
1283 {
1284   uint32_t secmem = FLASH->SECR;
1285 
1286   *BootEntry = (secmem & FLASH_SECR_BOOT_LOCK);
1287   *SecSize = (secmem & FLASH_SECR_SEC_SIZE);
1288 }
1289 #endif /* FLASH_DBANK_SUPPORT */
1290 #endif /* FLASH_SECURABLE_MEMORY_SUPPORT */
1291 
1292 /**
1293   * @}
1294   */
1295 
1296 /**
1297   * @}
1298   */
1299 
1300 #endif /* HAL_FLASH_MODULE_ENABLED */
1301 
1302 /**
1303   * @}
1304   */
1305 
1306 /**
1307   * @}
1308   */
1309 
1310