1 /**
2   ******************************************************************************
3   * @file    stm32c0xx_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   ******************************************************************************
11   * @attention
12   *
13   * Copyright (c) 2022 STMicroelectronics.
14   * All rights reserved.
15   *
16   * This software is licensed under terms that can be found in the LICENSE file
17   * in the root directory of this software component.
18   * If no LICENSE file comes with this software, it is provided AS-IS.
19   *
20   ******************************************************************************
21  @verbatim
22  ==============================================================================
23                    ##### Flash Extended features #####
24   ==============================================================================
25 
26   [..] Comparing to other previous devices, the FLASH interface for STM32C0xx
27        devices contains the following additional features
28 
29        (+) Capacity up to 128 Kbytes with single bank architecture supporting read-while-write
30            capability (RWW)
31        (+) Single bank memory organization
32        (+) PCROP protection
33 
34                         ##### How to use this driver #####
35  ==============================================================================
36   [..] This driver provides functions to configure and program the FLASH memory
37        of all STM32C0xx devices. It includes
38       (#) Flash Memory Erase functions:
39            (++) Lock and Unlock the FLASH interface using HAL_FLASH_Unlock() and
40                 HAL_FLASH_Lock() functions
41            (++) Erase function: Erase page, erase all sectors
42            (++) There are two modes of erase :
43              (+++) Polling Mode using HAL_FLASHEx_Erase()
44              (+++) Interrupt Mode using HAL_FLASHEx_Erase_IT()
45 
46       (#) Option Bytes Programming function: Use HAL_FLASHEx_OBProgram() to :
47         (++) Set/Reset the write protection
48         (++) Set the Read protection Level
49         (++) Program the user Option Bytes
50         (++) Configure the PCROP protection
51         (++) Set Securable memory area and boot entry point
52 
53       (#) Get Option Bytes Configuration function: Use HAL_FLASHEx_OBGetConfig() to :
54         (++) Get the value of a write protection area
55         (++) Know if the read protection is activated
56         (++) Get the value of the user Option Bytes
57         (++) Get Securable memory area and boot entry point information
58 
59       (#) Enable or disable debugger usage using HAL_FLASHEx_EnableDebugger and
60           HAL_FLASHEx_DisableDebugger.
61 
62       (#) Check is flash content is empty or not using HAL_FLASHEx_FlashEmptyCheck.
63           and modify this setting (for flash loader purpose e.g.) using
64           HAL_FLASHEx_ForceFlashEmpty.
65 
66       (#) Enable securable memory area protectionusing HAL_FLASHEx_EnableSecMemProtection
67 
68  @endverbatim
69   ******************************************************************************
70   */
71 
72 /* Includes ------------------------------------------------------------------*/
73 #include "stm32c0xx_hal.h"
74 
75 /** @addtogroup STM32C0xx_HAL_Driver
76   * @{
77   */
78 
79 /** @defgroup FLASHEx FLASHEx
80   * @brief FLASH Extended HAL module driver
81   * @{
82   */
83 
84 #ifdef HAL_FLASH_MODULE_ENABLED
85 
86 /* Private typedef -----------------------------------------------------------*/
87 /* Private define ------------------------------------------------------------*/
88 /* Private macro -------------------------------------------------------------*/
89 /* Private variables ---------------------------------------------------------*/
90 /* Private function prototypes -----------------------------------------------*/
91 /** @defgroup FLASHEx_Private_Functions FLASHEx Private Functions
92   * @{
93   */
94 static void            FLASH_MassErase(void);
95 void                   FLASH_FlushCaches(void);
96 static void            FLASH_OB_WRPConfig(uint32_t WRPArea, uint32_t WRPStartOffset, uint32_t WRDPEndOffset);
97 static void            FLASH_OB_OptrConfig(uint32_t UserType, uint32_t UserConfig, uint32_t RDPLevel);
98 static void            FLASH_OB_PCROP1AConfig(uint32_t PCROPConfig, uint32_t PCROP1AStartAddr, uint32_t PCROP1AEndAddr);
99 static void            FLASH_OB_PCROP1BConfig(uint32_t PCROP1BStartAddr, uint32_t PCROP1BEndAddr);
100 static void            FLASH_OB_SecMemConfig(uint32_t BootEntry, uint32_t SecSize);
101 static void            FLASH_OB_GetWRP(uint32_t WRPArea, uint32_t *WRPStartOffset, uint32_t *WRDPEndOffset);
102 static uint32_t        FLASH_OB_GetRDP(void);
103 static uint32_t        FLASH_OB_GetUser(void);
104 static void            FLASH_OB_GetPCROP1A(uint32_t *PCROPConfig, uint32_t *PCROP1AStartAddr, uint32_t *PCROP1AEndAddr);
105 static void            FLASH_OB_GetPCROP1B(uint32_t *PCROP1BStartAddr, uint32_t *PCROP1BEndAddr);
106 static void            FLASH_OB_GetSecMem(uint32_t *BootEntry, uint32_t *SecSize);
107 /**
108   * @}
109   */
110 
111 /* Exported functions -------------------------------------------------------*/
112 /** @defgroup FLASHEx_Exported_Functions FLASH Extended Exported Functions
113   * @{
114   */
115 
116 /** @defgroup FLASHEx_Exported_Functions_Group1 Extended IO operation functions
117   *  @brief   Extended IO operation functions
118   *
119 @verbatim
120  ===============================================================================
121                 ##### Extended programming operation functions #####
122  ===============================================================================
123     [..]
124     This subsection provides a set of functions allowing to manage the Extended FLASH
125     programming operations Operations.
126 
127 @endverbatim
128   * @{
129   */
130 /**
131   * @brief  Perform a mass erase or erase the specified FLASH memory pages.
132   * @param[in]  pEraseInit Pointer to an @ref FLASH_EraseInitTypeDef structure that
133   *         contains the configuration information for the erasing.
134   * @param[out]  PageError Pointer to variable that contains the configuration
135   *         information on faulty page in case of error (0xFFFFFFFF means that all
136   *         the pages have been correctly erased)
137   * @retval HAL Status
138   */
HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef * pEraseInit,uint32_t * PageError)139 HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *PageError)
140 {
141   HAL_StatusTypeDef status;
142   uint32_t index;
143 
144   /* Check the parameters */
145   assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase));
146 
147   /* Process Locked */
148   __HAL_LOCK(&pFlash);
149 
150   /* Reset error code */
151   pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
152 
153   /* Wait for last operation to be completed */
154   status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
155 
156   if (status == HAL_OK)
157   {
158     if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASS)
159     {
160       /* Mass erase to be done */
161       FLASH_MassErase();
162 
163       /* Wait for last operation to be completed */
164       status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
165     }
166     else
167     {
168       /*Initialization of PageError variable*/
169       *PageError = 0xFFFFFFFFU;
170 
171       for (index = pEraseInit->Page; index < (pEraseInit->Page + pEraseInit->NbPages); index++)
172       {
173         /* Start erase page */
174         FLASH_PageErase(index);
175 
176         /* Wait for last operation to be completed */
177         status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
178 
179         if (status != HAL_OK)
180         {
181           /* In case of error, stop erase procedure and return the faulty address */
182           *PageError = index;
183           break;
184         }
185       }
186 
187       /* If operation is completed or interrupted, disable the Page Erase Bit */
188       CLEAR_BIT(FLASH->CR, FLASH_CR_PER);
189     }
190   }
191 
192   /* Process Unlocked */
193   __HAL_UNLOCK(&pFlash);
194 
195   /* return status */
196   return status;
197 }
198 
199 
200 /**
201   * @brief  Perform a mass erase or erase the specified FLASH memory pages with interrupt enabled.
202   * @param  pEraseInit Pointer to an @ref FLASH_EraseInitTypeDef structure that
203   *         contains the configuration information for the erasing.
204   * @retval HAL Status
205   */
HAL_FLASHEx_Erase_IT(FLASH_EraseInitTypeDef * pEraseInit)206 HAL_StatusTypeDef HAL_FLASHEx_Erase_IT(FLASH_EraseInitTypeDef *pEraseInit)
207 {
208   HAL_StatusTypeDef status;
209 
210   /* Check the parameters */
211   assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase));
212 
213   /* Process Locked */
214   __HAL_LOCK(&pFlash);
215 
216   /* Reset error code */
217   pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
218 
219   /* save procedure for interrupt treatment */
220   pFlash.ProcedureOnGoing = pEraseInit->TypeErase;
221 
222   /* Wait for last operation to be completed */
223   status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
224 
225   if (status != HAL_OK)
226   {
227     /* Process Unlocked */
228     __HAL_UNLOCK(&pFlash);
229   }
230   else
231   {
232     /* Enable End of Operation and Error interrupts */
233     __HAL_FLASH_ENABLE_IT(FLASH_IT_EOP | FLASH_IT_OPERR);
234 
235     if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASS)
236     {
237       /* Set Page to 0 for Interrupt callback management */
238       pFlash.Page = 0;
239 
240       /* Proceed to Mass Erase */
241       FLASH_MassErase();
242     }
243     else
244     {
245       /* Erase by page to be done */
246       pFlash.NbPagesToErase = pEraseInit->NbPages;
247       pFlash.Page = pEraseInit->Page;
248 
249       /*Erase 1st page and wait for IT */
250       FLASH_PageErase(pEraseInit->Page);
251     }
252   }
253 
254   /* return status */
255   return status;
256 }
257 
258 /**
259   * @brief  Program Option bytes.
260   * @param  pOBInit Pointer to an @ref FLASH_OBProgramInitTypeDef structure that
261   *         contains the configuration information for the programming.
262   * @note   To configure any option bytes, the option lock bit OPTLOCK must be
263   *         cleared with the call of @ref HAL_FLASH_OB_Unlock() function.
264   * @note   New option bytes configuration will be taken into account only
265   *         - after an option bytes launch through the call of @ref HAL_FLASH_OB_Launch()
266   *         - a Power On Reset
267   *         - an exit from Standby or Shutdown mode.
268   * @retval HAL Status
269   */
HAL_FLASHEx_OBProgram(FLASH_OBProgramInitTypeDef * pOBInit)270 HAL_StatusTypeDef HAL_FLASHEx_OBProgram(FLASH_OBProgramInitTypeDef *pOBInit)
271 {
272   uint32_t optr;
273   HAL_StatusTypeDef status;
274 
275   /* Check the parameters */
276   assert_param(IS_OPTIONBYTE(pOBInit->OptionType));
277 
278   /* Process Locked */
279   __HAL_LOCK(&pFlash);
280 
281   pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
282 
283   /* Write protection configuration */
284   if ((pOBInit->OptionType & OPTIONBYTE_WRP) != 0x00U)
285   {
286     /* Configure of Write protection on the selected area */
287     FLASH_OB_WRPConfig(pOBInit->WRPArea, pOBInit->WRPStartOffset, pOBInit->WRPEndOffset);
288   }
289 
290   /* Option register */
291   if ((pOBInit->OptionType & (OPTIONBYTE_RDP | OPTIONBYTE_USER)) == (OPTIONBYTE_RDP | OPTIONBYTE_USER))
292   {
293     /* Fully modify OPTR register with RDP & user data */
294     FLASH_OB_OptrConfig(pOBInit->USERType, pOBInit->USERConfig, pOBInit->RDPLevel);
295   }
296   else if ((pOBInit->OptionType & OPTIONBYTE_RDP) != 0x00U)
297   {
298     /* Only modify RDP so get current user data */
299     optr = FLASH_OB_GetUser();
300     FLASH_OB_OptrConfig(optr, optr, pOBInit->RDPLevel);
301   }
302   else if ((pOBInit->OptionType & OPTIONBYTE_USER) != 0x00U)
303   {
304     /* Only modify user so get current RDP level */
305     optr = FLASH_OB_GetRDP();
306     FLASH_OB_OptrConfig(pOBInit->USERType, pOBInit->USERConfig, optr);
307   }
308   else
309   {
310     /* nothing to do */
311   }
312 
313   /* PCROP Configuration */
314   if ((pOBInit->OptionType & OPTIONBYTE_PCROP) != 0x00U)
315   {
316     /* Check the parameters */
317     assert_param(IS_OB_PCROP_CONFIG(pOBInit->PCROPConfig));
318 
319     if ((pOBInit->PCROPConfig & (OB_PCROP_ZONE_A | OB_PCROP_RDP_ERASE)) != 0x00U)
320     {
321       /* Configure the 1A Proprietary code readout protection */
322       FLASH_OB_PCROP1AConfig(pOBInit->PCROPConfig, pOBInit->PCROP1AStartAddr, pOBInit->PCROP1AEndAddr);
323     }
324 
325     if ((pOBInit->PCROPConfig & OB_PCROP_ZONE_B) != 0x00U)
326     {
327       /* Configure the 1B Proprietary code readout protection */
328       FLASH_OB_PCROP1BConfig(pOBInit->PCROP1BStartAddr, pOBInit->PCROP1BEndAddr);
329     }
330   }
331 
332   /* Securable Memory Area Configuration */
333   if ((pOBInit->OptionType & OPTIONBYTE_SEC) != 0x00U)
334   {
335     /* Configure the securable memory area protection */
336     FLASH_OB_SecMemConfig(pOBInit->BootEntryPoint, pOBInit->SecSize);
337   }
338 
339 
340   /* Wait for last operation to be completed */
341   status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
342 
343   if (status == HAL_OK)
344   {
345     /* Set OPTSTRT Bit */
346     SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
347 
348     /* Wait for last operation to be completed */
349     status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
350 
351     /* If the option byte program operation is completed, disable the OPTSTRT Bit */
352     CLEAR_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
353   }
354 
355   /* Process Unlocked */
356   __HAL_UNLOCK(&pFlash);
357 
358   /* return status */
359   return status;
360 }
361 
362 /**
363   * @brief  Get the Option bytes configuration.
364   * @note   warning: this API only read flash register, it does not reflect any
365   *         change that would have been programmed between previous Option byte
366   *         loading and current call.
367   * @param  pOBInit Pointer to an @ref FLASH_OBProgramInitTypeDef structure that contains the
368   *                  configuration information. The fields pOBInit->WRPArea and
369   *                  pOBInit->PCROPConfig should indicate which area is requested
370   *                  for the WRP and PCROP.
371   * @retval None
372   */
HAL_FLASHEx_OBGetConfig(FLASH_OBProgramInitTypeDef * pOBInit)373 void HAL_FLASHEx_OBGetConfig(FLASH_OBProgramInitTypeDef *pOBInit)
374 {
375   pOBInit->OptionType = OPTIONBYTE_ALL;
376 
377   /* Get write protection on the selected area */
378   FLASH_OB_GetWRP(pOBInit->WRPArea, &(pOBInit->WRPStartOffset), &(pOBInit->WRPEndOffset));
379 
380   /* Get Read protection level */
381   pOBInit->RDPLevel = FLASH_OB_GetRDP();
382 
383   /* Get the user option bytes */
384   pOBInit->USERConfig = FLASH_OB_GetUser();
385   pOBInit->USERType = OB_USER_ALL;
386 
387   /* Get the Proprietary code readout protection */
388   FLASH_OB_GetPCROP1A(&(pOBInit->PCROPConfig), &(pOBInit->PCROP1AStartAddr), &(pOBInit->PCROP1AEndAddr));
389   FLASH_OB_GetPCROP1B(&(pOBInit->PCROP1BStartAddr), &(pOBInit->PCROP1BEndAddr));
390   pOBInit->PCROPConfig |= (OB_PCROP_ZONE_A | OB_PCROP_ZONE_B);
391 
392   /* Get the Securable Memory Area protection */
393   FLASH_OB_GetSecMem(&(pOBInit->BootEntryPoint), &(pOBInit->SecSize));
394 }
395 
396 /**
397   * @brief  Enable Debugger.
398   * @note   After calling this API, flash interface allow debugger intrusion.
399   * @retval None
400   */
HAL_FLASHEx_EnableDebugger(void)401 void HAL_FLASHEx_EnableDebugger(void)
402 {
403   FLASH->ACR |= FLASH_ACR_DBG_SWEN;
404 }
405 
406 /**
407   * @brief  Disable Debugger.
408   * @note   After calling this API, Debugger is disabled: it is no more possible to
409   *         break, see CPU register, etc...
410   * @retval None
411   */
HAL_FLASHEx_DisableDebugger(void)412 void HAL_FLASHEx_DisableDebugger(void)
413 {
414   FLASH->ACR &= ~FLASH_ACR_DBG_SWEN;
415 }
416 
417 /**
418   * @brief  Flash Empty check
419   * @note   This API checks if first location in Flash is programmed or not.
420   *         This check is done once by Option Byte Loader.
421   * @retval 0 if 1st location is not programmed else
422   */
HAL_FLASHEx_FlashEmptyCheck(void)423 uint32_t HAL_FLASHEx_FlashEmptyCheck(void)
424 {
425   return ((FLASH->ACR & FLASH_ACR_PROGEMPTY));
426 }
427 
428 
429 /**
430   * @brief  Force Empty check value.
431   * @note   Allows to modify program empty check value in order to force this
432   *         infrmation in Flash Interface, for all next reset that do not launch
433   *         Option Byte Loader.
434   * @param  FlashEmpty this parameter can be a value of @ref FLASHEx_Empty_Check
435   * @retval None
436   */
HAL_FLASHEx_ForceFlashEmpty(uint32_t FlashEmpty)437 void HAL_FLASHEx_ForceFlashEmpty(uint32_t FlashEmpty)
438 {
439   uint32_t acr;
440   assert_param(IS_FLASH_EMPTY_CHECK(FlashEmpty));
441 
442   acr = (FLASH->ACR & ~FLASH_ACR_PROGEMPTY);
443   FLASH->ACR = (acr | FlashEmpty);
444 }
445 
446 /**
447   * @brief  Securable memory area protection enable
448   * @param  Bank Select Bank to be secured. On C0, there is only 1 bank so
449   *         parameter has to be set to 0.
450   * @note   This API locks Securable memory area which is defined in SEC_SIZE option byte
451   *         (that can be retrieved calling HAL_FLASHEx_OBGetConfig API and checking
452   *         Secsize).
453   * @note   SEC_PROT bit can only be set, it will be reset by system reset.
454   * @retval None
455   */
HAL_FLASHEx_EnableSecMemProtection(uint32_t Bank)456 void HAL_FLASHEx_EnableSecMemProtection(uint32_t Bank)
457 {
458   assert_param(IS_FLASH_BANK(Bank));
459   FLASH->CR |= FLASH_CR_SEC_PROT;
460 }
461 
462 /**
463   * @}
464   */
465 
466 /**
467   * @}
468   */
469 
470 /* Private functions ---------------------------------------------------------*/
471 /** @addtogroup FLASHEx_Private_Functions
472   * @{
473   */
474 
475 /**
476   * @brief  Mass erase of FLASH memory.
477   * @retval None
478   */
FLASH_MassErase(void)479 static void FLASH_MassErase(void)
480 {
481   /* Set the Mass Erase Bit and start bit */
482   FLASH->CR |= (FLASH_CR_STRT | FLASH_CR_MER1);
483 }
484 
485 /**
486   * @brief  Erase the specified FLASH memory page.
487   * @param  Page FLASH page to erase
488   *         This parameter must be a value between 0 and (max number of pages in Flash - 1)
489   * @retval None
490   */
FLASH_PageErase(uint32_t Page)491 void FLASH_PageErase(uint32_t Page)
492 {
493   uint32_t tmp;
494 
495   /* Check the parameters */
496   assert_param(IS_FLASH_PAGE(Page));
497 
498   /* Get configuration register, then clear page number */
499   tmp = (FLASH->CR & ~FLASH_CR_PNB);
500 
501   /* Set page number, Page Erase bit & Start bit */
502   FLASH->CR = (tmp | (FLASH_CR_STRT | (Page <<  FLASH_CR_PNB_Pos) | FLASH_CR_PER));
503 }
504 
505 /**
506   * @brief  Flush the instruction cache.
507   * @retval None
508   */
FLASH_FlushCaches(void)509 void FLASH_FlushCaches(void)
510 {
511   /* Flush instruction cache  */
512   if (READ_BIT(FLASH->ACR, FLASH_ACR_ICEN) != 0U)
513   {
514     /* Disable instruction cache  */
515     __HAL_FLASH_INSTRUCTION_CACHE_DISABLE();
516     /* Reset instruction cache */
517     __HAL_FLASH_INSTRUCTION_CACHE_RESET();
518     /* Enable instruction cache */
519     __HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
520   }
521 }
522 
523 
524 /**
525   * @brief  Configure the write protection of the desired pages.
526   * @note   When WRP is active in a zone, it cannot be erased or programmed.
527   *         Consequently, a software mass erase cannot be performed if one zone
528   *         is write-protected.
529   * @note   When the memory read protection level is selected (RDP level = 1),
530   *         it is not possible to program or erase Flash memory if the CPU debug
531   *         features are connected (JTAG or single wire) or boot code is being
532   *         executed from RAM or System flash, even if WRP is not activated.
533   * @param  WRPArea  Specifies the area to be configured.
534   *         This parameter can be one of the following values:
535   *            @arg  @ref OB_WRPAREA_ZONE_A Flash Zone A
536   *            @arg  @ref OB_WRPAREA_ZONE_B Flash Zone B
537   * @param  WRPStartOffset  Specifies the start page of the write protected area
538   *         This parameter can be page number between 0 and (max number of pages in the Flash - 1)
539   * @param  WRDPEndOffset  Specifies the end page of the write protected area
540   *         This parameter can be page number between WRPStartOffset and (max number of pages in the Flash - 1)
541   * @retval None
542   */
FLASH_OB_WRPConfig(uint32_t WRPArea,uint32_t WRPStartOffset,uint32_t WRDPEndOffset)543 static void FLASH_OB_WRPConfig(uint32_t WRPArea, uint32_t WRPStartOffset, uint32_t WRDPEndOffset)
544 {
545   /* Check the parameters */
546   assert_param(IS_OB_WRPAREA(WRPArea));
547   assert_param(IS_FLASH_PAGE(WRPStartOffset));
548   assert_param(IS_FLASH_PAGE(WRDPEndOffset));
549 
550   /* Configure the write protected area */
551   if (WRPArea != OB_WRPAREA_ZONE_A)
552   {
553     FLASH->WRP1BR = ((WRDPEndOffset << FLASH_WRP1AR_WRP1A_END_Pos) | WRPStartOffset);
554   }
555   else
556   {
557     FLASH->WRP1AR = ((WRDPEndOffset << FLASH_WRP1BR_WRP1B_END_Pos) | WRPStartOffset);
558   }
559 }
560 
561 /**
562   * @brief  Set user & RDP configuration
563   * @note   !!! Warning : When enabling OB_RDP level 2 it is no more possible
564   *         to go back to level 1 or 0 !!!
565   * @param  UserType  The FLASH User Option Bytes to be modified.
566   *         This parameter can be a combination of @ref FLASH_OB_USER_Type
567   * @param  UserConfig  The FLASH User Option Bytes values.
568   *         This parameter can be a combination of:
569   *         @arg @ref FLASH_OB_USER_BOR_ENABLE,
570   *         @arg @ref FLASH_OB_USER_BOR_LEVEL,
571   *         @arg @ref FLASH_OB_USER_nRST_STOP,
572   *         @arg @ref FLASH_OB_USER_nRST_STANDBY,
573   *         @arg @ref FLASH_OB_USER_nRST_SHUTDOWN,
574   *         @arg @ref FLASH_OB_USER_IWDG_SW,
575   *         @arg @ref FLASH_OB_USER_IWDG_STOP,
576   *         @arg @ref FLASH_OB_USER_IWDG_STANDBY,
577   *         @arg @ref FLASH_OB_USER_WWDG_SW,
578   *         @arg @ref FLASH_OB_USER_SRAM_PARITY,
579   *         @arg @ref FLASH_OB_USER_nBOOT_SEL,
580   *         @arg @ref FLASH_OB_USER_nBOOT1,
581   *         @arg @ref FLASH_OB_USER_nBOOT0,
582   *         @arg @ref FLASH_OB_USER_INPUT_RESET_HOLDER
583   * @param  RDPLevel  specifies the read protection level.
584   *         This parameter can be one of the following values:
585   *            @arg @ref OB_RDP_LEVEL_0 No protection
586   *            @arg @ref OB_RDP_LEVEL_1 Memory Read protection
587   *            @arg @ref OB_RDP_LEVEL_2 Full chip protection
588   * @retval None
589   */
FLASH_OB_OptrConfig(uint32_t UserType,uint32_t UserConfig,uint32_t RDPLevel)590 static void FLASH_OB_OptrConfig(uint32_t UserType, uint32_t UserConfig, uint32_t RDPLevel)
591 {
592   uint32_t optr;
593 
594   /* Check the parameters */
595   assert_param(IS_OB_USER_TYPE(UserType));
596   assert_param(IS_OB_USER_CONFIG(UserType, UserConfig));
597   assert_param(IS_OB_RDP_LEVEL(RDPLevel));
598 
599   /* Configure the RDP level in the option bytes register */
600   optr = FLASH->OPTR;
601   optr &= ~(UserType | FLASH_OPTR_RDP);
602   FLASH->OPTR = (optr | UserConfig | RDPLevel);
603 }
604 
605 /**
606   * @brief  Configure the 1A Proprietary code readout protection & erase configuration on RDP regression.
607   * @note   It is recommended to align PCROP zone with page granularity when using PCROP_RDP or avoid
608   *         having some executable code in a page where PCROP zone starts or ends.
609   * @note   Minimum PCROP area size is 2 times the chosen granularity: PCROPA_STRT and PCROPA_END.
610   *         So if the requirement is to be able to read-protect 1KB areas, the ROP granularity
611   *         has to be set to 512 Bytes
612   * @param  PCROPConfig  specifies the erase configuration (OB_PCROP_RDP_NOT_ERASE or OB_PCROP_RDP_ERASE)
613   *         on RDP level 1 regression.
614   * @param  PCROP1AStartAddr Specifies the Zone 1A Start address of the Proprietary code readout protection
615   *          This parameter can be an address between begin and end of the flash
616   * @param  PCROP1AEndAddr Specifies the Zone 1A end address of the Proprietary code readout protection
617   *          This parameter can be an address between PCROP1AStartAddr and end of the flash
618   * @retval None
619   */
FLASH_OB_PCROP1AConfig(uint32_t PCROPConfig,uint32_t PCROP1AStartAddr,uint32_t PCROP1AEndAddr)620 static void FLASH_OB_PCROP1AConfig(uint32_t PCROPConfig, uint32_t PCROP1AStartAddr, uint32_t PCROP1AEndAddr)
621 {
622   uint32_t startoffset;
623   uint32_t endoffset;
624   uint32_t pcrop1aend;
625 
626   /* Check the parameters */
627   assert_param(IS_OB_PCROP_CONFIG(PCROPConfig));
628   assert_param(IS_FLASH_MAIN_MEM_ADDRESS(PCROP1AStartAddr));
629   assert_param(IS_FLASH_MAIN_MEM_ADDRESS(PCROP1AEndAddr));
630 
631   /* get pcrop 1A end register */
632   pcrop1aend = FLASH->PCROP1AER;
633 
634   /* Configure the Proprietary code readout protection offset */
635   if ((PCROPConfig & OB_PCROP_ZONE_A) != 0x00U)
636   {
637     /* Compute offset depending on pcrop granularity */
638     startoffset = ((PCROP1AStartAddr - FLASH_BASE) >> FLASH_PCROP_GRANULARITY_OFFSET);
639     endoffset = ((PCROP1AEndAddr - FLASH_BASE) >> FLASH_PCROP_GRANULARITY_OFFSET);
640 
641     /* Set Zone A start offset */
642     FLASH->PCROP1ASR = startoffset;
643 
644     /* Set Zone A end offset */
645     pcrop1aend &= ~FLASH_PCROP1AER_PCROP1A_END;
646     pcrop1aend |= endoffset;
647   }
648 
649   /* Set RDP erase protection if needed. This bit is only set & will be reset by mass erase */
650   if ((PCROPConfig & OB_PCROP_RDP_ERASE) != 0x00U)
651   {
652     pcrop1aend |= FLASH_PCROP1AER_PCROP_RDP;
653   }
654 
655   /* set 1A End register */
656   FLASH->PCROP1AER = pcrop1aend;
657 }
658 
659 /**
660   * @brief  Configure the 1B Proprietary code readout protection.
661   * @note   It is recommended to align PCROP zone with page granularity when using PCROP_RDP or avoid
662   *         having some executable code in a page where PCROP zone starts or ends.
663   * @note   Minimum PCROP area size is 2 times the chosen granularity: PCROPA_STRT and PCROPA_END.
664   *         So if the requirement is to be able to read-protect 1KB areas, the ROP granularity
665   *         has to be set to 512 Bytes
666   * @param  PCROP1BStartAddr  Specifies the Zone 1B Start address of the Proprietary code readout protection
667   *         This parameter can be an address between begin and end of the flash
668   * @param  PCROP1BEndAddr  Specifies the Zone 1B end address of the Proprietary code readout protection
669   *         This parameter can be an address between PCROP1BStartAddr and end of the flash
670   * @retval None
671   */
FLASH_OB_PCROP1BConfig(uint32_t PCROP1BStartAddr,uint32_t PCROP1BEndAddr)672 static void FLASH_OB_PCROP1BConfig(uint32_t PCROP1BStartAddr, uint32_t PCROP1BEndAddr)
673 {
674   uint32_t startoffset;
675   uint32_t endoffset;
676 
677   /* Check the parameters */
678   assert_param(IS_FLASH_MAIN_MEM_ADDRESS(PCROP1BStartAddr));
679   assert_param(IS_FLASH_MAIN_MEM_ADDRESS(PCROP1BEndAddr));
680 
681   /* Configure the Proprietary code readout protection offset */
682   startoffset = ((PCROP1BStartAddr - FLASH_BASE) >> FLASH_PCROP_GRANULARITY_OFFSET);
683   endoffset = ((PCROP1BEndAddr - FLASH_BASE) >> FLASH_PCROP_GRANULARITY_OFFSET);
684 
685   /* Set Zone B start offset */
686   FLASH->PCROP1BSR = startoffset;
687   /* Set Zone B end offset */
688   FLASH->PCROP1BER = endoffset;
689 }
690 
691 /**
692   * @brief  Configure Securable Memory area feature.
693   * @param  BootEntry  specifies if boot scheme is forced to Flash (System or user) or not
694   *         This parameter can be one of the following values:
695   *           @arg @ref OB_BOOT_ENTRY_FORCED_NONE No boot entry forced
696   *           @arg @ref OB_BOOT_ENTRY_FORCED_FLASH FLash selected as unique entry boot
697   * @param  SecSize specifies number of pages to protect as securable memory area, starting from
698   *         beginning of the Flash (page 0).
699   * @retval None
700   */
FLASH_OB_SecMemConfig(uint32_t BootEntry,uint32_t SecSize)701 static void FLASH_OB_SecMemConfig(uint32_t BootEntry, uint32_t SecSize)
702 {
703   uint32_t secmem;
704 
705   /* Check the parameters */
706   assert_param(IS_OB_SEC_BOOT_LOCK(BootEntry));
707   assert_param(IS_OB_SEC_SIZE(SecSize));
708 
709   /* Set securable memory area configuration */
710   secmem = (FLASH->SECR & ~(FLASH_SECR_BOOT_LOCK | FLASH_SECR_SEC_SIZE));
711   FLASH->SECR = (secmem | BootEntry | SecSize);
712 }
713 
714 /**
715   * @brief  Return the FLASH Write Protection Option Bytes value.
716   * @param[in]  WRPArea Specifies the area to be returned.
717   *             This parameter can be one of the following values:
718   *               @arg @ref OB_WRPAREA_ZONE_A Flash Zone A
719   *               @arg @ref OB_WRPAREA_ZONE_B Flash Zone B
720   * @param[out]  WRPStartOffset  Specifies the address where to copied the start page
721   *                         of the write protected area
722   * @param[out]  WRDPEndOffset  Dpecifies the address where to copied the end page of
723   *                        the write protected area
724   * @retval None
725   */
FLASH_OB_GetWRP(uint32_t WRPArea,uint32_t * WRPStartOffset,uint32_t * WRDPEndOffset)726 static void FLASH_OB_GetWRP(uint32_t WRPArea, uint32_t *WRPStartOffset, uint32_t *WRDPEndOffset)
727 {
728   /* Check the parameters */
729   assert_param(IS_OB_WRPAREA(WRPArea));
730 
731   /* Get the configuration of the write protected area */
732   if (WRPArea == OB_WRPAREA_ZONE_A)
733   {
734     *WRPStartOffset = READ_BIT(FLASH->WRP1AR, FLASH_WRP1AR_WRP1A_STRT);
735     *WRDPEndOffset = (READ_BIT(FLASH->WRP1AR, FLASH_WRP1AR_WRP1A_END) >> FLASH_WRP1AR_WRP1A_END_Pos);
736   }
737   else
738   {
739     *WRPStartOffset = READ_BIT(FLASH->WRP1BR, FLASH_WRP1BR_WRP1B_STRT);
740     *WRDPEndOffset = (READ_BIT(FLASH->WRP1BR, FLASH_WRP1BR_WRP1B_END) >> FLASH_WRP1BR_WRP1B_END_Pos);
741   }
742 }
743 
744 /**
745   * @brief  Return the FLASH Read Protection level.
746   * @retval FLASH ReadOut Protection Status:
747   *         This return value can be one of the following values:
748   *            @arg @ref OB_RDP_LEVEL_0 No protection
749   *            @arg @ref OB_RDP_LEVEL_1 Read protection of the memory
750   *            @arg @ref OB_RDP_LEVEL_2 Full chip protection
751   */
FLASH_OB_GetRDP(void)752 static uint32_t FLASH_OB_GetRDP(void)
753 {
754   uint32_t rdplvl = READ_BIT(FLASH->OPTR, FLASH_OPTR_RDP);
755 
756   if ((rdplvl != OB_RDP_LEVEL_0) && (rdplvl != OB_RDP_LEVEL_2))
757   {
758     return (OB_RDP_LEVEL_1);
759   }
760   else
761   {
762     return rdplvl;
763   }
764 }
765 
766 /**
767   * @brief  Return the FLASH User Option Byte value.
768   * @retval The FLASH User Option Bytes values. It will be a combination of all the following values:
769   *         @arg @ref FLASH_OB_USER_BOR_ENABLE,
770   *         @ref FLASH_OB_USER_BOR_LEVEL,
771   *         @ref FLASH_OB_USER_nRST_STOP,
772   *         @ref FLASH_OB_USER_nRST_STANDBY,
773   *         @ref FLASH_OB_USER_nRST_SHUTDOWN,
774   *         @ref FLASH_OB_USER_IWDG_SW,
775   *         @ref FLASH_OB_USER_IWDG_STOP,
776   *         @ref FLASH_OB_USER_IWDG_STANDBY,
777   *         @ref FLASH_OB_USER_WWDG_SW,
778   *         @ref FLASH_OB_USER_SRAM_PARITY,
779   *         @ref FLASH_OB_USER_nBOOT_SEL,
780   *         @ref FLASH_OB_USER_nBOOT1,
781   *         @ref FLASH_OB_USER_nBOOT0,
782   *         @ref FLASH_OB_USER_INPUT_RESET_HOLDER
783   */
FLASH_OB_GetUser(void)784 static uint32_t FLASH_OB_GetUser(void)
785 {
786   uint32_t user = ((FLASH->OPTR & ~FLASH_OPTR_RDP) & OB_USER_ALL);
787   return user;
788 }
789 
790 /**
791   * @brief  Return the FLASH PCROP Protection Option Bytes value.
792   * @param  PCROPConfig [out]  specifies the configuration of PCROP_RDP option.
793   * @param  PCROP1AStartAddr [out]  Specifies the address where to copied the start address
794   *         of the 1A Proprietary code readout protection
795   * @param  PCROP1AEndAddr [out]  Specifies the address where to copied the end address of
796   *         the 1A Proprietary code readout protection
797   * @retval None
798   */
FLASH_OB_GetPCROP1A(uint32_t * PCROPConfig,uint32_t * PCROP1AStartAddr,uint32_t * PCROP1AEndAddr)799 static void FLASH_OB_GetPCROP1A(uint32_t *PCROPConfig, uint32_t *PCROP1AStartAddr, uint32_t *PCROP1AEndAddr)
800 {
801   uint32_t pcrop;
802 
803   pcrop = (FLASH->PCROP1ASR & FLASH_PCROP1ASR_PCROP1A_STRT);
804   *PCROP1AStartAddr = (pcrop << FLASH_PCROP_GRANULARITY_OFFSET);
805   *PCROP1AStartAddr += FLASH_BASE;
806 
807   pcrop = FLASH->PCROP1AER;
808   *PCROP1AEndAddr = ((pcrop & FLASH_PCROP1AER_PCROP1A_END) << FLASH_PCROP_GRANULARITY_OFFSET);
809   *PCROP1AEndAddr += (FLASH_BASE + FLASH_PCROP_GRANULARITY - 1U);
810 
811   *PCROPConfig &= ~OB_PCROP_RDP_ERASE;
812   *PCROPConfig |= (pcrop & FLASH_PCROP1AER_PCROP_RDP);
813 }
814 
815 
816 /**
817   * @brief  Return the FLASH PCROP Protection Option Bytes value.
818   * @param  PCROP1BStartAddr [out]  Specifies the address where to copied the start address
819   *         of the 1B Proprietary code readout protection
820   * @param  PCROP1BEndAddr [out]  Specifies the address where to copied the end address of
821   *         the 1B Proprietary code readout protection
822   * @retval None
823   */
FLASH_OB_GetPCROP1B(uint32_t * PCROP1BStartAddr,uint32_t * PCROP1BEndAddr)824 static void FLASH_OB_GetPCROP1B(uint32_t *PCROP1BStartAddr, uint32_t *PCROP1BEndAddr)
825 {
826   uint32_t pcrop;
827 
828   pcrop = (FLASH->PCROP1BSR & FLASH_PCROP1BSR_PCROP1B_STRT);
829   *PCROP1BStartAddr = (pcrop << FLASH_PCROP_GRANULARITY_OFFSET);
830   *PCROP1BStartAddr += FLASH_BASE;
831 
832   pcrop = (FLASH->PCROP1BER & FLASH_PCROP1BER_PCROP1B_END);
833   *PCROP1BEndAddr = (pcrop << FLASH_PCROP_GRANULARITY_OFFSET);
834   *PCROP1BEndAddr += (FLASH_BASE + FLASH_PCROP_GRANULARITY - 1U);
835 }
836 
837 /**
838   * @brief  Return the FLASH Securable memory area protection Option Bytes value.
839   * @param  BootEntry  specifies boot scheme configuration
840   * @param  SecSize specifies number of pages to protect as secure memory area, starting from
841   *         beginning of the Flash (page 0).
842   * @retval None
843   */
FLASH_OB_GetSecMem(uint32_t * BootEntry,uint32_t * SecSize)844 static void FLASH_OB_GetSecMem(uint32_t *BootEntry, uint32_t *SecSize)
845 {
846   uint32_t secmem = FLASH->SECR;
847 
848   *BootEntry = (secmem & FLASH_SECR_BOOT_LOCK);
849   *SecSize = (secmem & FLASH_SECR_SEC_SIZE);
850 }
851 
852 /**
853   * @}
854   */
855 
856 /**
857   * @}
858   */
859 
860 #endif /* HAL_FLASH_MODULE_ENABLED */
861 
862 /**
863   * @}
864   */
865 
866 /**
867   * @}
868   */
869