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(const FLASH_EraseInitTypeDef * pEraseInit,uint32_t * PageError)139 HAL_StatusTypeDef HAL_FLASHEx_Erase(const 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 OB_USER_BOR_ENABLE,
570 * @arg @ref OB_USER_BOR_LEVEL,
571 * @arg @ref OB_USER_nRST_STOP,
572 * @arg @ref OB_USER_nRST_STANDBY,
573 * @arg @ref OB_USER_nRST_SHUTDOWN,
574 * @arg @ref OB_USER_IWDG_SW,
575 * @arg @ref OB_USER_IWDG_STOP,
576 * @arg @ref OB_USER_IWDG_STANDBY,
577 * @arg @ref OB_USER_WWDG_SW,
578 * @arg @ref OB_USER_SRAM_PARITY,
579 * @arg @ref OB_USER_nBOOT_SEL,
580 * @arg @ref OB_USER_nBOOT1,
581 * @arg @ref OB_USER_nBOOT0,
582 * @arg @ref OB_USER_INPUT_RESET_HOLDER
583 * @arg @ref OB_USER_SECURE_MUXING_EN
584 * @arg @ref OB_USER_HSE_NOT_REMAPPED (*)
585 * @param RDPLevel specifies the read protection level.
586 * This parameter can be one of the following values:
587 * @arg @ref OB_RDP_LEVEL_0 No protection
588 * @arg @ref OB_RDP_LEVEL_1 Memory Read protection
589 * @arg @ref OB_RDP_LEVEL_2 Full chip protection
590 * @retval None
591 *
592 * @note (*) available only on STM32C071xx devices.
593 */
FLASH_OB_OptrConfig(uint32_t UserType,uint32_t UserConfig,uint32_t RDPLevel)594 static void FLASH_OB_OptrConfig(uint32_t UserType, uint32_t UserConfig, uint32_t RDPLevel)
595 {
596 uint32_t optr;
597
598 /* Check the parameters */
599 assert_param(IS_OB_USER_TYPE(UserType));
600 assert_param(IS_OB_USER_CONFIG(UserType, UserConfig));
601 assert_param(IS_OB_RDP_LEVEL(RDPLevel));
602
603 /* Configure the RDP level in the option bytes register */
604 optr = FLASH->OPTR;
605 optr &= ~(UserType | FLASH_OPTR_RDP);
606 FLASH->OPTR = (optr | UserConfig | RDPLevel);
607 }
608
609 /**
610 * @brief Configure the 1A Proprietary code readout protection & erase configuration on RDP regression.
611 * @note It is recommended to align PCROP zone with page granularity when using PCROP_RDP or avoid
612 * having some executable code in a page where PCROP zone starts or ends.
613 * @note Minimum PCROP area size is 2 times the chosen granularity: PCROPA_STRT and PCROPA_END.
614 * So if the requirement is to be able to read-protect 1KB areas, the ROP granularity
615 * has to be set to 512 Bytes
616 * @param PCROPConfig specifies the erase configuration (OB_PCROP_RDP_NOT_ERASE or OB_PCROP_RDP_ERASE)
617 * on RDP level 1 regression.
618 * @param PCROP1AStartAddr Specifies the Zone 1A Start address of the Proprietary code readout protection
619 * This parameter can be an address between begin and end of the flash
620 * @param PCROP1AEndAddr Specifies the Zone 1A end address of the Proprietary code readout protection
621 * This parameter can be an address between PCROP1AStartAddr and end of the flash
622 * @retval None
623 */
FLASH_OB_PCROP1AConfig(uint32_t PCROPConfig,uint32_t PCROP1AStartAddr,uint32_t PCROP1AEndAddr)624 static void FLASH_OB_PCROP1AConfig(uint32_t PCROPConfig, uint32_t PCROP1AStartAddr, uint32_t PCROP1AEndAddr)
625 {
626 uint32_t startoffset;
627 uint32_t endoffset;
628 uint32_t pcrop1aend;
629
630 /* Check the parameters */
631 assert_param(IS_OB_PCROP_CONFIG(PCROPConfig));
632 assert_param(IS_FLASH_MAIN_MEM_ADDRESS(PCROP1AStartAddr));
633 assert_param(IS_FLASH_MAIN_MEM_ADDRESS(PCROP1AEndAddr));
634
635 /* get pcrop 1A end register */
636 pcrop1aend = FLASH->PCROP1AER;
637
638 /* Configure the Proprietary code readout protection offset */
639 if ((PCROPConfig & OB_PCROP_ZONE_A) != 0x00U)
640 {
641 /* Compute offset depending on pcrop granularity */
642 startoffset = ((PCROP1AStartAddr - FLASH_BASE) >> FLASH_PCROP_GRANULARITY_OFFSET);
643 endoffset = ((PCROP1AEndAddr - FLASH_BASE) >> FLASH_PCROP_GRANULARITY_OFFSET);
644
645 /* Set Zone A start offset */
646 FLASH->PCROP1ASR = startoffset;
647
648 /* Set Zone A end offset */
649 pcrop1aend &= ~FLASH_PCROP1AER_PCROP1A_END;
650 pcrop1aend |= endoffset;
651 }
652
653 /* Set RDP erase protection if needed. This bit is only set & will be reset by mass erase */
654 if ((PCROPConfig & OB_PCROP_RDP_ERASE) != 0x00U)
655 {
656 pcrop1aend |= FLASH_PCROP1AER_PCROP_RDP;
657 }
658
659 /* set 1A End register */
660 FLASH->PCROP1AER = pcrop1aend;
661 }
662
663 /**
664 * @brief Configure the 1B Proprietary code readout protection.
665 * @note It is recommended to align PCROP zone with page granularity when using PCROP_RDP or avoid
666 * having some executable code in a page where PCROP zone starts or ends.
667 * @note Minimum PCROP area size is 2 times the chosen granularity: PCROPA_STRT and PCROPA_END.
668 * So if the requirement is to be able to read-protect 1KB areas, the ROP granularity
669 * has to be set to 512 Bytes
670 * @param PCROP1BStartAddr Specifies the Zone 1B Start address of the Proprietary code readout protection
671 * This parameter can be an address between begin and end of the flash
672 * @param PCROP1BEndAddr Specifies the Zone 1B end address of the Proprietary code readout protection
673 * This parameter can be an address between PCROP1BStartAddr and end of the flash
674 * @retval None
675 */
FLASH_OB_PCROP1BConfig(uint32_t PCROP1BStartAddr,uint32_t PCROP1BEndAddr)676 static void FLASH_OB_PCROP1BConfig(uint32_t PCROP1BStartAddr, uint32_t PCROP1BEndAddr)
677 {
678 uint32_t startoffset;
679 uint32_t endoffset;
680
681 /* Check the parameters */
682 assert_param(IS_FLASH_MAIN_MEM_ADDRESS(PCROP1BStartAddr));
683 assert_param(IS_FLASH_MAIN_MEM_ADDRESS(PCROP1BEndAddr));
684
685 /* Configure the Proprietary code readout protection offset */
686 startoffset = ((PCROP1BStartAddr - FLASH_BASE) >> FLASH_PCROP_GRANULARITY_OFFSET);
687 endoffset = ((PCROP1BEndAddr - FLASH_BASE) >> FLASH_PCROP_GRANULARITY_OFFSET);
688
689 /* Set Zone B start offset */
690 FLASH->PCROP1BSR = startoffset;
691 /* Set Zone B end offset */
692 FLASH->PCROP1BER = endoffset;
693 }
694
695 /**
696 * @brief Configure Securable Memory area feature.
697 * @param BootEntry specifies if boot scheme is forced to Flash (System or user) or not
698 * This parameter can be one of the following values:
699 * @arg @ref OB_BOOT_ENTRY_FORCED_NONE No boot entry forced
700 * @arg @ref OB_BOOT_ENTRY_FORCED_FLASH FLash selected as unique entry boot
701 * @param SecSize specifies number of pages to protect as securable memory area, starting from
702 * beginning of the Flash (page 0).
703 * @retval None
704 */
FLASH_OB_SecMemConfig(uint32_t BootEntry,uint32_t SecSize)705 static void FLASH_OB_SecMemConfig(uint32_t BootEntry, uint32_t SecSize)
706 {
707 uint32_t secmem;
708
709 /* Check the parameters */
710 assert_param(IS_OB_SEC_BOOT_LOCK(BootEntry));
711 assert_param(IS_OB_SEC_SIZE(SecSize));
712
713 /* Set securable memory area configuration */
714 secmem = (FLASH->SECR & ~(FLASH_SECR_BOOT_LOCK | FLASH_SECR_SEC_SIZE));
715 FLASH->SECR = (secmem | BootEntry | SecSize);
716 }
717
718 /**
719 * @brief Return the FLASH Write Protection Option Bytes value.
720 * @param[in] WRPArea Specifies the area to be returned.
721 * This parameter can be one of the following values:
722 * @arg @ref OB_WRPAREA_ZONE_A Flash Zone A
723 * @arg @ref OB_WRPAREA_ZONE_B Flash Zone B
724 * @param[out] WRPStartOffset Specifies the address where to copied the start page
725 * of the write protected area
726 * @param[out] WRDPEndOffset Dpecifies the address where to copied the end page of
727 * the write protected area
728 * @retval None
729 */
FLASH_OB_GetWRP(uint32_t WRPArea,uint32_t * WRPStartOffset,uint32_t * WRDPEndOffset)730 static void FLASH_OB_GetWRP(uint32_t WRPArea, uint32_t *WRPStartOffset, uint32_t *WRDPEndOffset)
731 {
732 /* Check the parameters */
733 assert_param(IS_OB_WRPAREA(WRPArea));
734
735 /* Get the configuration of the write protected area */
736 if (WRPArea == OB_WRPAREA_ZONE_A)
737 {
738 *WRPStartOffset = READ_BIT(FLASH->WRP1AR, FLASH_WRP1AR_WRP1A_STRT);
739 *WRDPEndOffset = (READ_BIT(FLASH->WRP1AR, FLASH_WRP1AR_WRP1A_END) >> FLASH_WRP1AR_WRP1A_END_Pos);
740 }
741 else
742 {
743 *WRPStartOffset = READ_BIT(FLASH->WRP1BR, FLASH_WRP1BR_WRP1B_STRT);
744 *WRDPEndOffset = (READ_BIT(FLASH->WRP1BR, FLASH_WRP1BR_WRP1B_END) >> FLASH_WRP1BR_WRP1B_END_Pos);
745 }
746 }
747
748 /**
749 * @brief Return the FLASH Read Protection level.
750 * @retval FLASH ReadOut Protection Status:
751 * This return value can be one of the following values:
752 * @arg @ref OB_RDP_LEVEL_0 No protection
753 * @arg @ref OB_RDP_LEVEL_1 Read protection of the memory
754 * @arg @ref OB_RDP_LEVEL_2 Full chip protection
755 */
FLASH_OB_GetRDP(void)756 static uint32_t FLASH_OB_GetRDP(void)
757 {
758 uint32_t rdplvl = READ_BIT(FLASH->OPTR, FLASH_OPTR_RDP);
759
760 if ((rdplvl != OB_RDP_LEVEL_0) && (rdplvl != OB_RDP_LEVEL_2))
761 {
762 return (OB_RDP_LEVEL_1);
763 }
764 else
765 {
766 return rdplvl;
767 }
768 }
769
770 /**
771 * @brief Return the FLASH User Option Byte value.
772 * @retval The FLASH User Option Bytes values. It will be a combination of all the following values:
773 * @arg @ref OB_USER_BOR_ENABLE,
774 * @ref OB_USER_BOR_LEVEL,
775 * @ref OB_USER_nRST_STOP,
776 * @ref OB_USER_nRST_STANDBY,
777 * @ref OB_USER_nRST_SHUTDOWN,
778 * @ref OB_USER_IWDG_SW,
779 * @ref OB_USER_IWDG_STOP,
780 * @ref OB_USER_IWDG_STANDBY,
781 * @ref OB_USER_WWDG_SW,
782 * @ref OB_USER_SRAM_PARITY,
783 * @ref OB_USER_nBOOT_SEL,
784 * @ref OB_USER_nBOOT1,
785 * @ref OB_USER_nBOOT0,
786 * @ref OB_USER_INPUT_RESET_HOLDER
787 * @ref OB_USER_SECURE_MUXING_EN
788 * @ref OB_USER_HSE_NOT_REMAPPED (*)
789 *
790 * @note (*) available only on STM32C071xx devices.
791 */
FLASH_OB_GetUser(void)792 static uint32_t FLASH_OB_GetUser(void)
793 {
794 uint32_t user = ((FLASH->OPTR & ~FLASH_OPTR_RDP) & OB_USER_ALL);
795 return user;
796 }
797
798 /**
799 * @brief Return the FLASH PCROP Protection Option Bytes value.
800 * @param PCROPConfig [out] specifies the configuration of PCROP_RDP option.
801 * @param PCROP1AStartAddr [out] Specifies the address where to copied the start address
802 * of the 1A Proprietary code readout protection
803 * @param PCROP1AEndAddr [out] Specifies the address where to copied the end address of
804 * the 1A Proprietary code readout protection
805 * @retval None
806 */
FLASH_OB_GetPCROP1A(uint32_t * PCROPConfig,uint32_t * PCROP1AStartAddr,uint32_t * PCROP1AEndAddr)807 static void FLASH_OB_GetPCROP1A(uint32_t *PCROPConfig, uint32_t *PCROP1AStartAddr, uint32_t *PCROP1AEndAddr)
808 {
809 uint32_t pcrop;
810
811 pcrop = (FLASH->PCROP1ASR & FLASH_PCROP1ASR_PCROP1A_STRT);
812 *PCROP1AStartAddr = (pcrop << FLASH_PCROP_GRANULARITY_OFFSET);
813 *PCROP1AStartAddr += FLASH_BASE;
814
815 pcrop = FLASH->PCROP1AER;
816 *PCROP1AEndAddr = ((pcrop & FLASH_PCROP1AER_PCROP1A_END) << FLASH_PCROP_GRANULARITY_OFFSET);
817 *PCROP1AEndAddr += (FLASH_BASE + FLASH_PCROP_GRANULARITY - 1U);
818
819 *PCROPConfig &= ~OB_PCROP_RDP_ERASE;
820 *PCROPConfig |= (pcrop & FLASH_PCROP1AER_PCROP_RDP);
821 }
822
823
824 /**
825 * @brief Return the FLASH PCROP Protection Option Bytes value.
826 * @param PCROP1BStartAddr [out] Specifies the address where to copied the start address
827 * of the 1B Proprietary code readout protection
828 * @param PCROP1BEndAddr [out] Specifies the address where to copied the end address of
829 * the 1B Proprietary code readout protection
830 * @retval None
831 */
FLASH_OB_GetPCROP1B(uint32_t * PCROP1BStartAddr,uint32_t * PCROP1BEndAddr)832 static void FLASH_OB_GetPCROP1B(uint32_t *PCROP1BStartAddr, uint32_t *PCROP1BEndAddr)
833 {
834 uint32_t pcrop;
835
836 pcrop = (FLASH->PCROP1BSR & FLASH_PCROP1BSR_PCROP1B_STRT);
837 *PCROP1BStartAddr = (pcrop << FLASH_PCROP_GRANULARITY_OFFSET);
838 *PCROP1BStartAddr += FLASH_BASE;
839
840 pcrop = (FLASH->PCROP1BER & FLASH_PCROP1BER_PCROP1B_END);
841 *PCROP1BEndAddr = (pcrop << FLASH_PCROP_GRANULARITY_OFFSET);
842 *PCROP1BEndAddr += (FLASH_BASE + FLASH_PCROP_GRANULARITY - 1U);
843 }
844
845 /**
846 * @brief Return the FLASH Securable memory area protection Option Bytes value.
847 * @param BootEntry specifies boot scheme configuration
848 * @param SecSize specifies number of pages to protect as secure memory area, starting from
849 * beginning of the Flash (page 0).
850 * @retval None
851 */
FLASH_OB_GetSecMem(uint32_t * BootEntry,uint32_t * SecSize)852 static void FLASH_OB_GetSecMem(uint32_t *BootEntry, uint32_t *SecSize)
853 {
854 uint32_t secmem = FLASH->SECR;
855
856 *BootEntry = (secmem & FLASH_SECR_BOOT_LOCK);
857 *SecSize = (secmem & FLASH_SECR_SEC_SIZE);
858 }
859
860 /**
861 * @}
862 */
863
864 /**
865 * @}
866 */
867
868 #endif /* HAL_FLASH_MODULE_ENABLED */
869
870 /**
871 * @}
872 */
873
874 /**
875 * @}
876 */
877