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