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