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