1 /**
2   ******************************************************************************
3   * @file    stm32wb0x_hal_flash.c
4   * @author  MCD Application Team
5   * @brief   FLASH HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          functionalities of the internal FLASH memory:
8   *           + Program operations functions
9   *           + Memory Control functions
10   *           + Peripheral Errors functions
11   ******************************************************************************
12   * @attention
13   *
14   * Copyright (c) 2024 STMicroelectronics.
15   * All rights reserved.
16   *
17   * This software is licensed under terms that can be found in the LICENSE file
18   * in the root directory of this software component.
19   * If no LICENSE file comes with this software, it is provided AS-IS.
20   *
21   ******************************************************************************
22   @verbatim
23   ==============================================================================
24                         ##### FLASH peripheral features #####
25   ==============================================================================
26     [..]
27       The Flash memory interface implements the erase and program Flash memory operations
28       and write/erase protection mechanisms.
29 
30     [..]
31       The FLASH main features are:
32       (+) Flash memory read operations
33       (+) Flash memory program/erase operations
34       (+) Read / write protections
35 
36                         ##### How to use this driver #####
37   ==============================================================================
38     [..]
39       This driver provides functions and macros to configure and program the FLASH
40       memory.
41 
42       (#) Flash Memory IO Programming functions:
43            (++) Program functions: word and burst program
44            (++) There are two modes of programming:
45             (+++) Polling mode using HAL_FLASH_Program() function
46             (+++) Interrupt mode using HAL_FLASH_Program_IT() function
47             (+++) Polling mode using HAL_FLASH_BurstProgram() function
48             (+++) Interrupt mode using HAL_FLASH_BurstProgram_IT() function
49 
50       (#) Interrupts and flags management functions:
51            (++) Handle FLASH interrupts by calling HAL_FLASH_IRQHandler()
52            (++) Callback functions are called when the flash operations are finished :
53                 HAL_FLASH_EndOfOperationCallback() when everything is ok, otherwise
54                 HAL_FLASH_OperationErrorCallback()
55            (++) Get error flag status by calling HAL_GetError()
56 
57     [..]
58       In addition to these functions, this driver includes a set of macros allowing
59       to handle the following operations:
60        (+) Set the wait state latency
61        (+) Enable/Disable the Flash interrupts
62        (+) Monitor the Flash flags status
63 
64   @endverbatim
65   ******************************************************************************
66   */
67 
68 /* Includes ------------------------------------------------------------------*/
69 #include "stm32wb0x_hal.h"
70 
71 /** @addtogroup STM32WB0x_HAL_Driver
72   * @{
73   */
74 
75 /** @defgroup FLASH FLASH
76   * @brief FLASH HAL module driver
77   * @{
78   */
79 
80 #ifdef HAL_FLASH_MODULE_ENABLED
81 
82 /* Private typedef -----------------------------------------------------------*/
83 /* Private defines -----------------------------------------------------------*/
84 /* Private macros ------------------------------------------------------------*/
85 /* Private variables ---------------------------------------------------------*/
86 /** @defgroup FLASH_Private_Variables FLASH Private Variables
87   * @{
88   */
89 /**
90   * @brief  Variable used for Program/Erase sectors under interruption
91   */
92 
93 FLASH_ProcessTypeDef pFlash = {.Lock = HAL_UNLOCKED, \
94                                .ErrorCode = HAL_FLASH_ERROR_NONE, \
95                                .ProcedureOnGoing = 0U, \
96                                .Address = 0U, \
97                                .Page = 0U, \
98                                .NbPagesToErase = 0U
99                               };
100 /**
101   * @}
102   */
103 
104 /* Private function prototypes -----------------------------------------------*/
105 /** @defgroup FLASH_Private_Functions FLASH Private Functions
106   * @{
107   */
108 static void          FLASH_Program_Word(uint32_t Address, uint32_t Data);
109 static void          FLASH_Program_Burst(uint32_t Address, uint32_t DataAddress);
110 /**
111   * @}
112   */
113 
114 /* Exported functions --------------------------------------------------------*/
115 /** @defgroup FLASH_Exported_Functions FLASH Exported Functions
116   * @{
117   */
118 
119 /** @defgroup FLASH_Exported_Functions_Group1 Programming operation functions
120   *  @brief   Programming operation functions
121   *
122 @verbatim
123  ===============================================================================
124                   ##### Programming operation functions #####
125  ===============================================================================
126     [..]
127     This subsection provides a set of functions allowing to manage the FLASH
128     program operations.
129 
130 @endverbatim
131   * @{
132   */
133 
134 /**
135   * @brief  Program a data at a specified address.
136   * @param  TypeProgram Indicate the way to program at a specified address
137   *                This parameter can be a value of @ref FLASH_TYPE_PROGRAM
138   * @param  Address Specifies the address to be programmed.
139   * @param  Data Specifies the data to be programmed
140   *                This parameter is the data for the word program and the address where
141   *                are stored the data for the burst program.
142   *
143   * @retval HAL_StatusTypeDef HAL Status
144   */
HAL_FLASH_Program(uint32_t TypeProgram,uint32_t Address,uint32_t Data)145 HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint32_t Data)
146 {
147   HAL_StatusTypeDef status;
148 
149   /* Check the parameters */
150   assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
151   assert_param(IS_ADDR_ALIGNED_32BITS(Address));
152   assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
153 
154   /* Process Locked */
155   __HAL_LOCK(&pFlash);
156 
157   /* Reset error code */
158   pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
159 
160   /* Verify that next operation can be proceed */
161   status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
162 
163   if (status == HAL_OK)
164   {
165     if (TypeProgram == FLASH_TYPEPROGRAM_WORD)
166     {
167       /* Check the parameters */
168       assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
169 
170       /* Program a word (32-bit) at a specified address */
171       FLASH_Program_Word(Address, Data);
172     }
173     else
174     {
175       /* Check the parameters */
176       assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
177 
178       /* Program 4 word starting from a specified address */
179       FLASH_Program_Burst(Address, Data);
180     }
181 
182     /* Wait for last operation to be completed */
183     status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
184 
185   }
186 
187   /* Process Unlocked */
188   __HAL_UNLOCK(&pFlash);
189 
190   /* return status */
191   return status;
192 }
193 
194 /**
195   * @brief  Program a word or burst program of a row at a specified address with interrupt enabled.
196   * @param  TypeProgram Indicate the way to program at a specified address.
197   *                           This parameter can be a value of @ref FLASH_TYPE_PROGRAM
198   * @param  Address Specifies the address to be programmed.
199   * @param  Data Specifies the data to be programmed
200   *                This parameter is the data for the double word program and the address where
201   *                are stored the data for the row fast program.
202   *
203   * @retval HAL Status
204   */
HAL_FLASH_Program_IT(uint32_t TypeProgram,uint32_t Address,uint32_t Data)205 HAL_StatusTypeDef HAL_FLASH_Program_IT(uint32_t TypeProgram, uint32_t Address, uint32_t Data)
206 {
207   HAL_StatusTypeDef status;
208 
209   /* Check the parameters */
210   assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
211   assert_param(IS_ADDR_ALIGNED_32BITS(Address));
212   assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
213 
214   /* Process Locked */
215   __HAL_LOCK(&pFlash);
216 
217   /* Reset error code */
218   pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
219 
220   /* Verify that next operation can be proceed */
221   status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
222 
223   if (status != HAL_OK)
224   {
225     /* Process Unlocked */
226     __HAL_UNLOCK(&pFlash);
227   }
228   else
229   {
230     /* Set internal variables used by the IRQ handler */
231     pFlash.ProcedureOnGoing = TypeProgram;
232     pFlash.Address = Address;
233 
234     /* Clear All IT pending flag */
235     __HAL_FLASH_CLEAR_IT(FLASH_IT_CMDDONE | FLASH_IT_CMDSTART | FLASH_IT_CMDERR | FLASH_IT_ILLCMD);
236 
237     /* Enable End of Operation and Error interrupts */
238     __HAL_FLASH_ENABLE_IT(FLASH_IT_CMDDONE | FLASH_IT_CMDERR | FLASH_IT_ILLCMD);
239 
240     if (TypeProgram == FLASH_TYPEPROGRAM_WORD)
241     {
242       /* Check the parameters */
243       assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
244 
245       /* Program a word (32-bit) at a specified address */
246       FLASH_Program_Word(Address, Data);
247     }
248     else
249     {
250       /* Check the parameters */
251       assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
252       /* Program 4 word starting from a specified address */
253       FLASH_Program_Burst(Address, Data);
254     }
255   }
256 
257   /* return status */
258   return status;
259 }
260 
261 /**
262   * @brief Handle FLASH interrupt request.
263   * @retval None
264   */
HAL_FLASH_IRQHandler(void)265 void HAL_FLASH_IRQHandler(void)
266 {
267   uint32_t param=0;
268   uint32_t error;
269 
270   /* Save flash errors. */
271   error = FLASH->IRQSTAT & FLASH_FLAG_ALL_ERRORS;
272 
273   /* A] Set parameter for user or error callbacks */
274 
275   /* Check if the operation was a program or erase */
276   if ((pFlash.ProcedureOnGoing & (FLASH_CMD_WRITE | FLASH_CMD_BURSTWRITE | FLASH_CMD_OTPWRITE)) != 0x00U)
277   {
278     /* Return address being programmed */
279     param = pFlash.Address;
280   }
281   else if ((pFlash.ProcedureOnGoing & (FLASH_CMD_MASSERASE | FLASH_CMD_ERASE_PAGES)) != 0x00U)
282   {
283     /* return page number being erased (0 for mass erase) */
284     param = pFlash.Page;
285   }
286   else
287   {
288     /* Nothing to do */
289   }
290 
291   /* B] Check errors */
292   if (error != 0x00U)
293   {
294     /* Save the error code */
295     pFlash.ErrorCode |= error;
296 
297     /* Clear error flags */
298     __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
299 
300     /* Stop the procedure ongoing */
301     pFlash.ProcedureOnGoing = FLASH_TYPENONE;
302 
303     /* Error callback */
304     HAL_FLASH_OperationErrorCallback(param);
305   }
306 
307   /* C] Check FLASH End of Operation flag */
308   if (__HAL_FLASH_GET_IT(FLASH_IT_CMDDONE))
309   {
310 
311     /* Clear FLASH End of Operation IT flag pending bit */
312     __HAL_FLASH_CLEAR_IT(FLASH_IT_CMDDONE);
313 
314     /* Clear FLASH End of Operation pending bit */
315     __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_CMDDONE);
316 
317 
318     if (pFlash.ProcedureOnGoing == FLASH_CMD_ERASE_PAGES)
319     {
320       /* Nb of pages to erased can be decreased */
321       pFlash.NbPagesToErase--;
322 
323       /* Check if there are still pages to erase */
324       if (pFlash.NbPagesToErase != 0x00u)
325       {
326         /* Increment page number */
327         pFlash.Page++;
328         FLASH_PageErase(pFlash.Page);
329       }
330       else
331       {
332         pFlash.Page = 0xFFFFFFFFU;
333         pFlash.ProcedureOnGoing = FLASH_TYPENONE;
334       }
335     }
336     else
337     {
338       /*Stop the ongoing procedure */
339       pFlash.Page = 0xFFFFFFFFU;
340       pFlash.ProcedureOnGoing = FLASH_TYPENONE;
341     }
342 
343     /* User callback */
344     HAL_FLASH_EndOfOperationCallback(param);
345   }
346 
347   if (pFlash.ProcedureOnGoing == FLASH_TYPENONE)
348   {
349     /* Disable End of Operation and Error interrupts */
350     __HAL_FLASH_DISABLE_IT(FLASH_IT_CMDDONE | FLASH_IT_CMDERR | FLASH_IT_ILLCMD);
351 
352     /* Process Unlocked */
353     __HAL_UNLOCK(&pFlash);
354   }
355 }
356 
357 /**
358   * @brief  FLASH end of operation interrupt callback.
359   * @param  ReturnValue The value saved in this parameter depends on the ongoing procedure
360   *                  Mass Erase: 0
361   *                  Page Erase: Page which has been erased
362   *                  Program: Address which was selected for data program
363   * @retval None
364   */
HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue)365 __weak void HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue)
366 {
367   /* Prevent unused argument(s) compilation warning */
368   UNUSED(ReturnValue);
369 
370   /* NOTE : This function should not be modified, when the callback is needed,
371             the HAL_FLASH_EndOfOperationCallback could be implemented in the user file
372    */
373 }
374 
375 /**
376   * @brief  FLASH operation error interrupt callback.
377   * @param  ReturnValue The value saved in this parameter depends on the ongoing procedure
378   *                 Mass Erase: 0
379   *                 Page Erase: Page number which returned an error
380   *                 Program: Address which was selected for data program
381   * @retval None
382   */
HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue)383 __weak void HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue)
384 {
385   /* Prevent unused argument(s) compilation warning */
386   UNUSED(ReturnValue);
387 
388   /* NOTE : This function should not be modified, when the callback is needed,
389             the HAL_FLASH_OperationErrorCallback could be implemented in the user file
390    */
391 }
392 
393 /**
394   * @}
395   */
396 
397 /** @defgroup FLASH_Exported_Functions_Group2 Peripheral Errors functions
398   *  @brief   Peripheral Errors functions
399   *
400 @verbatim
401  ===============================================================================
402                 ##### Peripheral Errors functions #####
403  ===============================================================================
404     [..]
405     This subsection permits to get in run-time Errors of the FLASH peripheral.
406 
407 @endverbatim
408   * @{
409   */
410 
411 /**
412   * @brief  Get the specific FLASH error flag.
413   * @retval FLASH_ErrorCode The returned value can be
414   *            @arg @ref HAL_FLASH_ERROR_NONE    No error set
415   *            @arg @ref HAL_FLASH_ERROR_OP      FLASH Operation error
416   *            @arg @ref HAL_FLASH_ERROR_ILLCMD  FLASH Illegal command
417   */
HAL_FLASH_GetError(void)418 uint32_t HAL_FLASH_GetError(void)
419 {
420   return pFlash.ErrorCode;
421 }
422 
423 /**
424   * @}
425   */
426 
427 /**
428   * @}
429   */
430 
431 /* Private functions ---------------------------------------------------------*/
432 
433 /** @addtogroup FLASH_Private_Functions
434   * @{
435   */
436 
437 /**
438   * @brief  Wait for a FLASH operation to complete.
439   * @param  Timeout Maximum flash operation timeout
440   * @retval HAL_StatusTypeDef HAL Status
441   */
FLASH_WaitForLastOperation(uint32_t Timeout)442 HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout)
443 {
444   uint32_t tickstart = HAL_GetTick();
445 
446   /* Wait for the FLASH operation to complete by polling on CMDDONE flag to be set.
447      If the FLASH operation fails, an error flag will be set */
448   while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_CMDDONE) != SET)
449   {
450     if (Timeout != HAL_MAX_DELAY)
451     {
452       if ((HAL_GetTick() - tickstart) >= Timeout)
453       {
454         return HAL_TIMEOUT;
455       }
456     }
457   }
458 
459   /* Check flash errors */
460   if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ALL_ERRORS))
461   {
462     /* Save the error code */
463     pFlash.ErrorCode |= FLASH->IRQSTAT;
464 
465     /* Clear error flags */
466     __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
467 
468     return HAL_ERROR;
469   }
470 
471   return HAL_OK;
472 }
473 
474 /**
475   * @brief  Program a word (32-bit) at a specified address.
476   * @param  Address Specifies the address to be programmed.
477   * @param  Data Specifies the data to be programmed.
478   * @retval None
479   */
FLASH_Program_Word(uint32_t Address,uint32_t Data)480 static void FLASH_Program_Word(uint32_t Address, uint32_t Data)
481 {
482   /* Clear All Flags */
483   __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_CMDDONE | FLASH_FLAG_CMDSTART | FLASH_FLAG_CMDERR | FLASH_FLAG_ILLCMD);
484 
485   /* Load the word address */
486 
487   FLASH->ADDRESS = (((Address - FLASH_START_ADDR) >> 2) & FLASH_SIZE_MASK);
488 
489   /* Load the data to program */
490   FLASH->DATA0 = Data;
491 
492   /* Load the WRITE command */
493   FLASH->COMMAND = FLASH_CMD_WRITE;
494 }
495 
496 /**
497   * @brief  Program 4 words starting from the specified address.
498   * @param  Address Specifies the address to be programmed.
499   * @param  DataAddress Specifies the address where the data are stored.
500   * @retval None
501   */
FLASH_Program_Burst(uint32_t Address,uint32_t DataAddress)502 static void FLASH_Program_Burst(uint32_t Address, uint32_t DataAddress)
503 {
504   uint32_t *src_addr  = (uint32_t *)DataAddress;
505 
506   /* Clear All Flags */
507   __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_CMDDONE | FLASH_FLAG_CMDSTART | FLASH_FLAG_CMDERR | FLASH_FLAG_ILLCMD);
508 
509   /* Load the word address */
510   FLASH->ADDRESS = (((Address - FLASH_START_ADDR) >> 2) & FLASH_SIZE_MASK);
511   FLASH->DATA0 = *src_addr;
512   src_addr = src_addr + 1;
513   FLASH->DATA1 = *src_addr;
514   src_addr = src_addr + 1;
515   FLASH->DATA2 = *src_addr;
516   src_addr = src_addr + 1;
517   FLASH->DATA3 = *src_addr;
518 
519   /* Load the BURST WRITE command */
520   FLASH->COMMAND = FLASH_CMD_BURSTWRITE;
521 }
522 
523 /**
524   * @}
525   */
526 
527 #endif /* HAL_FLASH_MODULE_ENABLED */
528 
529 /**
530   * @}
531   */
532 
533 /**
534   * @}
535   */
536