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