1 /*
2 * Percepio DFM v2.1.0
3 * Copyright 2023 Percepio AB
4 * www.percepio.com
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 *
8 * FLASH Example implementation
9 */
10
11 #include <dfm.h>
12
13 #if (defined(DFM_CFG_ENABLED) && ((DFM_CFG_ENABLED) >= 1))
14
15 #include "dfmStoragePort.h"
16
17 #include <string.h> // for memcpy
18
19 /* Include your specific flash header file */
20 #include "flash.h"
21 #include "stm32l4xx_hal.h"
22
23 #define DFM_STORAGE_PORT_ALERT_TYPE 0x34561842
24 #define DFM_STORAGE_PORT_PAYLOAD_TYPE 0x82713124
25
26 typedef struct{
27 uint8_t data[DFM_CFG_FLASHSTORAGE_SIZE];
28 uint32_t alert_storage_counter;
29 } dfmFlashData_t;
30
31 dfmFlashData_t dfmFlashData __attribute__( ( section( ".dfm_alert" ), aligned (8) ) ) = { {0}, 0 };
32
33 uint32_t ulWrOffset = 0;
34 uint32_t ulRdOffset = 0;
35
36 static DfmResult_t prvDfmStoragePortWrite(DfmEntryHandle_t xEntryHandle, uint32_t ulType, uint32_t ulOverwrite);
37
38 /**
39 * @internal DFM Flash entry structure
40 */
41 typedef struct DfmStorageMetadata {
42 uint32_t dummy;
43 } DfmStorageMetadata_t;
44
xDfmStoragePortInitialize(DfmStoragePortData_t * pxBuffer)45 DfmResult_t xDfmStoragePortInitialize(DfmStoragePortData_t *pxBuffer)
46 {
47 ulWrOffset = 0;
48 ulRdOffset = 0;
49 return DFM_SUCCESS;
50 }
51
xDfmStoragePortStoreSession(void * pvData,uint32_t ulSize)52 DfmResult_t xDfmStoragePortStoreSession(void* pvData, uint32_t ulSize)
53 {
54 return DFM_FAIL;
55 }
56
xDfmStoragePortGetSession(void * pvBuffer,uint32_t ulBufferSize)57 DfmResult_t xDfmStoragePortGetSession(void* pvBuffer, uint32_t ulBufferSize)
58 {
59 return DFM_FAIL;
60 }
61
62
xDfmStoragePortStoreAlert(DfmEntryHandle_t xEntryHandle,uint32_t ulOverwrite)63 DfmResult_t xDfmStoragePortStoreAlert(DfmEntryHandle_t xEntryHandle, uint32_t ulOverwrite)
64 {
65 return prvDfmStoragePortWrite(xEntryHandle, DFM_STORAGE_PORT_ALERT_TYPE, ulOverwrite);
66 }
67
xDfmStoragePortGetAlert(void * pvBuffer,uint32_t ulBufferSize)68 DfmResult_t xDfmStoragePortGetAlert(void* pvBuffer, uint32_t ulBufferSize)
69 {
70 if (*((uint32_t*)&dfmFlashData.data[ulRdOffset]) == 0xffffffff)
71 {
72 // Not written
73 return DFM_FAIL;
74 }
75 uint32_t ulSize;
76 if (xDfmEntryGetSize((DfmEntryHandle_t)&dfmFlashData.data[ulRdOffset], &ulSize) == DFM_FAIL)
77 {
78 return DFM_FAIL;
79 }
80 // Read data into buffer
81 if (ulSize > ulBufferSize)
82 {
83 ulSize = ulBufferSize;
84 }
85 memcpy(pvBuffer, &dfmFlashData.data[ulRdOffset], ulSize);
86 ulRdOffset += ulSize;
87 ulRdOffset += (8 - (ulSize % 8));
88 return DFM_SUCCESS;
89 }
90
xDfmStoragePortStorePayloadChunk(DfmEntryHandle_t xEntryHandle,uint32_t ulOverwrite)91 DfmResult_t xDfmStoragePortStorePayloadChunk(DfmEntryHandle_t xEntryHandle, uint32_t ulOverwrite)
92 {
93 return prvDfmStoragePortWrite(xEntryHandle, DFM_STORAGE_PORT_PAYLOAD_TYPE, ulOverwrite);
94 }
95
xDfmStoragePortGetPayloadChunk(char * szSessionId,uint32_t ulAlertId,void * pvBuffer,uint32_t ulBufferSize)96 DfmResult_t xDfmStoragePortGetPayloadChunk(char* szSessionId, uint32_t ulAlertId, void* pvBuffer, uint32_t ulBufferSize)
97 {
98 return xDfmStoragePortGetAlert(pvBuffer, ulBufferSize);
99 }
100
101 /* Note: This function assumes the affected flash pages are only used for DFM alert storage.
102 * It does not preserve other data that might be present on these pages (future improvement!) */
prvDfmStoragePortWrite(DfmEntryHandle_t xEntryHandle,uint32_t ulType,uint32_t ulOverwrite)103 static DfmResult_t prvDfmStoragePortWrite(DfmEntryHandle_t xEntryHandle, uint32_t ulType, uint32_t ulOverwrite)
104 {
105 DFM_DEBUG_PRINT("prvDfmStoragePortWrite\n");
106
107 if (xEntryHandle == 0)
108 {
109 return DFM_FAIL;
110 }
111 uint32_t ulSize;
112 if (xDfmEntryGetSize(xEntryHandle, &ulSize) == DFM_FAIL)
113 {
114 return DFM_FAIL;
115 }
116
117 if ((ulType != DFM_STORAGE_PORT_ALERT_TYPE) && (ulType != DFM_STORAGE_PORT_PAYLOAD_TYPE))
118 {
119 return DFM_FAIL;
120 }
121
122 uint32_t ulDst = (uint32_t)&dfmFlashData.data[ulWrOffset];
123
124 /* Write to destination */
125 if (ulWrOffset == 0)
126 {
127
128 /* This erases the affected flash pages, needed before write. */
129 if (xDfmStoragePortReset() != DFM_SUCCESS)
130 {
131 return DFM_FAIL;
132 }
133 }
134
135 ulWrOffset += ulSize;
136 ulWrOffset += (8 - (ulSize % 8));
137
138 if ( ulWrOffset >= sizeof(dfmFlashData.data))
139 {
140 /* If this happens, you may increase DFM_DEMO_FLASHSTORAGE_SIZE */
141 DFM_ERROR_PRINT("\nDFM: Error - Not enough space in dfmFlashData.data.\n");
142 return DFM_FAIL;
143 }
144
145 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
146
147 if (FLASH_write_at(ulDst, xEntryHandle, ulSize) != 0)
148 {
149 return DFM_FAIL;
150 }
151
152 return DFM_SUCCESS;
153 }
154
xDfmStoragePortReset(void)155 DfmResult_t xDfmStoragePortReset(void)
156 {
157 DFM_DEBUG_PRINT("xDfmStoragePortReset()\n");
158
159 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
160
161 if (FLASH_unlock_erase((uint32_t)&dfmFlashData, sizeof(dfmFlashData)) != 0)
162 {
163 return DFM_FAIL;
164 }
165
166 return DFM_SUCCESS;
167 }
168
169 #endif
170