1 /**
2 ******************************************************************************
3 * @file stm32wb0x_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 * @attention
11 *
12 * Copyright (c) 2024 STMicroelectronics.
13 * All rights reserved.
14 *
15 * This software is licensed under terms that can be found in the LICENSE file
16 * in the root directory of this software component.
17 * If no LICENSE file comes with this software, it is provided AS-IS.
18 *
19 ******************************************************************************
20 ******************************************************************************
21 @verbatim
22 ==============================================================================
23 ##### Flash Extended features #####
24 ==============================================================================
25
26 [..] The FLASH interface contains the following additional features
27
28 (+) Single bank memory organization
29 (+) Readout protection
30 (+) WRERP protection
31
32
33 ##### How to use this driver #####
34 ==============================================================================
35 [..] This driver provides functions to configure and program the FLASH memory.
36 It includes
37 (#) Flash Memory Erase functions:
38 (++) Erase function: Erase page, erase all sectors
39 (++) There are two modes of erase :
40 (+++) Polling Mode using HAL_FLASHEx_Erase()
41 (+++) Interrupt Mode using HAL_FLASHEx_Erase_IT()
42 (#) OTP Memory Programming functions:
43 (++) There are two modes of OTP program :
44 (+++) Polling Mode using HAL_FLASHEx_OTPWRite()
45 (+++) Interrupt Mode using HAL_FLASHEx_OTPWrite_IT()
46
47
48 @endverbatim
49 ******************************************************************************
50 */
51
52 /* Includes ------------------------------------------------------------------*/
53 #include "stm32wb0x_hal.h"
54
55 /** @addtogroup STM32WB0x_HAL_Driver
56 * @{
57 */
58
59 /** @defgroup FLASHEx FLASHEx
60 * @brief FLASH Extended HAL module driver
61 * @{
62 */
63
64 #ifdef HAL_FLASH_MODULE_ENABLED
65
66 /* Private typedef -----------------------------------------------------------*/
67 /* Private define ------------------------------------------------------------*/
68 /* Private macro -------------------------------------------------------------*/
69 /* Private function prototypes -----------------------------------------------*/
70 /** @defgroup FLASHEx_Private_Functions FLASHEx Private Functions
71 * @{
72 */
73
74 static void FLASH_MassErase(void);
75 static void FLASH_MassRead(void);
76 static void FLASH_Program_OTPWord(uint32_t Address, uint32_t Data);
77 static void FLASH_KeyWrite(void);
78 /**
79 * @}
80 */
81
82 /* Exported functions -------------------------------------------------------*/
83 /** @defgroup FLASHEx_Exported_Functions FLASH Extended Exported Functions
84 * @{
85 */
86
87 /** @defgroup FLASHEx_Exported_Functions_Group1 Extended IO operation functions
88 * @brief Extended IO operation functions
89 *
90 @verbatim
91 ===============================================================================
92 ##### Extended programming operation functions #####
93 ===============================================================================
94 [..]
95 This subsection provides a set of functions allowing to manage the Extended FLASH
96 programming operations Operations.
97
98 @endverbatim
99 * @{
100 */
101 /**
102 * @brief Perform a mass erase or erase the specified FLASH memory pages.
103 * @param[in] pEraseInit Pointer to an @ref FLASH_EraseInitTypeDef structure that
104 * contains the configuration information for the erasing.
105 * @param[out] PageError Pointer to variable that contains the configuration
106 * information on faulty page in case of error (0xFFFFFFFF means that all
107 * the pages have been correctly erased)
108 * @retval HAL Status
109 */
HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef * pEraseInit,uint32_t * PageError)110 HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *PageError)
111 {
112 HAL_StatusTypeDef status;
113 uint32_t index;
114
115 /* Check the parameters */
116 assert_param(IS_FLASH_TYPE_ERASE(pEraseInit->TypeErase));
117
118 /* Process Locked */
119 __HAL_LOCK(&pFlash);
120
121 /* Reset error code */
122 pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
123
124 /* Verify that next operation can be proceed */
125 if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE)
126 {
127 /* Mass erase to be done */
128 FLASH_MassErase();
129
130 /* Wait for last operation to be completed */
131 status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
132 }
133 else
134 {
135 /*Initialization of PageError variable*/
136 *PageError = 0xFFFFFFFFU;
137
138 for (index = pEraseInit->Page; index < (pEraseInit->Page + pEraseInit->NbPages); index++)
139 {
140 /* Start erase page */
141 FLASH_PageErase(index);
142
143 /* Wait for last operation to be completed */
144 status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
145
146 if (status != HAL_OK)
147 {
148 /* In case of error, stop erase procedure and return the faulty address */
149 *PageError = index;
150 break;
151 }
152 }
153 }
154
155 /* Process Unlocked */
156 __HAL_UNLOCK(&pFlash);
157
158 return status;
159 }
160
161
162 /**
163 * @brief Perform a mass erase or erase the specified FLASH memory pages with interrupt enabled.
164 * @param pEraseInit Pointer to an @ref FLASH_EraseInitTypeDef structure that
165 * contains the configuration information for the erasing.
166 * @retval HAL Status
167 */
HAL_FLASHEx_Erase_IT(FLASH_EraseInitTypeDef * pEraseInit)168 HAL_StatusTypeDef HAL_FLASHEx_Erase_IT(FLASH_EraseInitTypeDef *pEraseInit)
169 {
170 HAL_StatusTypeDef status;
171 /* Check the parameters */
172 assert_param(IS_FLASH_TYPE_ERASE(pEraseInit->TypeErase));
173
174 /* Process Locked */
175 __HAL_LOCK(&pFlash);
176
177 /* Reset error code */
178 pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
179
180 /* save procedure for interrupt treatment */
181 pFlash.ProcedureOnGoing = pEraseInit->TypeErase;
182
183 /* Verify that next operation can be proceed */
184 status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
185
186 if (status != HAL_OK)
187 {
188 /* Process Unlocked */
189 __HAL_UNLOCK(&pFlash);
190 }
191 else
192 {
193 /* Enable End of Operation and Error interrupts */
194 __HAL_FLASH_ENABLE_IT(FLASH_IT_CMDDONE | FLASH_IT_CMDERR | FLASH_IT_ILLCMD);
195
196 if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE)
197 {
198 /* Set Page to 0 for Interrupt callback management */
199 pFlash.Page = 0;
200
201 /* Proceed to Mass Erase */
202 FLASH_MassErase();
203 }
204 else
205 {
206 /* Erase by page to be done */
207 pFlash.NbPagesToErase = pEraseInit->NbPages;
208 pFlash.Page = pEraseInit->Page;
209
210 /*Erase 1st page and wait for IT */
211 FLASH_PageErase(pEraseInit->Page);
212 }
213 }
214
215 /* return status */
216 return HAL_OK;
217 }
218
219 /**
220 * @brief Program a word at a specified OTP address.
221 * @param Address Specifies the address to be programmed.
222 * @param Data Specifies the data to be programmed.
223 *
224 * @retval HAL_StatusTypeDef HAL Status
225 */
HAL_FLASHEx_OTPWrite(uint32_t Address,uint32_t Data)226 HAL_StatusTypeDef HAL_FLASHEx_OTPWrite(uint32_t Address, uint32_t Data)
227 {
228 HAL_StatusTypeDef status;
229
230 /* Check the parameters */
231 assert_param(IS_ADDR_ALIGNED_32BITS(Address));
232 assert_param(IS_FLASH_PROGRAM_OTP_ADDRESS(Address));
233
234 /* Process Locked */
235 __HAL_LOCK(&pFlash);
236
237 /* Reset error code */
238 pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
239
240 /* Program a word (32-bit) at a specified OTP address */
241 FLASH_Program_OTPWord(Address, Data);
242
243 /* Wait for last operation to be completed */
244 status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
245
246 /* Process Unlocked */
247 __HAL_UNLOCK(&pFlash);
248
249 /* return status */
250 return status;
251 }
252
253 /**
254 * @brief Program a word at a specified OTP address with interrupt enabled.
255 * @param Address Specifies the address to be programmed.
256 * @param Data Specifies the data to be programmed.
257 *
258 * @retval HAL Status
259 */
HAL_FLASHEx_OTPWrite_IT(uint32_t Address,uint32_t Data)260 HAL_StatusTypeDef HAL_FLASHEx_OTPWrite_IT(uint32_t Address, uint32_t Data)
261 {
262 /* Check the parameters */
263 assert_param(IS_ADDR_ALIGNED_32BITS(Address));
264 assert_param(IS_FLASH_PROGRAM_OTP_ADDRESS(Address));
265
266 /* Process Locked */
267 __HAL_LOCK(&pFlash);
268
269 /* Reset error code */
270 pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
271
272 /* Set internal variables used by the IRQ handler */
273 pFlash.ProcedureOnGoing = FLASH_CMD_OTPWRITE;
274 pFlash.Address = Address;
275
276 /* Clear All IT pending flag */
277 __HAL_FLASH_CLEAR_IT(FLASH_IT_CMDDONE | FLASH_IT_CMDSTART | FLASH_IT_CMDERR | FLASH_IT_ILLCMD);
278
279 /* Enable End of Operation and Error interrupts */
280 __HAL_FLASH_ENABLE_IT(FLASH_IT_CMDDONE | FLASH_IT_CMDERR | FLASH_IT_ILLCMD);
281
282 /* Program a word (32-bit) at a specified address */
283 FLASH_Program_OTPWord(Address, Data);
284
285 /* return status */
286 return HAL_OK;
287 }
288
289 /**
290 * @brief Page Protection function. It allows protecting from write and page erase
291 * by group of 8 pages.
292 * @param pageProtectionStruct Pointer to a @ref FLASH_PageProtectionTypeDef enumeration. Bitfield with
293 * the write/page erase protection for group of 8 pages (group 0: Flash pages 0 to 7, group 1: Flash
294 * pages 8 to 15... i.e. if pageProt=0x0C the function will protect pages from 16 to 31).
295 * @retval HAL Status
296 */
HAL_FLASHEx_PageProtection(FLASH_PageProtectionTypeDef * pageProtectionStruct)297 HAL_StatusTypeDef HAL_FLASHEx_PageProtection(FLASH_PageProtectionTypeDef *pageProtectionStruct)
298 {
299 /* Check Null pointer */
300 if (pageProtectionStruct == NULL)
301 {
302 return HAL_ERROR;
303 }
304
305 /* Check the parameters */
306 assert_param(IS_FUNCTIONAL_STATE(pageProtectionStruct->state));
307
308 /* Process Locked */
309 __HAL_LOCK(&pFlash);
310
311 #if defined( STM32WB06) || defined( STM32WB07)
312 uint32_t dev_cut_version;
313 dev_cut_version = (LL_SYSCFG_GetDeviceVersion() << 4) | LL_SYSCFG_GetDeviceRevision();
314
315 if (dev_cut_version == LL_BLUENRG_LP_CUT_10)
316 {
317 pageProtectionStruct->pageProt_1 = 0;
318 }
319 #endif /* STM32WB06 || STM32WB07*/
320
321 if (pageProtectionStruct->state == ENABLE)
322 {
323 FLASH->PAGEPROT0 |= pageProtectionStruct->pageProt_0;
324 if (pageProtectionStruct->pageProt_1 != 0)
325 {
326 FLASH->PAGEPROT1 |= pageProtectionStruct->pageProt_1;
327 }
328
329 }
330 else
331 {
332 FLASH->PAGEPROT0 &= ~pageProtectionStruct->pageProt_0;
333 if (pageProtectionStruct->pageProt_1 != 0)
334 {
335 FLASH->PAGEPROT1 &= ~pageProtectionStruct->pageProt_1;
336 }
337
338 }
339
340 /* Process Unlocked */
341 __HAL_UNLOCK(&pFlash);
342
343 /* return status */
344 return HAL_OK;
345
346 }
347
348 /**
349 * @brief Set Protection level configuration
350 * @param ProtectionLevel Level of protection
351 * This parameter can be a combination of all the following values:
352 * @arg @ref PROT_LEVEL_NONE
353 * @arg @ref PROT_LEVEL_1
354 * @arg @ref PROT_LEVEL_2
355 * @arg @ref PROT_LEVEL_3
356 * @retval None
357 */
HAL_FLASHEx_Protection_Config(uint32_t ProtectionLevel)358 HAL_StatusTypeDef HAL_FLASHEx_Protection_Config(uint32_t ProtectionLevel)
359 {
360 HAL_StatusTypeDef status;
361
362 /* Check the parameters */
363 assert_param(IS_PROTECTION_LEVEL(ProtectionLevel));
364
365 /* Process Locked */
366 __HAL_LOCK(&pFlash);
367
368 FLASH->DATA2 = FLASH_DATAKEY2;
369 FLASH->DATA3 = FLASH_DATAKEY3;
370
371 if (ProtectionLevel == PROT_LEVEL_1)
372 {
373 FLASH->DATA0 = FLASH_KEY1;
374 FLASH->DATA1 = FLASH_KEY1;
375 }
376 else if (ProtectionLevel == PROT_LEVEL_2)
377 {
378 FLASH->DATA0 = FLASH_KEY2;
379 FLASH->DATA1 = FLASH_KEY2;
380 }
381 /* Configure KEYWRITE command */
382 FLASH_KeyWrite();
383 /* Wait for last operation to be completed */
384 status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
385
386 /* Process Unlocked */
387 __HAL_UNLOCK(&pFlash);
388
389 /* return status */
390 return status;
391 }
392
393
394 /**
395 * @brief Return the FLASH Protection level.
396 * @retval FLASH Protection Level:
397 * This return value can be one of the following values:
398 * @arg @ref PROT_LEVEL_NONE
399 * @arg @ref PROT_LEVEL_1
400 * @arg @ref PROT_LEVEL_2
401 * @arg @ref PROT_LEVEL_3
402 */
HAL_FLASHEx_GetProtection_Level(void)403 uint32_t HAL_FLASHEx_GetProtection_Level(void)
404 {
405 uint32_t Prot_Key1 = READ_REG(FLASH->DATA0);
406 uint32_t Prot_Key2 = READ_REG(FLASH->DATA1);
407
408 if ((Prot_Key1 == FLASH_KEY1) && (Prot_Key2 == FLASH_KEY1))
409 {
410 return (PROT_LEVEL_1);
411 }
412 else if ((Prot_Key1 == FLASH_KEY2) && (Prot_Key2 == FLASH_KEY2))
413 {
414 return (PROT_LEVEL_2);
415 }
416 else if ((Prot_Key1 == FLASH_KEY0) && (Prot_Key2 == FLASH_KEY0))
417 {
418 return (PROT_LEVEL_NONE);
419 }
420 else
421 {
422 return (PROT_LEVEL_3);
423 }
424 }
425
426 /**
427 * @brief Perform a mass read.
428 * @param pattern Specifies the expected value.
429 * @retval HAL_StatusTypeDef HAL Status
430 */
HAL_FLASHEx_MassRead(uint32_t pattern)431 HAL_StatusTypeDef HAL_FLASHEx_MassRead(uint32_t pattern)
432 {
433 /* Process Locked */
434 __HAL_LOCK(&pFlash);
435
436 /* Reset error code */
437 pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
438
439 /* Program a mass read */
440 FLASH_MassRead();
441
442 /* Check FLASH End of Operation flag */
443 if ((FLASH->IRQSTAT & FLASH_FLAG_CMDDONE) == 0U)
444 {
445 /* Clear FLASH End of Operation pending bit */
446 FLASH->IRQRAW = FLASH_FLAG_CMDDONE;
447 }
448
449 /* verify Flash content */
450 if (FLASH->DATA0 != pattern)
451 {
452 return HAL_ERROR;
453 }
454
455 /* Process Unlocked */
456 __HAL_UNLOCK(&pFlash);
457
458 return HAL_OK;
459 }
460
461 /**
462 * @brief Perform a LFSR signature issued by a MASSREAD command
463 * @retval HAL Status
464 */
HAL_FLASHEx_LFSRSignature(uint32_t * LFSR_Result)465 HAL_StatusTypeDef HAL_FLASHEx_LFSRSignature(uint32_t *LFSR_Result)
466 {
467 HAL_StatusTypeDef status;
468
469 /* Wait for last operation to be completed */
470 status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
471
472 if (status == HAL_OK)
473 {
474 /* Process Locked */
475 __HAL_LOCK(&pFlash);
476
477 /* Reset error code */
478 pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
479
480 /* Program a mass read */
481 FLASH_MassRead();
482
483 /* Check FLASH End of Operation flag */
484 if ((FLASH->IRQSTAT & FLASH_FLAG_CMDDONE) == 0U)
485 {
486 /* Clear FLASH End of Operation pending bit */
487 FLASH->IRQRAW = FLASH_FLAG_CMDDONE;
488 }
489 /* Return LFSRVAL result */
490 (*LFSR_Result) = FLASH->LFSRVAL;
491
492 /* Process Unlocked */
493 __HAL_UNLOCK(&pFlash);
494 }
495
496 return status;
497 }
498
499 /**
500 * @}
501 */
502
503 /**
504 * @}
505 */
506
507 /* Private functions ---------------------------------------------------------*/
508 /** @addtogroup FLASHEx_Private_Functions
509 * @{
510 */
511
512 /**
513 * @brief Mass erase of FLASH memory.
514 * @retval None
515 */
FLASH_MassErase(void)516 static void FLASH_MassErase(void)
517 {
518 /* Clear All Flags */
519 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_CMDDONE | FLASH_FLAG_CMDSTART | FLASH_FLAG_CMDERR | FLASH_FLAG_ILLCMD);
520
521 /* MASSERASE command */
522 FLASH->COMMAND = FLASH_CMD_MASSERASE;
523 }
524
525 /**
526 * @brief Erase the specified FLASH memory page.
527 * @param Page FLASH page to erase
528 * This parameter must be a value between 0 and (max number of pages in Flash - 1)
529 * @retval None
530 */
FLASH_PageErase(uint32_t Page)531 void FLASH_PageErase(uint32_t Page)
532 {
533 /* Check the parameters */
534 assert_param(IS_FLASH_PAGE(Page));
535
536 /* Clear All Flags */
537 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_CMDDONE | FLASH_FLAG_CMDSTART | FLASH_FLAG_CMDERR | FLASH_FLAG_ILLCMD);
538
539 FLASH->ADDRESS = (((Page * FLASH_PAGE_SIZE) >> 2) & FLASH_SIZE_MASK);
540
541 /* Write the ERASE command */
542 FLASH->COMMAND = FLASH_CMD_ERASE_PAGES;
543 }
544
545 /**
546 * @brief Mass read of FLASH memory.
547 * @retval None
548 */
FLASH_MassRead(void)549 static void FLASH_MassRead(void)
550 {
551 /* Clear All Flags */
552 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_CMDDONE | FLASH_FLAG_CMDSTART | FLASH_FLAG_CMDERR | FLASH_FLAG_ILLCMD);
553
554 /* MASSERASE command */
555 FLASH->COMMAND = FLASH_CMD_MASSREAD;
556 }
557
558 /**
559 * @brief Program a word (32-bit) at a specified OTP address.
560 * @param Address Specifies the address to be programmed.
561 * @param Data Specifies the data to be programmed.
562 * @retval None
563 */
FLASH_Program_OTPWord(uint32_t Address,uint32_t Data)564 static void FLASH_Program_OTPWord(uint32_t Address, uint32_t Data)
565 {
566 uint32_t otp_address;
567 uint32_t addr_offset;
568
569 /* Clear All Flags */
570 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_CMDDONE | FLASH_FLAG_CMDSTART | FLASH_FLAG_CMDERR | FLASH_FLAG_ILLCMD);
571
572 addr_offset = Address - OTP_AREA_BASE;
573 otp_address = (((addr_offset & 0x300) >> 2) | ((addr_offset & 0xFF) >> 2));
574 /* Load the word address */
575 FLASH->ADDRESS = otp_address;
576
577 /* Load the data to program */
578 FLASH->DATA0 = Data;
579
580 /* Load the OTP WRITE command */
581 FLASH->COMMAND = FLASH_CMD_OTPWRITE;
582 }
583
584 /**
585 * @brief Write the customer key used to protect the main Flash
586 * @retval None
587 */
FLASH_KeyWrite(void)588 static void FLASH_KeyWrite(void)
589 {
590 /* Clear All Flags */
591 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_CMDDONE | FLASH_FLAG_CMDSTART | FLASH_FLAG_CMDERR | FLASH_FLAG_ILLCMD);
592 /* MASSREAD command */
593 FLASH->COMMAND = FLASH_CMD_KEYWRITE;
594 }
595
596 /**
597 * @}
598 */
599
600 /**
601 * @}
602 */
603
604 #endif /* HAL_FLASH_MODULE_ENABLED */
605
606 /**
607 * @}
608 */
609
610 /**
611 * @}
612 */
613