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