1 /*
2 * 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 of the entry table.
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 /* (EntryAddress >= FirstEntryAddress) && (EntryAddress < EntryAddressOutsideArray) */
18 #define VALIDATE_ENTRY_HANDLE(xEntryHandle) (((void*)(xEntryHandle) >= (void*)&pxEntryTable->axEntries[0]) && ((void*)(xEntryHandle) < (void*)&pxEntryTable->axEntries[TRC_ENTRY_TABLE_SLOTS]))
19
20 /*cstat !MISRAC2004-19.4 Suppress macro check*/
21 #define GIVE_ENTRY_INDEX(xIndex) pxIndexTable->axFreeIndexes[pxIndexTable->uiFreeIndexCount] = (xIndex); pxIndexTable->uiFreeIndexCount++
22
23 /*cstat !MISRAC2004-19.4 Suppress macro check*/
24 #define GET_FREE_INDEX_COUNT() pxIndexTable->uiFreeIndexCount
25
26 /* Index = (EntryAddress - FirstEntryAddress) / EntrySize */
27 #define CALCULATE_ENTRY_INDEX(xEntryHandle) (TraceEntryIndex_t)(((TraceUnsignedBaseType_t)(xEntryHandle) - (TraceUnsignedBaseType_t)&pxEntryTable->axEntries[0]) / sizeof(TraceEntry_t))
28
29 /* Private function definitions */
30 static traceResult prvEntryIndexInitialize(void);
31 static traceResult prvEntryIndexTake(TraceEntryIndex_t *pxIndex);
32
33 /* Variables */
34 static TraceEntryTable_t *pxEntryTable TRC_CFG_RECORDER_DATA_ATTRIBUTE;
35 static TraceEntryIndexTable_t *pxIndexTable TRC_CFG_RECORDER_DATA_ATTRIBUTE;
36
xTraceEntryIndexTableInitialize(TraceEntryIndexTable_t * const pxBuffer)37 traceResult xTraceEntryIndexTableInitialize(TraceEntryIndexTable_t* const pxBuffer)
38 {
39 /* This should never fail */
40 TRC_ASSERT(pxBuffer != (void*)0);
41
42 pxIndexTable = pxBuffer;
43
44 return prvEntryIndexInitialize();
45 }
46
xTraceEntryTableInitialize(TraceEntryTable_t * const pxBuffer)47 traceResult xTraceEntryTableInitialize(TraceEntryTable_t* const pxBuffer)
48 {
49 uint32_t i, j;
50
51 /* This should never fail */
52 TRC_ASSERT(pxBuffer != (void*)0);
53
54 /* This should never fail */
55 TRC_ASSERT((TRC_ENTRY_TABLE_SLOTS) != 0);
56
57 pxEntryTable = pxBuffer;
58
59 pxEntryTable->uxSlots = (TraceUnsignedBaseType_t)(TRC_ENTRY_TABLE_SLOTS);
60 pxEntryTable->uxEntrySymbolLength = (TraceUnsignedBaseType_t)(TRC_ENTRY_TABLE_SLOT_SYMBOL_SIZE);
61 pxEntryTable->uxEntryStateCount = (TraceUnsignedBaseType_t)(TRC_ENTRY_TABLE_STATE_COUNT);
62
63 for (i = 0u; i < (uint32_t)(TRC_ENTRY_TABLE_SLOTS); i++)
64 {
65 pxEntryTable->axEntries[i].pvAddress = 0;
66 for (j = 0u; j < TRC_ENTRY_TABLE_STATE_COUNT; j++)
67 {
68 pxEntryTable->axEntries[i].xStates[j] = (TraceUnsignedBaseType_t)0;
69 }
70 pxEntryTable->axEntries[i].szSymbol[0] = (char)0; /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
71 }
72
73 xTraceSetComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY);
74
75 return TRC_SUCCESS;
76 }
77
xTraceEntryCreate(TraceEntryHandle_t * pxEntryHandle)78 traceResult xTraceEntryCreate(TraceEntryHandle_t *pxEntryHandle)
79 {
80 uint32_t i;
81 TraceEntryIndex_t xIndex;
82 TraceEntry_t *pxEntry;
83
84 TRACE_ALLOC_CRITICAL_SECTION();
85
86 /* We always check this */
87 if (xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY) == 0U)
88 {
89 return TRC_FAIL;
90 }
91
92 /* This should never fail */
93 TRC_ASSERT(pxEntryHandle != (void*)0);
94
95 TRACE_ENTER_CRITICAL_SECTION();
96
97 if (prvEntryIndexTake(&xIndex) != TRC_SUCCESS)
98 {
99 (void)xTraceDiagnosticsIncrease(TRC_DIAGNOSTICS_ENTRY_SLOTS_NO_ROOM);
100
101 TRACE_EXIT_CRITICAL_SECTION();
102
103 return TRC_FAIL;
104 }
105
106 pxEntry = &pxEntryTable->axEntries[xIndex];
107
108 pxEntry->pvAddress = (void*)pxEntry; /* We set a temporary address */
109
110 for (i = 0u; i < (uint32_t)(TRC_ENTRY_TABLE_STATE_COUNT); i++)
111 {
112 pxEntry->xStates[i] = (TraceUnsignedBaseType_t)0;
113 }
114
115 pxEntry->uiOptions = 0u;
116 pxEntry->szSymbol[0] = (char)0; /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
117
118 *pxEntryHandle = (TraceEntryHandle_t)pxEntry;
119
120 TRACE_EXIT_CRITICAL_SECTION();
121
122 return TRC_SUCCESS;
123 }
124
xTraceEntryDelete(TraceEntryHandle_t xEntryHandle)125 traceResult xTraceEntryDelete(TraceEntryHandle_t xEntryHandle)
126 {
127 TraceEntryIndex_t xIndex;
128
129 TRACE_ALLOC_CRITICAL_SECTION();
130
131 /* This should never fail */
132 TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
133
134 /* This should never fail */
135 TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle)); /*cstat !MISRAC2004-17.3 !MISRAC2012-Rule-18.3 Suppress pointer comparison check*/
136
137 /* Calculate the index based on the entry address */
138 /* Does not need to be locked. */
139 /* This should never fail */
140 xIndex = CALCULATE_ENTRY_INDEX(xEntryHandle); /*cstat !MISRAC2004-11.3 !MISRAC2012-Rule-11.4 Suppress conversion from pointer to integer check*/ /*cstat !MISRAC2004-17.2 !MISRAC2012-Rule-18.2 !MISRAC2012-Rule-18.4 Suppress pointer comparison check*/
141
142 TRC_ASSERT(xIndex < (TraceEntryIndex_t)TRC_ENTRY_TABLE_SLOTS);
143
144 TRACE_ENTER_CRITICAL_SECTION();
145
146 if (((TraceEntry_t*)xEntryHandle)->pvAddress == 0)
147 {
148 /* Someone else has deleted this already? */
149 TRACE_EXIT_CRITICAL_SECTION();
150
151 return TRC_FAIL;
152 }
153
154 /* A valid address, so we assume it is OK. */
155 /* We clear the address field which is used on host to see if entries are active. */
156 ((TraceEntry_t*)xEntryHandle)->pvAddress = 0;
157
158 /* Give back the index */
159 GIVE_ENTRY_INDEX(xIndex);
160
161 TRACE_EXIT_CRITICAL_SECTION();
162
163 return TRC_SUCCESS;
164 }
165
xTraceEntryFind(const void * const pvAddress,TraceEntryHandle_t * pxEntryHandle)166 traceResult xTraceEntryFind(const void* const pvAddress, TraceEntryHandle_t* pxEntryHandle)
167 {
168 uint32_t i;
169 TraceEntry_t* pxEntry;
170
171 /* This should never fail */
172 TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
173
174 /* This should never fail */
175 TRC_ASSERT(pxEntryHandle != (void*)0);
176
177 /* This should never fail */
178 TRC_ASSERT(pvAddress != (void*)0);
179
180 for (i = 0u; i < (uint32_t)(TRC_ENTRY_TABLE_SLOTS); i++)
181 {
182 pxEntry = &pxEntryTable->axEntries[i];
183 if (pxEntry->pvAddress == pvAddress)
184 {
185 *pxEntryHandle = (TraceEntryHandle_t)pxEntry;
186
187 return TRC_SUCCESS;
188 }
189 }
190
191 return TRC_FAIL;
192 }
193
194 /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
xTraceEntrySetSymbol(const TraceEntryHandle_t xEntryHandle,const char * szSymbol,uint32_t uiLength)195 traceResult xTraceEntrySetSymbol(const TraceEntryHandle_t xEntryHandle, const char* szSymbol, uint32_t uiLength)
196 {
197 uint32_t i;
198
199 /* This should never fail */
200 TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
201
202 if (szSymbol == (void*)0)
203 {
204 szSymbol = ""; /*cstat !MISRAC2012-Rule-17.8 Suppress modified function parameter check*/
205 uiLength = 0u; /*cstat !MISRAC2012-Rule-17.8 Suppress modified function parameter check*/
206 }
207
208 /* Remember the longest symbol name */
209 (void)xTraceDiagnosticsSetIfHigher(TRC_DIAGNOSTICS_ENTRY_SYMBOL_LONGEST_LENGTH, (int32_t)uiLength);
210
211 if (uiLength >= (uint32_t)(TRC_ENTRY_TABLE_SYMBOL_LENGTH))
212 {
213 /* No room for null termination. Set to max. */
214 uiLength = (uint32_t)(TRC_ENTRY_TABLE_SYMBOL_LENGTH) / sizeof(uint32_t); /*cstat !MISRAC2012-Rule-17.8 Suppress modified function parameter check*/
215 }
216 else
217 {
218 /* Make room for null termination by increasing the number of uint32_t required by 1 */
219 uiLength = (uiLength / sizeof(uint32_t)) + 1u; /*cstat !MISRAC2012-Rule-17.8 Suppress modified function parameter check*/
220 }
221
222 /* Does not need to be locked. */
223 /* This should never fail */
224 TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle)); /*cstat !MISRAC2004-17.3 !MISRAC2012-Rule-18.3 Suppress pointer comparison check*/
225
226 /* This will also copy the null termination, if possible */
227 for (i = 0u; i < uiLength; i++)
228 {
229 ((uint32_t*)(((TraceEntry_t*)xEntryHandle)->szSymbol))[i] = ((const uint32_t*)szSymbol)[i]; /*cstat !MISRAC2004-11.4 !MISRAC2012-Rule-11.3 Suppress conversion between pointer types checks*/ /*cstat !MISRAC2004-17.4_b We cast it to a uint32_t* in order to copy 4 bytes at a time*/
230 }
231
232 return TRC_SUCCESS;
233 }
234
xTraceEntryGetCount(uint32_t * puiCount)235 traceResult xTraceEntryGetCount(uint32_t* puiCount)
236 {
237 /* This should never fail */
238 TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
239
240 /* This should never fail */
241 TRC_ASSERT(puiCount != (void*)0);
242
243 *puiCount = (uint32_t)(TRC_ENTRY_TABLE_SLOTS) - GET_FREE_INDEX_COUNT();
244
245 return TRC_SUCCESS;
246 }
247
xTraceEntryGetAtIndex(uint32_t index,TraceEntryHandle_t * pxEntryHandle)248 traceResult xTraceEntryGetAtIndex(uint32_t index, TraceEntryHandle_t* pxEntryHandle)
249 {
250 /* This should never fail */
251 TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
252
253 /* This should never fail */
254 TRC_ASSERT(index < (uint32_t)(TRC_ENTRY_TABLE_SLOTS));
255
256 /* This should never fail */
257 TRC_ASSERT(pxEntryHandle != (void*)0);
258
259 *pxEntryHandle = (TraceEntryHandle_t)&pxEntryTable->axEntries[index];
260
261 return TRC_SUCCESS;
262 }
263
264 #if ((TRC_CFG_USE_TRACE_ASSERT) == 1)
265
xTraceEntryCreateWithAddress(void * const pvAddress,TraceEntryHandle_t * pxEntryHandle)266 traceResult xTraceEntryCreateWithAddress(void* const pvAddress, TraceEntryHandle_t* pxEntryHandle)
267 {
268 /* This should never fail */
269 TRC_ASSERT(pvAddress != (void*)0);
270
271 return TRC_ENTRY_CREATE_WITH_ADDRESS(pvAddress, pxEntryHandle);
272 }
273
xTraceEntrySetState(const TraceEntryHandle_t xEntryHandle,TraceUnsignedBaseType_t uxStateIndex,TraceUnsignedBaseType_t uxState)274 traceResult xTraceEntrySetState(const TraceEntryHandle_t xEntryHandle, TraceUnsignedBaseType_t uxStateIndex, TraceUnsignedBaseType_t uxState)
275 {
276 /* This should never fail */
277 TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
278
279 /* This should never fail */
280 TRC_ASSERT(uxStateIndex < (TraceUnsignedBaseType_t)(TRC_ENTRY_TABLE_STATE_COUNT));
281
282 /* This should never fail */
283 TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle)); /*cstat !MISRAC2004-17.3 !MISRAC2012-Rule-18.3 Suppress pointer comparison check*/
284
285 return TRC_ENTRY_SET_STATE(xEntryHandle, uxStateIndex, uxState);
286 }
287
xTraceEntrySetOptions(const TraceEntryHandle_t xEntryHandle,uint32_t uiMask)288 traceResult xTraceEntrySetOptions(const TraceEntryHandle_t xEntryHandle, uint32_t uiMask)
289 {
290 /* This should never fail */
291 TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
292
293 /* Does not need to be locked. */
294 /* This should never fail */
295 TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle)); /*cstat !MISRAC2004-17.3 !MISRAC2012-Rule-18.3 Suppress pointer comparison check*/
296
297 return TRC_ENTRY_SET_OPTIONS(xEntryHandle, uiMask);
298 }
299
xTraceEntryClearOptions(const TraceEntryHandle_t xEntryHandle,uint32_t uiMask)300 traceResult xTraceEntryClearOptions(const TraceEntryHandle_t xEntryHandle, uint32_t uiMask)
301 {
302 /* This should never fail */
303 TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
304
305 /* Does not need to be locked. */
306 /* This should never fail */
307 TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle)); /*cstat !MISRAC2004-17.3 !MISRAC2012-Rule-18.3 Suppress pointer comparison check*/
308
309 return TRC_ENTRY_CLEAR_OPTIONS(xEntryHandle, uiMask);
310 }
311
xTraceEntryGetAddress(const TraceEntryHandle_t xEntryHandle,void ** ppvAddress)312 traceResult xTraceEntryGetAddress(const TraceEntryHandle_t xEntryHandle, void **ppvAddress)
313 {
314 /* This should never fail */
315 TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
316
317 /* This should never fail */
318 TRC_ASSERT(ppvAddress != (void*)0);
319
320 /* Does not need to be locked. */
321 /* This should never fail */
322 TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle)); /*cstat !MISRAC2004-17.3 !MISRAC2012-Rule-18.3 Suppress pointer comparison check*/
323
324 return TRC_ENTRY_GET_ADDRESS(xEntryHandle, ppvAddress);
325 }
326
327 /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
xTraceEntryGetSymbol(const TraceEntryHandle_t xEntryHandle,const char ** pszSymbol)328 traceResult xTraceEntryGetSymbol(const TraceEntryHandle_t xEntryHandle, const char** pszSymbol)
329 {
330 /* This should never fail */
331 TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
332
333 /* This should never fail */
334 TRC_ASSERT(pszSymbol != (void*)0);
335
336 /* Does not need to be locked. */
337 /* This should never fail */
338 TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle)); /*cstat !MISRAC2004-17.3 !MISRAC2012-Rule-18.3 Suppress pointer comparison check*/
339
340 return TRC_ENTRY_GET_SYMBOL(xEntryHandle, pszSymbol);
341 }
342
xTraceEntryGetState(const TraceEntryHandle_t xEntryHandle,TraceUnsignedBaseType_t uxStateIndex,TraceUnsignedBaseType_t * puxState)343 traceResult xTraceEntryGetState(const TraceEntryHandle_t xEntryHandle, TraceUnsignedBaseType_t uxStateIndex, TraceUnsignedBaseType_t *puxState)
344 {
345 /* This should never fail */
346 TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
347
348 /* This should never fail */
349 TRC_ASSERT(puxState != (void*)0);
350
351 /* This should never fail */
352 TRC_ASSERT(uxStateIndex < (TraceUnsignedBaseType_t)(TRC_ENTRY_TABLE_STATE_COUNT));
353
354 /* Does not need to be locked. */
355 /* This should never fail */
356 TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle)); /*cstat !MISRAC2004-17.3 !MISRAC2012-Rule-18.3 Suppress pointer comparison check*/
357
358 return TRC_ENTRY_GET_STATE(xEntryHandle, uxStateIndex, puxState);
359 }
360
361 /*cstat !MISRAC2012-Rule-8.13 Suppress const check for xEntryHandle*/
xTraceEntryGetStateReturn(const TraceEntryHandle_t xEntryHandle,TraceUnsignedBaseType_t uxStateIndex)362 TraceUnsignedBaseType_t xTraceEntryGetStateReturn(const TraceEntryHandle_t xEntryHandle, TraceUnsignedBaseType_t uxStateIndex)
363 {
364 return TRC_ENTRY_GET_STATE_RETURN(xEntryHandle, uxStateIndex);
365 }
366
xTraceEntryGetOptions(const TraceEntryHandle_t xEntryHandle,uint32_t * puiOptions)367 traceResult xTraceEntryGetOptions(const TraceEntryHandle_t xEntryHandle, uint32_t *puiOptions)
368 {
369 /* This should never fail */
370 TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
371
372 /* This should never fail */
373 TRC_ASSERT(puiOptions != (void*)0);
374
375 /* Does not need to be locked. */
376 /* This should never fail */
377 TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle)); /*cstat !MISRAC2004-17.3 !MISRAC2012-Rule-18.3 Suppress pointer comparison check*/
378
379 return TRC_ENTRY_GET_OPTIONS(xEntryHandle, puiOptions);
380 }
381
382 #endif /* ((TRC_CFG_USE_TRACE_ASSERT) == 1) */
383
384 /* PRIVATE FUNCTIONS */
385
prvEntryIndexInitialize(void)386 static traceResult prvEntryIndexInitialize(void)
387 {
388 uint32_t i;
389
390 for (i = 0u; i < (uint32_t)(TRC_ENTRY_TABLE_SLOTS); i++)
391 {
392 pxIndexTable->axFreeIndexes[i] = (TraceEntryIndex_t)i;
393 }
394
395 pxIndexTable->uiFreeIndexCount = TRC_ENTRY_TABLE_SLOTS;
396
397 return TRC_SUCCESS;
398 }
399
prvEntryIndexTake(TraceEntryIndex_t * pxIndex)400 static traceResult prvEntryIndexTake(TraceEntryIndex_t *pxIndex)
401 {
402 /* Critical Section must be active! */
403 TraceEntryIndex_t xIndex;
404
405 if (pxIndexTable->uiFreeIndexCount == 0u)
406 {
407 return TRC_FAIL;
408 }
409
410 /* Always take the first item */
411 xIndex = pxIndexTable->axFreeIndexes[0];
412 pxIndexTable->uiFreeIndexCount--;
413
414 /* Move the last item to the first slot, to avoid holes */
415 pxIndexTable->axFreeIndexes[0] = pxIndexTable->axFreeIndexes[pxIndexTable->uiFreeIndexCount];
416
417 #if (TRC_ENTRY_TABLE_SLOTS > 256)
418 pxIndexTable->axFreeIndexes[pxIndexTable->uiFreeIndexCount] = UINT16_MAX;
419 #else
420 pxIndexTable->axFreeIndexes[pxIndexTable->uiFreeIndexCount] = UINT8_MAX;
421 #endif
422
423 *pxIndex = xIndex;
424 return TRC_SUCCESS;
425 }
426
427 #endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */
428
429 #endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */
430