L14-Click 1.0
STM32WLE5CC LoRaWAN Sensor Platform
Loading...
Searching...
No Matches
flash_if.c
Go to the documentation of this file.
1/* USER CODE BEGIN Header */
2/**
3 ******************************************************************************
4 * @file flash_if.c
5 * @author MCD Application Team
6 * @brief This file provides set of firmware functions to manage Flash
7 * Interface functionalities.
8 ******************************************************************************
9 * @attention
10 *
11 * Copyright (c) 2026 STMicroelectronics.
12 * All rights reserved.
13 *
14 * This software is licensed under terms that can be found in the LICENSE file
15 * in the root directory of this software component.
16 * If no LICENSE file comes with this software, it is provided AS-IS.
17 *
18 ******************************************************************************
19 */
20/* USER CODE END Header */
21
22/* Includes ------------------------------------------------------------------*/
23#include "flash_if.h"
24#include "stm32_mem.h"
25
26/* USER CODE BEGIN Includes */
27
28/* USER CODE END Includes */
29
30/* External variables ---------------------------------------------------------*/
31/* USER CODE BEGIN EV */
32
33/* USER CODE END EV */
34
35/* Private typedef -----------------------------------------------------------*/
36/* USER CODE BEGIN PTD */
37
38/* USER CODE END PTD */
39
40/* Private define ------------------------------------------------------------*/
41/**
42 * @brief Flash empty status enumeration
43 */
44enum
45{
48};
49
50/* USER CODE BEGIN PD */
51
52/* USER CODE END PD */
53
54/* Private macro -------------------------------------------------------------*/
55/**
56 * @brief Get internal flash page index from page address
57 */
58#define PAGE_INDEX(__ADDRESS__) (uint32_t)((((__ADDRESS__) - FLASH_BASE) % FLASH_BANK_SIZE) / FLASH_PAGE_SIZE)
59
60/* USER CODE BEGIN PM */
61
62/* USER CODE END PM */
63
64/* Private variables ---------------------------------------------------------*/
65static uint8_t *pAllocatedBuffer = NULL;
66/* USER CODE BEGIN PV */
67
68/* USER CODE END PV */
69
70/* Private function prototypes -----------------------------------------------*/
71
72/* Private Functions prototypes: internal flash ------------------------------*/
73/**
74 * @brief This function writes a data buffer in flash (data are 64-bit aligned).
75 *
76 * @note After writing data buffer, the flash content is checked.
77 * @param pDestination: Start address for target location. It has to be 8 bytes aligned.
78 * @param pSource: pointer on buffer with data to write
79 * @param uLength: Length of data buffer in bytes. It has to be 8 bytes aligned.
80 * @return FLASH_IF_StatusTypedef status
81 */
82static FLASH_IF_StatusTypedef FLASH_IF_INT_Write(void *pDestination, const void *pSource, uint32_t uLength);
83
84/**
85 * @brief This function reads flash
86 *
87 * @param pDestination: Start address for target location
88 * @param pSource: flash address to read
89 * @param uLength: number of bytes
90 * @return FLASH_IF_StatusTypedef status
91 */
92static FLASH_IF_StatusTypedef FLASH_IF_INT_Read(void *pDestination, const void *pSource, uint32_t uLength);
93
94/**
95 * @brief This function does an erase of n (depends on Length) pages in user flash area
96 *
97 * @param pStart pointer of flash address to be erased
98 * @param uLength number of bytes
99 * @return FLASH_IF_StatusTypedef status
100 */
101static FLASH_IF_StatusTypedef FLASH_IF_INT_Erase(void *pStart, uint32_t uLength);
102
103/**
104 * @brief Clear error flags raised during previous operation
105 *
106 * @retval FLASH_IF_StatusTypedef status
107 */
109
110/* USER CODE BEGIN PFP */
111
112/* USER CODE END PFP */
113
114/* Exported functions --------------------------------------------------------*/
116{
118 /* USER CODE BEGIN FLASH_IF_Init_1 */
119
120 /* USER CODE END FLASH_IF_Init_1 */
121 pAllocatedBuffer = (uint8_t *)pAllocRamBuffer;
122
123 /* USER CODE BEGIN FLASH_IF_Init_2 */
124
125 /* USER CODE END FLASH_IF_Init_2 */
126 return ret_status;
127}
128
130{
132 /* USER CODE BEGIN FLASH_IF_DeInit_1 */
133
134 /* USER CODE END FLASH_IF_DeInit_1 */
135 pAllocatedBuffer = NULL;
136
137 /* USER CODE BEGIN FLASH_IF_DeInit_2 */
138
139 /* USER CODE END FLASH_IF_DeInit_2 */
140 return ret_status;
141}
142
143FLASH_IF_StatusTypedef FLASH_IF_Write(void *pDestination, const void *pSource, uint32_t uLength)
144{
146 /* USER CODE BEGIN FLASH_IF_Write_1 */
147
148 /* USER CODE END FLASH_IF_Write_1 */
149 if (IS_FLASH_MAIN_MEM_ADDRESS((uint32_t)pDestination))
150 {
151 ret_status = FLASH_IF_INT_Write(pDestination, pSource, uLength);
152 }
153 /* USER CODE BEGIN FLASH_IF_Write_2 */
154
155 /* USER CODE END FLASH_IF_Write_2 */
156 return ret_status;
157}
158
159FLASH_IF_StatusTypedef FLASH_IF_Read(void *pDestination, const void *pSource, uint32_t uLength)
160{
162 /* USER CODE BEGIN FLASH_IF_Read_1 */
163
164 /* USER CODE END FLASH_IF_Read_1 */
165 if (IS_FLASH_MAIN_MEM_ADDRESS((uint32_t)pSource))
166 {
167 ret_status = FLASH_IF_INT_Read(pDestination, pSource, uLength);
168 }
169 /* USER CODE BEGIN FLASH_IF_Read_2 */
170
171 /* USER CODE END FLASH_IF_Read_2 */
172 return ret_status;
173}
174
175FLASH_IF_StatusTypedef FLASH_IF_Erase(void *pStart, uint32_t uLength)
176{
178 /* USER CODE BEGIN FLASH_IF_Erase_1 */
179
180 /* USER CODE END FLASH_IF_Erase_1 */
181 /* Check Flash start address */
182 if (IS_FLASH_MAIN_MEM_ADDRESS((uint32_t)pStart))
183 {
184 ret_status = FLASH_IF_INT_Erase(pStart, uLength);
185 }
186 /* USER CODE BEGIN FLASH_IF_Erase_2 */
187
188 /* USER CODE END FLASH_IF_Erase_2 */
189 return ret_status;
190}
191
192/* USER CODE BEGIN EF */
193
194/* USER CODE END EF */
195
196/* Private Functions Definition -----------------------------------------------*/
197
198/* Private Functions : internal flash -----------------------------------------*/
199static FLASH_IF_StatusTypedef FLASH_IF_INT_Write(void *pDestination, const void *pSource, uint32_t uLength)
200{
202 /* USER CODE BEGIN FLASH_IF_INT_Write_1 */
203
204 /* USER CODE END FLASH_IF_INT_Write_1 */
205 uint32_t uDest = (uint32_t)pDestination;
206 uint32_t uSource = (uint32_t)pSource;
207 uint32_t length = uLength;
208 uint32_t page_index;
209 uint32_t address_offset;
210 uint32_t start_page_index;
211 uint32_t page_address;
212 uint32_t number_pages;
213 uint32_t current_dest;
214 uint32_t current_source;
215 uint32_t current_length;
216 volatile uint64_t data = 0;
217
218 if ((pDestination == NULL) || (pSource == NULL) || !IS_ADDR_ALIGNED_64BITS(uLength)
219 || !IS_ADDR_ALIGNED_64BITS((uint32_t)pDestination))
220 {
222 }
223
224 /* Clear error flags raised during previous operation */
225 ret_status = FLASH_IF_INT_Clear_Error();
226
227 if (ret_status == FLASH_IF_OK)
228 {
229 /* Unlock the Flash to enable the flash control register access */
230 if (HAL_FLASH_Unlock() == HAL_OK)
231 {
232 start_page_index = PAGE_INDEX(uDest);
233 number_pages = PAGE_INDEX(uDest + uLength - 1U) - start_page_index + 1U;
234
235 if (number_pages > 1)
236 {
237 length = FLASH_PAGE_SIZE - (uDest % FLASH_PAGE_SIZE);
238 }
239
240 for (page_index = start_page_index; page_index < (start_page_index + number_pages); page_index++)
241 {
242 page_address = page_index * FLASH_PAGE_SIZE + FLASH_BASE;
243 if (pAllocatedBuffer == NULL)
244 {
245 ret_status = FLASH_IF_PARAM_ERROR;
246 break; /* exit for loop */
247 }
248
249 /* backup initial Flash page data in RAM area */
250 FLASH_IF_INT_Read(pAllocatedBuffer, (const void *)page_address, FLASH_PAGE_SIZE);
251 /* copy fragment into RAM area */
252 UTIL_MEM_cpy_8(&pAllocatedBuffer[uDest % FLASH_PAGE_SIZE], (const void *)uSource, length);
253
254 /* erase the Flash sector, to avoid writing twice in RAM */
255 if (FLASH_IF_INT_Erase((void *)page_address, FLASH_PAGE_SIZE) != FLASH_IF_OK)
256 {
257 ret_status = FLASH_IF_ERASE_ERROR;
258 break; /* exit for loop */
259 }
260
261 /* copy the whole flash sector including fragment from RAM to Flash */
262 current_dest = page_address;
263 current_source = (uint32_t)pAllocatedBuffer;
264 current_length = FLASH_PAGE_SIZE;
265
266 /* Unlock back the Flash */
267 if (HAL_OK != HAL_FLASH_Unlock())
268 {
269 ret_status = FLASH_IF_LOCK_ERROR;
270 }
271
272 for (address_offset = 0U; address_offset < current_length; address_offset += 8U)
273 {
274 data = (uint64_t)(*(uint32_t*)(current_source + address_offset));
275 data |= ((uint64_t)(*(uint32_t*)(current_source + sizeof(current_source) + address_offset)) << 32U);
276 /* Device voltage range supposed to be [2.7V to 3.6V], the operation will be done by word */
277 if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, current_dest, data) == HAL_OK)
278 {
279 /* Check the written value */
280 if ( ((uint64_t)(*(uint32_t*)(current_dest)) | ((uint64_t)(*(uint32_t*)(current_dest + sizeof(current_dest))) << 32U)) != data)
281 {
282 /* Flash content doesn't match SRAM content */
283 ret_status = FLASH_IF_WRITE_ERROR;
284 break;
285 }
286 /* Increment FLASH Destination address */
287 current_dest = current_dest + 8U;
288 }
289 else
290 {
291 /* Error occurred while writing data in Flash memory */
292 ret_status = FLASH_IF_WRITE_ERROR;
293 break;
294 }
295 }
296
297 if (ret_status != FLASH_IF_OK)
298 {
299 /* Error occurred while writing data in Flash memory */
300 break;
301 }
302
303 /* Increment FLASH destination address, source address, and decrease remaining length */
304 uDest += length;
305 uSource += length;
306 length = ((uLength - length) > FLASH_PAGE_SIZE) ? FLASH_PAGE_SIZE : uLength - length;
307 }
308
309 /* Lock the Flash to disable the flash control register access (recommended
310 * to protect the FLASH memory against possible unwanted operation) */
311 HAL_FLASH_Lock();
312 }
313 else
314 {
315 ret_status = FLASH_IF_LOCK_ERROR;
316 }
317 }
318 /* USER CODE BEGIN FLASH_IF_INT_Write_2 */
319
320 /* USER CODE END FLASH_IF_INT_Write_2 */
321 return ret_status;
322}
323
324static FLASH_IF_StatusTypedef FLASH_IF_INT_Read(void *pDestination, const void *pSource, uint32_t uLength)
325{
327 /* USER CODE BEGIN FLASH_IF_INT_Read_1 */
328
329 /* USER CODE END FLASH_IF_INT_Read_1 */
330 if ((pDestination == NULL) || (pSource == NULL))
331 {
333 }
334
335 UTIL_MEM_cpy_8(pDestination, pSource, uLength);
336 /* USER CODE BEGIN FLASH_IF_INT_Read_2 */
337
338 /* USER CODE END FLASH_IF_INT_Read_2 */
339 return ret_status;
340}
341
342static FLASH_IF_StatusTypedef FLASH_IF_INT_Erase(void *pStart, uint32_t uLength)
343{
345 /* USER CODE BEGIN FLASH_IF_INT_Erase_1 */
346
347 /* USER CODE END FLASH_IF_INT_Erase_1 */
348 HAL_StatusTypeDef hal_status = HAL_ERROR;
349 uint32_t page_error = 0U;
350 uint32_t uStart = (uint32_t)pStart;
351 FLASH_EraseInitTypeDef erase_init;
352
353 if (pStart == NULL)
354 {
356 }
357
358 /* Clear error flags raised during previous operation */
359 ret_status = FLASH_IF_INT_Clear_Error();
360
361 if (ret_status == FLASH_IF_OK)
362 {
363 /* Unlock the Flash to enable the flash control register access */
364 if (HAL_FLASH_Unlock() == HAL_OK)
365 {
366 erase_init.TypeErase = FLASH_TYPEERASE_PAGES;
367 erase_init.Page = PAGE_INDEX(uStart);
368 /* Get the number of pages to erase from 1st page */
369 erase_init.NbPages = PAGE_INDEX(uStart + uLength - 1U) - erase_init.Page + 1U;
370
371 /* Erase the Page */
372 hal_status = HAL_FLASHEx_Erase(&erase_init, &page_error);
373
374 if (hal_status != HAL_OK)
375 {
376 ret_status = (hal_status == HAL_BUSY) ? FLASH_IF_BUSY : FLASH_IF_ERASE_ERROR;
377 }
378
379 /* Lock the Flash to disable the flash control register access (recommended
380 * to protect the FLASH memory against possible unwanted operation) */
381 HAL_FLASH_Lock();
382 }
383 else
384 {
385 ret_status = FLASH_IF_LOCK_ERROR;
386 }
387 }
388 /* USER CODE BEGIN FLASH_IF_INT_Erase_2 */
389
390 /* USER CODE END FLASH_IF_INT_Erase_2 */
391 return ret_status;
392}
393
395{
397 /* USER CODE BEGIN FLASH_IF_INT_Clear_Error_1 */
398
399 /* USER CODE END FLASH_IF_INT_Clear_Error_1 */
400 /* Unlock the Program memory */
401 if (HAL_FLASH_Unlock() == HAL_OK)
402 {
403 /* Clear all FLASH flags */
404 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
405 /* Unlock the Program memory */
406 if (HAL_FLASH_Lock() == HAL_OK)
407 {
408 ret_status = FLASH_IF_OK;
409 }
410 }
411 /* USER CODE BEGIN FLASH_IF_INT_Clear_Error_2 */
412
413 /* USER CODE END FLASH_IF_INT_Clear_Error_2 */
414 return ret_status;
415}
416
417/* USER CODE BEGIN PrFD */
418
419/* USER CODE END PrFD */
420
421/* HAL overload functions ---------------------------------------------------------*/
422/**
423 * @note This function overwrites the __weak one from HAL
424 */
425void HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue)
426{
427 /* USER CODE BEGIN HAL_FLASH_EndOfOperationCallback_1 */
428
429 /* USER CODE END HAL_FLASH_EndOfOperationCallback_1 */
430 if (ReturnValue == 0xFFFFFFFFUL)
431 {
432 /* Call when all requested pages have been erased */
433 }
434 /* USER CODE BEGIN HAL_FLASH_EndOfOperationCallback_2 */
435
436 /* USER CODE END HAL_FLASH_EndOfOperationCallback_2 */
437}
438
439/**
440 * @note This function overwrites the __weak one from HAL
441 */
442void HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue)
443{
444 /* USER CODE BEGIN HAL_FLASH_OperationErrorCallback_1 */
445
446 /* USER CODE END HAL_FLASH_OperationErrorCallback_1 */
447}
448
449/* USER CODE BEGIN Overload_HAL_weaks */
450
451/* USER CODE END Overload_HAL_weaks */
FLASH_IF_StatusTypedef FLASH_IF_Write(void *pDestination, const void *pSource, uint32_t uLength)
This function writes a data buffer in internal or external flash.
Definition flash_if.c:143
static uint8_t * pAllocatedBuffer
Definition flash_if.c:65
#define PAGE_INDEX(__ADDRESS__)
Get internal flash page index from page address.
Definition flash_if.c:58
void HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue)
Definition flash_if.c:442
static FLASH_IF_StatusTypedef FLASH_IF_INT_Read(void *pDestination, const void *pSource, uint32_t uLength)
This function reads flash.
Definition flash_if.c:324
FLASH_IF_StatusTypedef FLASH_IF_DeInit(void)
This function de-initializes the internal and external flash interface.
Definition flash_if.c:129
void HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue)
Definition flash_if.c:425
static FLASH_IF_StatusTypedef FLASH_IF_INT_Erase(void *pStart, uint32_t uLength)
This function does an erase of n (depends on Length) pages in user flash area.
Definition flash_if.c:342
static FLASH_IF_StatusTypedef FLASH_IF_INT_Write(void *pDestination, const void *pSource, uint32_t uLength)
This function writes a data buffer in flash (data are 64-bit aligned).
Definition flash_if.c:199
FLASH_IF_StatusTypedef FLASH_IF_Erase(void *pStart, uint32_t uLength)
This function erases a amount of internal or external flash pages depending of the length.
Definition flash_if.c:175
static FLASH_IF_StatusTypedef FLASH_IF_INT_Clear_Error(void)
Clear error flags raised during previous operation.
Definition flash_if.c:394
FLASH_IF_StatusTypedef FLASH_IF_Read(void *pDestination, const void *pSource, uint32_t uLength)
This function reads a amount of data from flash and copy into the output data buffer.
Definition flash_if.c:159
@ FLASH_IF_MEM_NOT_EMPTY
Definition flash_if.c:47
@ FLASH_IF_MEM_EMPTY
Definition flash_if.c:46
FLASH_IF_StatusTypedef FLASH_IF_Init(void *pAllocRamBuffer)
This function initializes the internal and external flash interface.
Definition flash_if.c:115
This file contains definitions for FLASH Interface functionalities.
FLASH_IF_StatusTypedef
Flash status.
Definition flash_if.h:41
@ FLASH_IF_ERASE_ERROR
Definition flash_if.h:46
@ FLASH_IF_OK
Definition flash_if.h:48
@ FLASH_IF_LOCK_ERROR
Definition flash_if.h:43
@ FLASH_IF_BUSY
Definition flash_if.h:49
@ FLASH_IF_PARAM_ERROR
Definition flash_if.h:42
@ FLASH_IF_ERROR
Definition flash_if.h:47
@ FLASH_IF_WRITE_ERROR
Definition flash_if.h:44