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