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