1 /*
2 * Percepio Trace Recorder for Tracealyzer v4.8.1
3 * Copyright 2023 Percepio AB
4 * www.percepio.com
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 *
8 * The implementation for strings.
9 */
10
11 #include <trcRecorder.h>
12
13 #if (TRC_USE_TRACEALYZER_RECORDER == 1)
14
15 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
16
17 #include <trcTypes.h>
18
19 #ifndef TRC_SEND_NAME_ONLY_ON_DELETE
20 #define TRC_SEND_NAME_ONLY_ON_DELETE 0
21 #endif
22
23 traceResult prvTraceObjectSendNameEvent(void* pvObject, const char* szName, uint32_t uiLength);
24
25 /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
xTraceObjectRegisterInternal(uint32_t uiEventCode,void * const pvObject,const char * szName,TraceUnsignedBaseType_t uxStateCount,const TraceUnsignedBaseType_t uxStates[],TraceUnsignedBaseType_t uxOptions,TraceObjectHandle_t * pxObjectHandle)26 traceResult xTraceObjectRegisterInternal(uint32_t uiEventCode, void* const pvObject, const char* szName, TraceUnsignedBaseType_t uxStateCount, const TraceUnsignedBaseType_t uxStates[], TraceUnsignedBaseType_t uxOptions, TraceObjectHandle_t* pxObjectHandle)
27 {
28 TraceEntryHandle_t xEntryHandle;
29 TraceEventHandle_t xEventHandle = 0;
30 TraceUnsignedBaseType_t i;
31 void *pvAddress;
32
33 TRACE_ALLOC_CRITICAL_SECTION();
34
35 /* This should never fail */
36 TRC_ASSERT(pxObjectHandle != (void*)0);
37
38 /* This should never fail */
39 TRC_ASSERT(uxStateCount <= (uint32_t)(TRC_ENTRY_TABLE_STATE_COUNT));
40
41 TRACE_ENTER_CRITICAL_SECTION();
42
43 if (pvObject != (void*)0)
44 {
45 /* An address was supplied */
46 if (xTraceEntryCreateWithAddress(pvObject, &xEntryHandle) == TRC_FAIL)
47 {
48 TRACE_EXIT_CRITICAL_SECTION();
49
50 return TRC_FAIL;
51 }
52
53 pvAddress = pvObject;
54 }
55 else
56 {
57 /* No address was supplied */
58 if (xTraceEntryCreate(&xEntryHandle) == TRC_FAIL)
59 {
60 TRACE_EXIT_CRITICAL_SECTION();
61
62 return TRC_FAIL;
63 }
64
65 TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetAddress(xEntryHandle, &pvAddress) == TRC_SUCCESS);
66 }
67
68 for (i = 0u; i < uxStateCount; i++)
69 {
70 /* This should never fail */
71 TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetState(xEntryHandle, (uint32_t)i, uxStates[i]) == TRC_SUCCESS);
72 }
73
74 /* This should never fail */
75 TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetOptions(xEntryHandle, (uint32_t)uxOptions) == TRC_SUCCESS);
76
77 *pxObjectHandle = (TraceObjectHandle_t)xEntryHandle;
78
79 TRACE_EXIT_CRITICAL_SECTION();
80
81 if ((szName != (void*)0) && (szName[0] != (char)0)) /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/ /*cstat !MISRAC2004-17.4_b We need to access every character in the string*/
82 {
83 /* Not a null or empty string */
84 /* This will set the symbol and create an event for it */
85 /* This should never fail */
86 TRC_ASSERT_ALWAYS_EVALUATE(xTraceObjectSetName((TraceObjectHandle_t)xEntryHandle, szName) == TRC_SUCCESS);
87 }
88
89 /* Send the create event, if possible */
90 /*We need to check this */
91 if (xTraceEventBegin(uiEventCode, sizeof(void*) + (uxStateCount * sizeof(TraceUnsignedBaseType_t)), &xEventHandle) == TRC_SUCCESS)
92 {
93 (void)xTraceEventAddPointer(xEventHandle, pvAddress);
94 for (i = 0u; i < uxStateCount; i++)
95 {
96 (void)xTraceEventAddUnsignedBaseType(xEventHandle, uxStates[i]);
97 }
98 (void)xTraceEventEnd(xEventHandle); /*cstat !MISRAC2012-Rule-17.7 Suppress ignored return value check (inside macro)*/
99 }
100
101 return TRC_SUCCESS;
102 }
103
104 /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
xTraceObjectRegister(uint32_t uiEventCode,void * const pvObject,const char * szName,TraceUnsignedBaseType_t uxState,TraceObjectHandle_t * pxObjectHandle)105 traceResult xTraceObjectRegister(uint32_t uiEventCode, void* const pvObject, const char* szName, TraceUnsignedBaseType_t uxState, TraceObjectHandle_t *pxObjectHandle)
106 {
107 return xTraceObjectRegisterInternal(uiEventCode, pvObject, szName, 1u, &uxState, 0u, pxObjectHandle);
108 }
109
xTraceObjectUnregister(TraceObjectHandle_t xObjectHandle,uint32_t uiEventCode,TraceUnsignedBaseType_t uxState)110 traceResult xTraceObjectUnregister(TraceObjectHandle_t xObjectHandle, uint32_t uiEventCode, TraceUnsignedBaseType_t uxState)
111 {
112 void* pvObject = (void*)0;
113 const char *szName = (void*)0; /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
114 #if (TRC_SEND_NAME_ONLY_ON_DELETE == 1)
115 uint32_t uiLength;
116 uint32_t i;
117 #endif
118
119 /* If asserts are disabled this variable will not get used, this stops warnings. */
120 (void)szName;
121
122 /* This should never fail */
123 TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetAddress((TraceEntryHandle_t)xObjectHandle, &pvObject) == TRC_SUCCESS);
124
125 /* This should never fail */
126 TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetSymbol((TraceEntryHandle_t)xObjectHandle, &szName) == TRC_SUCCESS);
127
128 #if (TRC_SEND_NAME_ONLY_ON_DELETE == 1)
129 /* Send name event because this is a delete */
130
131 for (i = 0u; (szName[i] != (char)0) && (i < 128u); i++) {} /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/ /*cstat !MISRAC2004-17.4_b We need to access every character in the string*/
132
133 uiLength = i;
134 /* This should never fail */
135 TRC_ASSERT_ALWAYS_EVALUATE(prvTraceObjectSendNameEvent(pvObject, szName, uiLength) == TRC_SUCCESS);
136 #endif /* (TRC_SEND_NAME_ONLY_ON_DELETE == 1) */
137
138 /* Send the delete event, if possible */
139 (void)xTraceEventCreate2(uiEventCode, (TraceUnsignedBaseType_t)(pvObject), uxState); /*cstat !MISRAC2004-11.3 !MISRAC2012-Rule-11.4 !MISRAC2012-Rule-11.6 Suppress conversion from pointer to integer check*/
140
141 return xTraceEntryDelete(xObjectHandle);
142 }
143
144 /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
xTraceObjectSetName(TraceObjectHandle_t xObjectHandle,const char * szName)145 traceResult xTraceObjectSetName(TraceObjectHandle_t xObjectHandle, const char* szName)
146 {
147 void* pvObject = (void*)0;
148 uint32_t uiLength;
149 uint32_t i;
150
151 /* If asserts are disabled this variable will not get used, this stops warnings. */
152 (void)pvObject;
153
154 if (szName == (void*)0)
155 {
156 szName = ""; /*cstat !MISRAC2012-Rule-17.8 Suppress modified function parameter check*/
157 }
158
159 /* This should never fail */
160 TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetAddress((TraceEntryHandle_t)xObjectHandle, &pvObject) == TRC_SUCCESS);
161
162 for (i = 0u; (szName[i] != (char)0) && (i < 128u); i++) {} /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/ /*cstat !MISRAC2004-17.4_b We need to access every character in the string*/
163
164 uiLength = i;
165
166 #if (TRC_SEND_NAME_ONLY_ON_DELETE == 0)
167 /* Send name event now since we don't do it on delete events */
168 /* This should never fail */
169 TRC_ASSERT_ALWAYS_EVALUATE(prvTraceObjectSendNameEvent(pvObject, szName, uiLength) == TRC_SUCCESS);
170 #endif /* (TRC_SEND_NAME_ONLY_ON_DELETE == 0) */
171
172 return xTraceEntrySetSymbol((TraceEntryHandle_t)xObjectHandle, szName, uiLength);
173 }
174
175 /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
xTraceObjectRegisterWithoutHandle(uint32_t uiEventCode,void * pvObject,const char * szName,TraceUnsignedBaseType_t uxState)176 traceResult xTraceObjectRegisterWithoutHandle(uint32_t uiEventCode, void* pvObject, const char* szName, TraceUnsignedBaseType_t uxState)
177 {
178 TraceObjectHandle_t xObjectHandle;
179
180 return xTraceObjectRegister(uiEventCode, pvObject, szName, uxState, &xObjectHandle);
181 }
182
xTraceObjectUnregisterWithoutHandle(uint32_t uiEventCode,void * pvObject,TraceUnsignedBaseType_t uxState)183 traceResult xTraceObjectUnregisterWithoutHandle(uint32_t uiEventCode, void* pvObject, TraceUnsignedBaseType_t uxState)
184 {
185 TraceEntryHandle_t xEntryHandle;
186 traceResult xResult;
187
188 TRACE_ALLOC_CRITICAL_SECTION();
189
190 TRACE_ENTER_CRITICAL_SECTION();
191
192 if (xTraceEntryFind(pvObject, &xEntryHandle) == TRC_FAIL)
193 {
194 TRACE_EXIT_CRITICAL_SECTION();
195
196 return TRC_FAIL;
197 }
198
199 xResult = xTraceObjectUnregister((TraceObjectHandle_t)xEntryHandle, uiEventCode, uxState);
200
201 TRACE_EXIT_CRITICAL_SECTION();
202
203 return xResult;
204 }
205
206 /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
xTraceObjectSetNameWithoutHandle(void * pvObject,const char * szName)207 traceResult xTraceObjectSetNameWithoutHandle(void* pvObject, const char* szName)
208 {
209 TraceEntryHandle_t xEntryHandle;
210 traceResult xResult;
211
212 TRACE_ALLOC_CRITICAL_SECTION();
213
214 TRACE_ENTER_CRITICAL_SECTION();
215
216 if (xTraceEntryFind(pvObject, &xEntryHandle) == TRC_FAIL)
217 {
218 /* No previous entry found. Create one. */
219 if (xTraceEntryCreateWithAddress(pvObject, &xEntryHandle) == TRC_FAIL)
220 {
221 TRACE_EXIT_CRITICAL_SECTION();
222
223 return TRC_FAIL;
224 }
225 }
226
227 xResult = xTraceObjectSetName((TraceObjectHandle_t)xEntryHandle, szName);
228
229 TRACE_EXIT_CRITICAL_SECTION();
230
231 return xResult;
232 }
233
xTraceObjectSetSpecificStateWithoutHandle(void * pvObject,uint32_t uiIndex,TraceUnsignedBaseType_t uxState)234 traceResult xTraceObjectSetSpecificStateWithoutHandle(void* pvObject, uint32_t uiIndex, TraceUnsignedBaseType_t uxState)
235 {
236 TraceEntryHandle_t xEntryHandle;
237 traceResult xResult;
238
239 TRACE_ALLOC_CRITICAL_SECTION();
240
241 TRACE_ENTER_CRITICAL_SECTION();
242
243 if (xTraceEntryFind(pvObject, &xEntryHandle) == TRC_FAIL)
244 {
245 TRACE_EXIT_CRITICAL_SECTION();
246
247 return TRC_FAIL;
248 }
249
250 xResult = xTraceObjectSetSpecificState((TraceObjectHandle_t)xEntryHandle, uiIndex, uxState);
251
252 TRACE_EXIT_CRITICAL_SECTION();
253
254 return xResult;
255 }
256
xTraceObjectSetOptionsWithoutHandle(void * pvObject,uint32_t uiMask)257 traceResult xTraceObjectSetOptionsWithoutHandle(void* pvObject, uint32_t uiMask)
258 {
259 TraceEntryHandle_t xEntryHandle;
260 traceResult xResult;
261
262 TRACE_ALLOC_CRITICAL_SECTION();
263
264 TRACE_ENTER_CRITICAL_SECTION();
265
266 if (xTraceEntryFind(pvObject, &xEntryHandle) == TRC_FAIL)
267 {
268 /* No previous entry found. Create one. */
269 if (xTraceEntryCreateWithAddress(pvObject, &xEntryHandle) == TRC_FAIL)
270 {
271 TRACE_EXIT_CRITICAL_SECTION();
272
273 return TRC_FAIL;
274 }
275 }
276
277 xResult = xTraceObjectSetOptions((TraceObjectHandle_t)xEntryHandle, uiMask);
278
279 TRACE_EXIT_CRITICAL_SECTION();
280
281 return xResult;
282 }
283
284 /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
prvTraceObjectSendNameEvent(void * const pvObject,const char * szName,uint32_t uiLength)285 traceResult prvTraceObjectSendNameEvent(void* const pvObject, const char* szName, uint32_t uiLength)
286 {
287 uint32_t uiValue = 0u;
288 TraceEventHandle_t xEventHandle = 0;
289
290 if (xTraceEventBegin(PSF_EVENT_OBJ_NAME, sizeof(void*) + uiLength, &xEventHandle) == TRC_SUCCESS)
291 {
292 (void)xTraceEventAddPointer(xEventHandle, pvObject);
293 (void)xTraceEventAddString(xEventHandle, szName, uiLength);
294
295 /* Check if we can truncate */
296 (void)xTraceEventPayloadRemaining(xEventHandle, &uiValue);
297 if (uiValue > 0u)
298 {
299 (void)xTraceEventAdd8(xEventHandle, 0u);
300 }
301
302 (void)xTraceEventEnd(xEventHandle); /*cstat !MISRAC2012-Rule-17.7 Suppress ignored return value check (inside macro)*/
303 }
304
305 return TRC_SUCCESS;
306 }
307
308 #endif
309
310 #endif
311