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 generic core of the trace recorder's streaming mode.
9 */
10
11 #include <trcRecorder.h>
12
13 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
14
15 #if (TRC_USE_TRACEALYZER_RECORDER == 1)
16
17 #ifndef TRC_KERNEL_PORT_HEAP_INIT
18 #define TRC_KERNEL_PORT_HEAP_INIT(__size)
19 #endif
20
21 /* Entry symbol length maximum check */
22 #if ((TRC_CFG_ENTRY_SYMBOL_MAX_LENGTH) > 28UL)
23 #error Maximum entry symbol length is 28!
24 #endif
25
26 /* Entry symbol length minimum check */
27 #if ((TRC_CFG_ENTRY_SYMBOL_MAX_LENGTH) < 4UL)
28 #error Minimum entry symbol length is 4!
29 #endif
30
31 typedef struct TraceHeader
32 {
33 uint32_t uiPSF;
34 uint16_t uiVersion;
35 uint16_t uiPlatform;
36 uint32_t uiOptions;
37 uint32_t uiNumCores;
38 uint32_t isrTailchainingThreshold;
39 uint16_t uiPlatformCfgPatch;
40 uint8_t uiPlatformCfgMinor;
41 uint8_t uiPlatformCfgMajor;
42 char platformCfg[8];
43 } TraceHeader_t;
44
45 /* The data structure for commands (a bit overkill) */
46 typedef struct TraceCommandType_t
47 {
48 unsigned char cmdCode;
49 unsigned char param1;
50 unsigned char param2;
51 unsigned char param3;
52 unsigned char param4;
53 unsigned char param5;
54 unsigned char checksumLSB;
55 unsigned char checksumMSB;
56 } TraceCommand_t;
57
58 #ifndef TRC_CFG_RECORDER_DATA_INIT
59 #define TRC_CFG_RECORDER_DATA_INIT 1
60 #endif
61
62 /* Used to interpret the data format */
63 #define TRACE_FORMAT_VERSION ((uint16_t)0x000E)
64
65 /* Used to determine endian of data (big/little) */
66 #define TRACE_PSF_ENDIANESS_IDENTIFIER ((uint32_t)0x50534600)
67
68 #if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_STATIC)
69 static TraceRecorderData_t xRecorderData TRC_CFG_RECORDER_DATA_ATTRIBUTE; /*cstat !MISRAC2004-8.7 !MISRAC2012-Rule-8.9_a !MISRAC2012-Rule-8.9_b Suppress global variable check*/
70 TraceRecorderData_t* pxTraceRecorderData TRC_CFG_RECORDER_DATA_ATTRIBUTE;
71 #else
72 /* If using DYNAMIC or CUSTOM allocation */
73 TraceRecorderData_t* pxTraceRecorderData TRC_CFG_RECORDER_DATA_ATTRIBUTE;
74 #endif
75
76 static TraceHeader_t* pxHeader TRC_CFG_RECORDER_DATA_ATTRIBUTE; /*cstat !MISRAC2004-8.7 !MISRAC2012-Rule-8.9_a !MISRAC2012-Rule-8.9_b Suppress global variable check*/
77
78 /*******************************************************************************
79 * RecorderInitialized
80 *
81 * Makes sure the recorder data is only initialized once.
82 *
83 * NOTE: RecorderInitialized is only initialized to 0 if
84 * TRC_CFG_RECORDER_DATA_INIT is non-zero.
85 * This will avoid issues where the recorder must be started before main(),
86 * which can lead to RecorderInitialized be cleared by late initialization after
87 * xTraceEnable(TRC_INIT) was called and assigned RecorderInitialized its'
88 * value.
89 ******************************************************************************/
90 #if (TRC_CFG_RECORDER_DATA_INIT != 0)
91 uint32_t RecorderInitialized = 0u;
92 #else /* (TRC_CFG_RECORDER_DATA_INIT != 0) */
93 uint32_t RecorderInitialized TRC_CFG_RECORDER_DATA_ATTRIBUTE;
94 #endif /* (TRC_CFG_RECORDER_DATA_INIT != 0) */
95
96 #if (TRC_EXTERNAL_BUFFERS == 0)
97 /* Stores the header information on Start */
98 static void prvTraceStoreHeader(void);
99
100 /* Store the Timestamp info */
101 static void prvTraceStoreTimestampInfo(void);
102
103 /* Stores the entry table on Start */
104 static void prvTraceStoreEntryTable(void);
105
106 #else /* (TRC_EXTERNAL_BUFFERS == 0) */
107
108 #define prvTraceStoreHeader()
109 #define prvTraceStoreTimestampInfo()
110 #define prvTraceStoreEntryTable()
111
112 #endif /* (TRC_EXTERNAL_BUFFERS == 0) */
113
114 /* Store start event. */
115 static void prvTraceStoreStartEvent(void);
116
117 /* Checks if the provided command is a valid command */
118 static int32_t prvIsValidCommand(const TraceCommand_t* const cmd);
119
120 /* Executed the received command (Start or Stop) */
121 static void prvProcessCommand(const TraceCommand_t* const cmd);
122
123 /* Internal function for starting the recorder */
124 static void prvSetRecorderEnabled(void);
125
126 /* Internal function for stopping the recorder */
127 static void prvSetRecorderDisabled(void);
128
129 static TraceUnsignedBaseType_t prvIs64bit(void);
130
131 /******************************************************************************
132 * xTraceInitialize
133 *
134 * Initializes the recorder data.
135 * This function will be called by xTraceEnable(...).
136 * Only needs to be called manually if traced objects are created before the
137 * trace recorder can be enabled, at which point make sure to call this function
138 * as early as possible.
139 * See TRC_CFG_RECORDER_DATA_INIT in trcConfig.h.
140 ******************************************************************************/
xTraceInitialize(void)141 traceResult xTraceInitialize(void)
142 {
143 TraceUnsignedBaseType_t i;
144 TRC_ASSERT_EQUAL_SIZE(TraceUnsignedBaseType_t, TraceBaseType_t);
145
146 /* TraceUnsignedBaseType_t is used to store handles (addresses) */
147 TRC_ASSERT_EQUAL_SIZE(TraceUnsignedBaseType_t, TraceHandleBaseType_t);
148
149 if (RecorderInitialized != 0u)
150 {
151 return TRC_SUCCESS;
152 }
153
154 TRC_PORT_SPECIFIC_INIT();
155 #if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_STATIC)
156 pxTraceRecorderData = &xRecorderData;
157 #elif (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_DYNAMIC)
158 /* Initialize heap */
159 TRC_KERNEL_PORT_HEAP_INIT(sizeof(TraceRecorderData_t));
160
161 /* Allocate data */
162 pxTraceRecorderData = TRC_KERNEL_PORT_HEAP_MALLOC(sizeof(TraceRecorderData_t));
163 #endif
164
165 /* These are set on init so they aren't overwritten by late initialization values. */
166 pxTraceRecorderData->uiSessionCounter = 0u;
167 pxTraceRecorderData->uiRecorderEnabled = 0u;
168
169 for (i = 0; i < TRC_CFG_CORE_COUNT; i++)
170 {
171 pxTraceRecorderData->uxTraceSystemStates[i] = (TraceUnsignedBaseType_t)TRC_STATE_IN_STARTUP;
172 }
173
174 /*cstat !MISRAC2004-13.7_b Suppress always false check*/
175 if (xTraceEntryIndexTableInitialize(&pxTraceRecorderData->xEntryIndexTableBuffer) == TRC_FAIL)
176 {
177 return TRC_FAIL;
178 }
179
180 #if (TRC_EXTERNAL_BUFFERS == 0)
181 if (xTraceHeaderInitialize(&pxTraceRecorderData->xHeaderBuffer) == TRC_FAIL)
182 {
183 return TRC_FAIL;
184 }
185
186 if (xTraceEntryTableInitialize(&pxTraceRecorderData->xEntryTable) == TRC_FAIL)
187 {
188 return TRC_FAIL;
189 }
190
191 if (xTraceTimestampInitialize(&pxTraceRecorderData->xTimestampBuffer) == TRC_FAIL)
192 {
193 return TRC_FAIL;
194 }
195 #endif
196
197 if (xTraceCounterInitialize(&pxTraceRecorderData->xCounterBuffer) == TRC_FAIL)
198 {
199 return TRC_FAIL;
200 }
201
202 /*cstat !MISRAC2004-13.7_b !MISRAC2012-Rule-14.3_b Suppress always false check*/
203 if (xTraceStackMonitorInitialize(&pxTraceRecorderData->xStackMonitorBuffer) == TRC_FAIL)
204 {
205 return TRC_FAIL;
206 }
207
208 /*cstat !MISRAC2004-13.7_b !MISRAC2012-Rule-14.3_b Suppress always false check*/
209 if (xTraceStreamPortInitialize(&pxTraceRecorderData->xStreamPortBuffer) == TRC_FAIL)
210 {
211 return TRC_FAIL;
212 }
213
214 if (xTraceAssertInitialize(&pxTraceRecorderData->xAssertBuffer) == TRC_FAIL)
215 {
216 return TRC_FAIL;
217 }
218
219 if (xTraceDiagnosticsInitialize(&pxTraceRecorderData->xDiagnosticsBuffer) == TRC_FAIL)
220 {
221 return TRC_FAIL;
222 }
223
224 /*cstat !MISRAC2004-13.7_b Suppress always false check*/
225 if (xTraceExtensionInitialize(&pxTraceRecorderData->xExtensionBuffer) == TRC_FAIL)
226 {
227 return TRC_FAIL;
228 }
229
230 if (xTraceStaticBufferInitialize(&pxTraceRecorderData->xStaticBufferBuffer) == TRC_FAIL)
231 {
232 return TRC_FAIL;
233 }
234
235 if (xTraceEventInitialize(&pxTraceRecorderData->xEventDataBuffer) == TRC_FAIL)
236 {
237 return TRC_FAIL;
238 }
239
240 if (xTracePrintInitialize(&pxTraceRecorderData->xPrintBuffer) == TRC_FAIL)
241 {
242 return TRC_FAIL;
243 }
244
245 if (xTraceErrorInitialize(&pxTraceRecorderData->xErrorBuffer) == TRC_FAIL)
246 {
247 return TRC_FAIL;
248 }
249
250 if (xTraceISRInitialize(&pxTraceRecorderData->xISRBuffer) == TRC_FAIL)
251 {
252 return TRC_FAIL;
253 }
254
255 if (xTraceTaskInitialize(&pxTraceRecorderData->xTaskInfoBuffer) == TRC_FAIL)
256 {
257 return TRC_FAIL;
258 }
259
260 /*cstat !MISRAC2004-13.7_b !MISRAC2012-Rule-14.3_b Suppress always false check*/
261 if (xTraceKernelPortInitialize(&pxTraceRecorderData->xKernelPortBuffer) == TRC_FAIL)
262 {
263 return TRC_FAIL;
264 }
265
266 pxTraceRecorderData->reserved = 0xFFFFFFFFUL;
267
268 xTraceSetComponentInitialized(TRC_RECORDER_COMPONENT_CORE);
269
270 return TRC_SUCCESS;
271 }
272
273 /* Do this in function to avoid unreachable code warnings */
prvVerifySizeAlignment(uint32_t ulSize)274 traceResult prvVerifySizeAlignment(uint32_t ulSize)
275 {
276 return (ulSize % sizeof(TraceUnsignedBaseType_t)) == 0 ? TRC_SUCCESS : TRC_FAIL;
277 }
278
xTraceHeaderInitialize(TraceHeaderBuffer_t * pxBuffer)279 traceResult xTraceHeaderInitialize(TraceHeaderBuffer_t *pxBuffer)
280 {
281 uint32_t i;
282 const char* platform_cfg = TRC_PLATFORM_CFG; /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
283
284 TRC_ASSERT_EQUAL_SIZE(TraceHeaderBuffer_t, TraceHeader_t);
285
286 if (pxBuffer == (void*)0)
287 {
288 return TRC_FAIL;
289 }
290
291 if (prvVerifySizeAlignment(sizeof(TraceStreamPortBuffer_t)) == TRC_FAIL)
292 {
293 /* TraceStreamPortBuffer_t size is not aligned to TraceUnsignedBaseType_t */
294 return TRC_FAIL;
295 }
296
297 if (prvVerifySizeAlignment(sizeof(TraceEventDataTable_t)) == TRC_FAIL)
298 {
299 /* TraceEventDataTable_t size is not aligned to TraceUnsignedBaseType_t */
300 return TRC_FAIL;
301 }
302
303 if (prvVerifySizeAlignment(sizeof(TraceKernelPortDataBuffer_t)) == TRC_FAIL)
304 {
305 /* TraceKernelPortDataBuffer_t size is not aligned to TraceUnsignedBaseType_t */
306 return TRC_FAIL;
307 }
308
309 pxHeader = (TraceHeader_t*)pxBuffer; /*cstat !MISRAC2004-11.4 !MISRAC2012-Rule-11.3 Suppress conversion between pointer types checks*/
310
311 pxHeader->uiPSF = TRACE_PSF_ENDIANESS_IDENTIFIER;
312 pxHeader->uiVersion = TRACE_FORMAT_VERSION;
313 pxHeader->uiPlatform = TRACE_KERNEL_VERSION;
314
315 for (i = 0u; i < (uint32_t)(TRC_PLATFORM_CFG_LENGTH); i++)
316 {
317 pxHeader->platformCfg[i] = platform_cfg[i]; /*cstat !MISRAC2004-17.4_b We need to access every character in the string*/
318 if (platform_cfg[i] == (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*/
319 {
320 break;
321 }
322 }
323 pxHeader->uiPlatformCfgPatch = (uint16_t)TRC_PLATFORM_CFG_PATCH;
324 pxHeader->uiPlatformCfgMinor = (uint8_t)TRC_PLATFORM_CFG_MINOR;
325 pxHeader->uiPlatformCfgMajor = (uint8_t)TRC_PLATFORM_CFG_MAJOR;
326 pxHeader->uiNumCores = (uint32_t)TRC_CFG_CORE_COUNT;
327
328 #ifdef TRC_STREAM_PORT_MULTISTREAM_SUPPORT
329 pxHeader->uiNumCores |= 2 << 8;
330 #else
331 pxHeader->uiNumCores |= 3 << 8;
332 #endif
333
334 pxHeader->isrTailchainingThreshold = TRC_CFG_ISR_TAILCHAINING_THRESHOLD;
335
336 /* Lowest bit used for TRC_IRQ_PRIORITY_ORDER */
337 pxHeader->uiOptions = (((uint32_t)(TRC_IRQ_PRIORITY_ORDER)) << 0);
338
339 /* 3rd bit used for TRC_CFG_TEST_MODE */
340 pxHeader->uiOptions |= (((uint32_t)(TRC_CFG_TEST_MODE)) << 2);
341
342 /* 4th bit used for 64-bit*/
343 if (prvIs64bit()) /* Call helper function to avoid "unreachable code" */
344 {
345 pxHeader->uiOptions |= (1 << 3);
346 }
347
348 return TRC_SUCCESS;
349 }
350
xTraceEnable(uint32_t uiStartOption)351 traceResult xTraceEnable(uint32_t uiStartOption)
352 {
353 TraceCommand_t xCommand = { 0 };
354 int32_t iBytes;
355
356 if (xTraceInitialize() == TRC_FAIL)
357 {
358 return TRC_FAIL;
359 }
360
361 /*cstat !MISRAC2004-13.7_b !MISRAC2012-Rule-14.3_b Suppress always false check*/
362 if (xTraceStreamPortOnEnable(uiStartOption) == TRC_FAIL)
363 {
364 return TRC_FAIL;
365 }
366
367 /*cstat !MISRAC2004-13.7_b !MISRAC2012-Rule-14.3_b Suppress always false check*/
368 if (xTraceKernelPortEnable() == TRC_FAIL)
369 {
370 return TRC_FAIL;
371 }
372
373 if (uiStartOption == TRC_START_AWAIT_HOST)
374 {
375 /* We keep trying to read commands from host until the recorder has been started */
376 do
377 {
378 iBytes = 0;
379
380 if (xTraceStreamPortReadData(&xCommand, sizeof(TraceCommand_t), (int32_t*)&iBytes) == TRC_FAIL)
381 {
382 (void)xTraceWarning(TRC_WARNING_STREAM_PORT_READ);
383 }
384
385 if ((uint32_t)iBytes == sizeof(TraceCommand_t))
386 {
387 if (prvIsValidCommand(&xCommand) != 0)
388 {
389 prvProcessCommand(&xCommand);
390 }
391 }
392 } while (pxTraceRecorderData->uiRecorderEnabled == 0u);
393 }
394 else if (uiStartOption == (uint32_t)(TRC_START))
395 {
396 /* We start streaming directly - this assumes that the host interface is ready! */
397 xCommand.cmdCode = CMD_SET_ACTIVE;
398 xCommand.param1 = 1u;
399 prvProcessCommand(&xCommand);
400 }
401 else if (uiStartOption == TRC_START_FROM_HOST)
402 {
403 /* We prepare the system to receive commands from host, but let system resume execution until that happens */
404 }
405 else
406 {
407 return TRC_FAIL;
408 }
409
410 return TRC_SUCCESS;
411 }
412
xTraceDisable(void)413 traceResult xTraceDisable(void)
414 {
415 prvSetRecorderDisabled();
416
417 (void)xTraceStreamPortOnDisable();
418
419 return TRC_SUCCESS;
420 }
421
422 #if (TRC_CFG_RECORDER_BUFFER_ALLOCATION == TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM)
xTraceSetBuffer(TraceRecorderData_t * pxBuffer)423 traceResult xTraceSetBuffer(TraceRecorderData_t* pxBuffer)
424 {
425 if (pxBuffer == 0)
426 {
427 return TRC_FAIL;
428 }
429
430 pxTraceRecorderData = pxBuffer;
431
432 return TRC_SUCCESS;
433 }
434 #endif
435
xTraceGetEventBuffer(void ** ppvBuffer,TraceUnsignedBaseType_t * puiSize)436 traceResult xTraceGetEventBuffer(void **ppvBuffer, TraceUnsignedBaseType_t *puiSize)
437 {
438 if ((pxTraceRecorderData == (void*)0) || (ppvBuffer == (void*)0) || (puiSize == (void*)0))
439 {
440 return TRC_FAIL;
441 }
442
443 /* Returns the xStreamPortBuffer since that is the one containing trace data */
444 *ppvBuffer = (void*)&pxTraceRecorderData->xStreamPortBuffer;
445 *puiSize = sizeof(pxTraceRecorderData->xStreamPortBuffer);
446
447 return TRC_SUCCESS;
448 }
449
xTraceTzCtrl(void)450 traceResult xTraceTzCtrl(void)
451 {
452 TraceCommand_t xCommand = { 0 };
453 int32_t iRxBytes;
454
455 do
456 {
457 /* Listen for new commands */
458 iRxBytes = 0;
459 if (xTraceStreamPortReadData(&xCommand, sizeof(TraceCommand_t), &iRxBytes) == TRC_FAIL)
460 {
461 /* The connection has failed, stop tracing */
462 (void)xTraceDisable();
463
464 return TRC_FAIL;
465 }
466
467 if ((uint32_t)iRxBytes == sizeof(TraceCommand_t))
468 {
469 if (prvIsValidCommand(&xCommand) != 0)
470 {
471 prvProcessCommand(&xCommand); /* Start or Stop currently... */
472 }
473 }
474
475 if (xTraceIsRecorderEnabled())
476 {
477 xTraceInternalEventBufferTransfer();
478 }
479
480 /* If there was data sent or received (bytes != 0), loop around and repeat, if there is more data to send or receive.
481 Otherwise, step out of this loop and sleep for a while. */
482
483 } while (iRxBytes > 0);
484
485 if (xTraceIsRecorderEnabled())
486 {
487 (void)xTraceDiagnosticsCheckStatus();
488 (void)xTraceStackMonitorReport();
489 }
490
491 return TRC_SUCCESS;
492 }
493
vTraceSetFilterGroup(uint16_t filterGroup)494 void vTraceSetFilterGroup(uint16_t filterGroup)
495 {
496 (void)filterGroup;
497 }
498
vTraceSetFilterMask(uint16_t filterMask)499 void vTraceSetFilterMask(uint16_t filterMask)
500 {
501 (void)filterMask;
502 }
503
504 /******************************************************************************/
505 /*** INTERNAL FUNCTIONS *******************************************************/
506 /******************************************************************************/
507
prvIs64bit(void)508 static TraceUnsignedBaseType_t prvIs64bit(void)
509 {
510 return sizeof(TraceUnsignedBaseType_t) == 8;
511 }
512
513 /* Internal function for starting/stopping the recorder. */
prvSetRecorderEnabled(void)514 static void prvSetRecorderEnabled(void)
515 {
516 TraceUnsignedBaseType_t uxTimestampFrequency = 0u;
517 uint32_t uiTimestampPeriod = 0u;
518
519 TRACE_ALLOC_CRITICAL_SECTION();
520
521 if (pxTraceRecorderData->uiRecorderEnabled == 1u)
522 {
523 return;
524 }
525
526 (void)xTraceTimestampGetFrequency(&uxTimestampFrequency);
527 /* If not overridden using xTraceTimestampSetFrequency(...), use default value */
528 if (uxTimestampFrequency == 0u)
529 {
530 (void)xTraceTimestampSetFrequency((TraceUnsignedBaseType_t)(TRC_HWTC_FREQ_HZ));
531 }
532
533 (void)xTraceTimestampGetPeriod(&uiTimestampPeriod);
534 /* If not overridden using xTraceTimestampSetPeriod(...), use default value */
535 if (uiTimestampPeriod == 0u)
536 {
537 (void)xTraceTimestampSetPeriod((TraceUnsignedBaseType_t)(TRC_HWTC_PERIOD));
538 }
539
540 TRACE_ENTER_CRITICAL_SECTION();
541
542 /* If the internal event buffer is used, we must clear it */
543 (void)xTraceInternalEventBufferClear();
544
545 (void)xTraceStreamPortOnTraceBegin();
546
547 prvTraceStoreHeader();
548 prvTraceStoreTimestampInfo();
549 prvTraceStoreEntryTable();
550 prvTraceStoreStartEvent();
551
552 pxTraceRecorderData->uiSessionCounter++;
553
554 pxTraceRecorderData->uiRecorderEnabled = 1u;
555
556 TRACE_EXIT_CRITICAL_SECTION();
557 }
558
prvSetRecorderDisabled(void)559 static void prvSetRecorderDisabled(void)
560 {
561 TRACE_ALLOC_CRITICAL_SECTION();
562
563 if (pxTraceRecorderData->uiRecorderEnabled == 0u)
564 {
565 return;
566 }
567
568 TRACE_ENTER_CRITICAL_SECTION();
569
570 pxTraceRecorderData->uiRecorderEnabled = 0u;
571
572 (void)xTraceStreamPortOnTraceEnd();
573
574 TRACE_EXIT_CRITICAL_SECTION();
575 }
576
577 #if (TRC_EXTERNAL_BUFFERS == 0)
578 /* Stores the header information on Start */
prvTraceStoreHeader(void)579 static void prvTraceStoreHeader(void)
580 {
581 TraceEventHandle_t xEventHandle;
582
583 if (xTraceEventBeginRawOfflineBlocking(sizeof(TraceHeader_t), &xEventHandle) == TRC_SUCCESS)
584 {
585 xTraceEventAddData(xEventHandle, (TraceUnsignedBaseType_t*)pxHeader, sizeof(TraceHeader_t) / sizeof(TraceUnsignedBaseType_t));
586 xTraceEventEndOfflineBlocking(xEventHandle);
587 }
588 }
589
590 /* Store the Timestamp */
prvTraceStoreTimestampInfo(void)591 static void prvTraceStoreTimestampInfo(void)
592 {
593 TraceEventHandle_t xEventHandle;
594
595 if (xTraceEventBeginRawOfflineBlocking(sizeof(TraceTimestampData_t), &xEventHandle) == TRC_SUCCESS)
596 {
597 xTraceEventAddData(xEventHandle, (TraceUnsignedBaseType_t*)&pxTraceRecorderData->xTimestampBuffer, sizeof(TraceTimestampData_t) / sizeof(TraceUnsignedBaseType_t));
598 xTraceEventEndOfflineBlocking(xEventHandle);
599 }
600 }
601
602 /* Stores the entry table on Start */
prvTraceStoreEntryTable(void)603 static void prvTraceStoreEntryTable(void)
604 {
605 uint32_t i = 0;
606 TraceEventHandle_t xEventHandle;
607 TraceEntryHandle_t xEntryHandle;
608 uint32_t uiEntryCount;
609 void *pvEntryAddress;
610
611 (void)xTraceEntryGetCount(&uiEntryCount);
612
613 if (xTraceEventBeginRawOfflineBlocking(sizeof(TraceUnsignedBaseType_t) + sizeof(TraceUnsignedBaseType_t) + sizeof(TraceUnsignedBaseType_t), &xEventHandle) == TRC_SUCCESS)
614 {
615 (void)xTraceEventAddUnsignedBaseType(xEventHandle, (TraceUnsignedBaseType_t)uiEntryCount);
616 (void)xTraceEventAddUnsignedBaseType(xEventHandle, TRC_ENTRY_TABLE_SLOT_SYMBOL_SIZE);
617 (void)xTraceEventAddUnsignedBaseType(xEventHandle, TRC_ENTRY_TABLE_STATE_COUNT);
618 (void)xTraceEventEndOfflineBlocking(xEventHandle);
619 }
620
621 for (i = 0; i < (TRC_ENTRY_TABLE_SLOTS); i++)
622 {
623 (void)xTraceEntryGetAtIndex(i, &xEntryHandle);
624 (void)xTraceEntryGetAddress(xEntryHandle, &pvEntryAddress);
625 /* We only send used entry slots */
626 if (pvEntryAddress != 0)
627 {
628 /* Send entry */
629 if (xTraceEventBeginRawOfflineBlocking(sizeof(TraceEntry_t), &xEventHandle) == TRC_SUCCESS)
630 {
631 (void)xTraceEventAddData(xEventHandle, (TraceUnsignedBaseType_t*)xEntryHandle, sizeof(TraceEntry_t) / sizeof(TraceUnsignedBaseType_t));
632 (void)xTraceEventEndOfflineBlocking(xEventHandle);
633 }
634 }
635 }
636 }
637 #endif /* (TRC_EXTERNAL_BUFFERS == 0) */
638
prvTraceStoreStartEvent(void)639 static void prvTraceStoreStartEvent(void)
640 {
641 TraceEventHandle_t xEventHandle = 0;
642 void* pvCurrentTask = (void*)0;
643 uint32_t i;
644
645 if (xTraceEventBeginOffline(PSF_EVENT_TRACE_START, sizeof(TraceUnsignedBaseType_t) * (TRC_CFG_CORE_COUNT), &xEventHandle) == TRC_SUCCESS)
646 {
647 for (i = 0; i < (TRC_CFG_CORE_COUNT); i++)
648 {
649
650 (void)xTraceTaskGetCurrentOnCore(i, &pvCurrentTask);
651 (void)xTraceEventAddUnsignedBaseType(xEventHandle, (TraceUnsignedBaseType_t)pvCurrentTask); /*cstat !MISRAC2004-11.3 !MISRAC2012-Rule-11.4 !MISRAC2012-Rule-11.6 Suppress conversion from pointer to integer check*/
652 }
653 (void)xTraceEventEndOffline(xEventHandle);
654 }
655 }
656
657 /* Checks if the provided command is a valid command */
prvIsValidCommand(const TraceCommand_t * const cmd)658 static int32_t prvIsValidCommand(const TraceCommand_t* const cmd)
659 {
660 uint16_t checksum = (uint16_t)0xFFFFU - (uint16_t)(unsigned char)(cmd->cmdCode + /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
661 cmd->param1 +
662 cmd->param2 +
663 cmd->param3 +
664 cmd->param4 +
665 cmd->param5);
666
667 if (cmd->checksumMSB != (unsigned char)(checksum >> 8)) /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
668 {
669 return 0;
670 }
671
672 if (cmd->checksumLSB != (unsigned char)(checksum & 0xFFU)) /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
673 {
674 return 0;
675 }
676
677 if (cmd->cmdCode > (unsigned char)(CMD_LAST_COMMAND)) /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
678 {
679 return 0;
680 }
681
682 return 1;
683 }
684
685 /* Executed the received command (Start or Stop) */
prvProcessCommand(const TraceCommand_t * const cmd)686 static void prvProcessCommand(const TraceCommand_t* const cmd)
687 {
688 switch(cmd->cmdCode)
689 {
690 case CMD_SET_ACTIVE:
691 if (cmd->param1 == 1u)
692 {
693 prvSetRecorderEnabled();
694 }
695 else
696 {
697 prvSetRecorderDisabled();
698 }
699 break;
700 default:
701 break;
702 }
703 }
704
705 #endif
706
707 #endif
708