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 FreeRTOS specific parts of the trace recorder
9  */
10 
11 #include <FreeRTOS.h>
12 #include <trcRecorder.h>
13 
14 #if (!defined(TRC_USE_TRACEALYZER_RECORDER) && configUSE_TRACE_FACILITY == 1)
15 
16 #error Trace Recorder: You need to include trcRecorder.h at the end of your FreeRTOSConfig.h!
17 
18 #endif
19 
20 #if (defined(TRC_USE_TRACEALYZER_RECORDER) && TRC_USE_TRACEALYZER_RECORDER == 1)
21 
22 #ifndef TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS
23 
24 /* TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS is missing in trcConfig.h. */
25 #error "TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS must be defined in trcConfig.h."
26 
27 #endif
28 
29 #ifndef TRC_CFG_INCLUDE_TIMER_EVENTS
30 
31 /* TRC_CFG_INCLUDE_TIMER_EVENTS is missing in trcConfig.h. */
32 #error "TRC_CFG_INCLUDE_TIMER_EVENTS must be defined in trcConfig.h."
33 
34 #endif
35 
36 #ifndef TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS
37 
38 /* TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS is missing in trcConfig.h. */
39 #error "TRC_CFG_INCLUDE_PEND_FUNC_CALL_EVENTS must be defined in trcConfig.h."
40 
41 #endif
42 
43 #ifndef TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS
44 
45 /* TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS is missing in trcConfig.h. Define this as 1 if using FreeRTOS v10 or later and like to trace stream buffer or message buffer events, otherwise 0. */
46 #error "TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS must be defined in trcConfig.h."
47 
48 #endif
49 
50 #if (configUSE_TICKLESS_IDLE != 0 && (TRC_HWTC_TYPE == TRC_OS_TIMER_INCR || TRC_HWTC_TYPE == TRC_OS_TIMER_DECR))
51 /*
52 	The below error message is to alert you on the following issue:
53 
54 	The hardware port selected in trcConfig.h uses the operating system timer for the
55 	timestamping, i.e., the periodic interrupt timer that drives the OS tick interrupt.
56 
57 	When using "tickless idle" mode, the recorder needs an independent time source in
58 	order to correctly record the durations of the idle times. Otherwise, the trace may appear
59 	to have a different length than in reality, and the reported CPU load is also affected.
60 
61 	You may override this warning by defining the TRC_CFG_ACKNOWLEDGE_TICKLESS_IDLE_WARNING
62 	macro in your trcConfig.h file. But then the time scale may be incorrect during
63 	tickless idle periods.
64 
65 	To get this correct, override the default timestamping by setting TRC_CFG_HARDWARE_PORT
66 	in trcConfig.h to TRC_HARDWARE_PORT_APPLICATION_DEFINED and define the HWTC macros
67 	accordingly, using a free running counter or an independent periodic interrupt timer.
68 	See trcHardwarePort.h for details.
69 
70 	For ARM Cortex-M3, M4 and M7 MCUs this is not an issue, since the recorder uses the
71 	DWT cycle counter for timestamping in these cases.
72 */
73 
74 #ifndef TRC_CFG_ACKNOWLEDGE_TICKLESS_IDLE_WARNING
75 #error Trace Recorder: This timestamping mode is not recommended with Tickless Idle.
76 #endif
77 
78 #endif
79 
80 #include <task.h>
81 #include <queue.h>
82 
83 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) || (defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0))
84 
85 #if defined(configSUPPORT_STATIC_ALLOCATION) && (configSUPPORT_STATIC_ALLOCATION == 1)
86 
87 #if (TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_9_0_0)
88 
89 static StackType_t stackTzCtrl[TRC_CFG_CTRL_TASK_STACK_SIZE];
90 static StaticTask_t tcbTzCtrl;
91 
92 #else
93 
94 #error "configSUPPORT_STATIC_ALLOCATION not supported before FreeRTOS v9"
95 
96 #endif
97 
98 #endif
99 
100 /* The TzCtrl task - receives commands from Tracealyzer (start/stop) */
101 static portTASK_FUNCTION(TzCtrl, pvParameters);
102 
103 #endif
104 
105 #if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X)
106 
107 /* If the project does not include the FreeRTOS timers, TRC_CFG_INCLUDE_TIMER_EVENTS must be set to 0 */
108 #include <timers.h>
109 
110 #endif
111 
112 #if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X)
113 
114 /* If the project does not include the FreeRTOS event groups, TRC_CFG_INCLUDE_TIMER_EVENTS must be set to 0 */
115 #include <event_groups.h>
116 
117 #endif
118 
119 #if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
120 
121 /* If the project does not include the FreeRTOS stream buffers, TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS must be set to 0 */
122 #include <stream_buffer.h>
123 
124 #endif
125 
126 #if (TRC_CFG_ACKNOWLEDGE_QUEUE_SET_SEND != TRC_ACKNOWLEDGED) && (TRC_CFG_FREERTOS_VERSION == TRC_FREERTOS_VERSION_10_3_0 || TRC_CFG_FREERTOS_VERSION == TRC_FREERTOS_VERSION_10_3_1) && (configUSE_QUEUE_SETS == 1)
127 
128 #error "When using FreeRTOS v10.3.0 or v10.3.1, please make sure that the trace point in prvNotifyQueueSetContainer() in queue.c is renamed from traceQUEUE_SEND to traceQUEUE_SET_SEND in order to tell them apart from other traceQUEUE_SEND trace points. Then set TRC_CFG_ACKNOWLEDGE_QUEUE_SET_SEND in trcConfig.h to TRC_ACKNOWLEDGED to get rid of this error."
129 
130 #endif
131 
132 #if defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0)
133 
xTraceKernelPortGetUnusedStack(void * pvTask,TraceUnsignedBaseType_t * puxUnusedStack)134 traceResult xTraceKernelPortGetUnusedStack(void* pvTask, TraceUnsignedBaseType_t* puxUnusedStack)
135 {
136 	*puxUnusedStack = uxTaskGetStackHighWaterMark(pvTask);
137 
138 	return TRC_SUCCESS;
139 }
140 
141 #endif
142 
xTraceKernelPortDelay(uint32_t uiTicks)143 traceResult xTraceKernelPortDelay(uint32_t uiTicks)
144 {
145 	vTaskDelay(uiTicks);
146 
147 	return TRC_SUCCESS;
148 }
149 
xTraceKernelPortIsSchedulerSuspended(void)150 unsigned char xTraceKernelPortIsSchedulerSuspended(void)
151 {
152 	/* Assumed to be available in FreeRTOS. According to the FreeRTOS docs,
153 	INCLUDE_xTaskGetSchedulerState or configUSE_TIMERS must be set to 1 in
154 	FreeRTOSConfig.h for this function to be available. */
155 
156 	return xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED;
157 }
158 
159 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
160 
161 typedef struct TraceKernelPortData
162 {
163 	TraceHeapHandle_t xSystemHeapHandle;
164 	TraceKernelPortTaskHandle_t xTzCtrlHandle;
165 } TraceKernelPortData_t;
166 
167 static TraceKernelPortData_t* pxKernelPortData;
168 
169 #define TRC_PORT_MALLOC(size) pvPortMalloc(size)
170 
xTraceKernelPortInitialize(TraceKernelPortDataBuffer_t * pxBuffer)171 traceResult xTraceKernelPortInitialize(TraceKernelPortDataBuffer_t* pxBuffer)
172 {
173 	TRC_ASSERT_EQUAL_SIZE(TraceKernelPortDataBuffer_t, TraceKernelPortData_t);
174 
175 	if (pxBuffer == 0)
176 	{
177 		return TRC_FAIL;
178 	}
179 
180 	pxKernelPortData = (TraceKernelPortData_t*)pxBuffer;
181 
182 	pxKernelPortData->xSystemHeapHandle = 0;
183 	pxKernelPortData->xTzCtrlHandle = 0;
184 
185 	return TRC_SUCCESS;
186 }
187 
xTraceKernelPortEnable(void)188 traceResult xTraceKernelPortEnable(void)
189 {
190 	if (pxKernelPortData->xSystemHeapHandle == 0)
191 	{
192 		xTraceHeapCreate("System Heap", 0, 0, configTOTAL_HEAP_SIZE, &pxKernelPortData->xSystemHeapHandle);
193 	}
194 
195 	if (pxKernelPortData->xTzCtrlHandle == 0)
196 	{
197 		/* Creates the TzCtrl task - receives trace commands (start, stop, ...) */
198 #if defined(configSUPPORT_STATIC_ALLOCATION) && (configSUPPORT_STATIC_ALLOCATION == 1)
199 		pxKernelPortData->xTzCtrlHandle = xTaskCreateStatic(TzCtrl, STRING_CAST("TzCtrl"), TRC_CFG_CTRL_TASK_STACK_SIZE, 0, TRC_CFG_CTRL_TASK_PRIORITY, stackTzCtrl, &tcbTzCtrl);
200 #else
201 		xTaskCreate(TzCtrl, STRING_CAST("TzCtrl"), TRC_CFG_CTRL_TASK_STACK_SIZE, 0, TRC_CFG_CTRL_TASK_PRIORITY, &pxKernelPortData->xTzCtrlHandle);
202 #endif
203 
204 		if (pxKernelPortData->xTzCtrlHandle == 0)
205 		{
206 			xTraceError(TRC_ERROR_TZCTRLTASK_NOT_CREATED);
207 
208 			return TRC_FAIL;
209 		}
210 	}
211 
212 	return TRC_SUCCESS;
213 }
214 
portTASK_FUNCTION(TzCtrl,pvParameters)215 static portTASK_FUNCTION(TzCtrl, pvParameters)
216 {
217 	(void)pvParameters;
218 
219 	while (1)
220 	{
221 		xTraceTzCtrl();
222 
223 		vTaskDelay(TRC_CFG_CTRL_TASK_DELAY);
224 	}
225 }
226 
227 #if (TRC_CFG_SCHEDULING_ONLY == 0)
228 
vTraceSetQueueName(void * pvQueue,const char * szName)229 void vTraceSetQueueName(void* pvQueue, const char* szName)
230 {
231 	xTraceObjectSetNameWithoutHandle(pvQueue, szName);
232 }
233 
vTraceSetSemaphoreName(void * pvSemaphore,const char * szName)234 void vTraceSetSemaphoreName(void* pvSemaphore, const char* szName)
235 {
236 	xTraceObjectSetNameWithoutHandle(pvSemaphore, szName);
237 }
238 
vTraceSetMutexName(void * pvMutex,const char * szName)239 void vTraceSetMutexName(void* pvMutex, const char* szName)
240 {
241 	xTraceObjectSetNameWithoutHandle(pvMutex, szName);
242 }
243 
244 #if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X)
245 
vTraceSetEventGroupName(void * pvEventGroup,const char * szName)246 void vTraceSetEventGroupName(void* pvEventGroup, const char* szName)
247 {
248 	xTraceObjectSetNameWithoutHandle(pvEventGroup, szName);
249 }
250 
251 #endif
252 
253 #if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
254 
vTraceSetStreamBufferName(void * pvStreamBuffer,const char * szName)255 void vTraceSetStreamBufferName(void* pvStreamBuffer, const char* szName)
256 {
257 	xTraceObjectSetNameWithoutHandle(pvStreamBuffer, szName);
258 }
259 
vTraceSetMessageBufferName(void * pvMessageBuffer,const char * szName)260 void vTraceSetMessageBufferName(void* pvMessageBuffer, const char* szName)
261 {
262 	xTraceObjectSetNameWithoutHandle(pvMessageBuffer, szName);
263 }
264 
265 #endif
266 
267 #endif
268 
xTraceKernelPortGetSystemHeapHandle(void)269 TraceHeapHandle_t xTraceKernelPortGetSystemHeapHandle(void)
270 {
271 	return pxKernelPortData->xSystemHeapHandle;
272 }
273 
274 #endif
275 
276 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)
277 
278 uint32_t prvTraceGetQueueNumber(void* handle);
279 
280 #if (TRC_CFG_FREERTOS_VERSION < TRC_FREERTOS_VERSION_8_X_X)
281 
282 extern unsigned char ucQueueGetQueueNumber(xQueueHandle pxQueue);
283 extern void vQueueSetQueueNumber(xQueueHandle pxQueue, unsigned char ucQueueNumber);
284 extern unsigned char ucQueueGetQueueType(xQueueHandle pxQueue);
285 
prvTraceGetQueueNumber(void * handle)286 uint32_t prvTraceGetQueueNumber(void* handle)
287 {
288 	return (uint32_t)ucQueueGetQueueNumber(handle);
289 }
290 
291 #else
292 
prvTraceGetQueueNumber(void * handle)293 uint32_t prvTraceGetQueueNumber(void* handle)
294 {
295 	return (uint32_t)uxQueueGetQueueNumber(handle);
296 }
297 
298 #endif
299 
prvTraceGetQueueType(void * pvQueue)300 uint8_t prvTraceGetQueueType(void* pvQueue)
301 {
302 	// This is either declared in header file in FreeRTOS 8 and later, or as extern above
303 	return ucQueueGetQueueType(pvQueue);
304 }
305 
306 /* Tasks */
prvTraceGetTaskNumberLow16(void * pvTask)307 uint16_t prvTraceGetTaskNumberLow16(void* pvTask)
308 {
309 	return TRACE_GET_LOW16(uxTaskGetTaskNumber(pvTask));
310 }
311 
prvTraceGetTaskNumberHigh16(void * pvTask)312 uint16_t prvTraceGetTaskNumberHigh16(void* pvTask)
313 {
314 	return TRACE_GET_HIGH16(uxTaskGetTaskNumber(pvTask));
315 }
316 
prvTraceSetTaskNumberLow16(void * pvTask,uint16_t uiValue)317 void prvTraceSetTaskNumberLow16(void* pvTask, uint16_t uiValue)
318 {
319 	vTaskSetTaskNumber(pvTask, TRACE_SET_LOW16(uxTaskGetTaskNumber(pvTask), uiValue));
320 }
321 
prvTraceSetTaskNumberHigh16(void * pvTask,uint16_t uiValue)322 void prvTraceSetTaskNumberHigh16(void* pvTask, uint16_t uiValue)
323 {
324 	vTaskSetTaskNumber(pvTask, TRACE_SET_HIGH16(uxTaskGetTaskNumber(pvTask), uiValue));
325 }
326 
prvTraceGetQueueNumberLow16(void * pvQueue)327 uint16_t prvTraceGetQueueNumberLow16(void* pvQueue)
328 {
329 	return TRACE_GET_LOW16(prvTraceGetQueueNumber(pvQueue));
330 }
331 
prvTraceGetQueueNumberHigh16(void * pvQueue)332 uint16_t prvTraceGetQueueNumberHigh16(void* pvQueue)
333 {
334 	return TRACE_GET_HIGH16(prvTraceGetQueueNumber(pvQueue));
335 }
336 
prvTraceSetQueueNumberLow16(void * pvQueue,uint16_t uiValue)337 void prvTraceSetQueueNumberLow16(void* pvQueue, uint16_t uiValue)
338 {
339 	vQueueSetQueueNumber(pvQueue, TRACE_SET_LOW16(prvTraceGetQueueNumber(pvQueue), uiValue));
340 }
341 
prvTraceSetQueueNumberHigh16(void * pvQueue,uint16_t uiValue)342 void prvTraceSetQueueNumberHigh16(void* pvQueue, uint16_t uiValue)
343 {
344 	vQueueSetQueueNumber(pvQueue, TRACE_SET_HIGH16(prvTraceGetQueueNumber(pvQueue), uiValue));
345 }
346 
347 #if (TRC_CFG_INCLUDE_TIMER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
348 
prvTraceGetTimerNumberLow16(void * pvTimer)349 uint16_t prvTraceGetTimerNumberLow16(void* pvTimer)
350 {
351 	return TRACE_GET_LOW16(uxTimerGetTimerNumber(pvTimer));
352 }
353 
prvTraceGetTimerNumberHigh16(void * pvTimer)354 uint16_t prvTraceGetTimerNumberHigh16(void* pvTimer)
355 {
356 	return TRACE_GET_HIGH16(uxTimerGetTimerNumber(pvTimer));
357 }
358 
prvTraceSetTimerNumberLow16(void * pvTimer,uint16_t uiValue)359 void prvTraceSetTimerNumberLow16(void* pvTimer, uint16_t uiValue)
360 {
361 	vTimerSetTimerNumber(pvTimer, TRACE_SET_LOW16(uxTimerGetTimerNumber(pvTimer), uiValue));
362 }
363 
prvTraceSetTimerNumberHigh16(void * pvTimer,uint16_t uiValue)364 void prvTraceSetTimerNumberHigh16(void* pvTimer, uint16_t uiValue)
365 {
366 	vTimerSetTimerNumber(pvTimer, TRACE_SET_HIGH16(uxTimerGetTimerNumber(pvTimer), uiValue));
367 }
368 
369 #endif
370 
371 #if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
372 
prvTraceGetEventGroupNumberLow16(void * pvEventGroup)373 uint16_t prvTraceGetEventGroupNumberLow16(void* pvEventGroup)
374 {
375 	return TRACE_GET_LOW16(uxEventGroupGetNumber(pvEventGroup));
376 }
377 
prvTraceGetEventGroupNumberHigh16(void * pvEventGroup)378 uint16_t prvTraceGetEventGroupNumberHigh16(void* pvEventGroup)
379 {
380 	return TRACE_GET_HIGH16(uxEventGroupGetNumber(pvEventGroup));
381 }
382 
prvTraceSetEventGroupNumberLow16(void * pvEventGroup,uint16_t uiValue)383 void prvTraceSetEventGroupNumberLow16(void* pvEventGroup, uint16_t uiValue)
384 {
385 	vEventGroupSetNumber(pvEventGroup, TRACE_SET_LOW16(uxEventGroupGetNumber(pvEventGroup), uiValue));
386 }
387 
prvTraceSetEventGroupNumberHigh16(void * pvEventGroup,uint16_t uiValue)388 void prvTraceSetEventGroupNumberHigh16(void* pvEventGroup, uint16_t uiValue)
389 {
390 	vEventGroupSetNumber(pvEventGroup, TRACE_SET_HIGH16(uxEventGroupGetNumber(pvEventGroup), uiValue));
391 }
392 
393 #endif
394 
395 #if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
396 
prvTraceGetStreamBufferNumberLow16(void * pvStreamBuffer)397 uint16_t prvTraceGetStreamBufferNumberLow16(void* pvStreamBuffer)
398 {
399 	return TRACE_GET_LOW16(uxStreamBufferGetStreamBufferNumber(pvStreamBuffer));
400 }
401 
prvTraceGetStreamBufferNumberHigh16(void * pvStreamBuffer)402 uint16_t prvTraceGetStreamBufferNumberHigh16(void* pvStreamBuffer)
403 {
404 	return TRACE_GET_HIGH16(uxStreamBufferGetStreamBufferNumber(pvStreamBuffer));
405 }
406 
prvTraceSetStreamBufferNumberLow16(void * pvStreamBuffer,uint16_t uiValue)407 void prvTraceSetStreamBufferNumberLow16(void* pvStreamBuffer, uint16_t uiValue)
408 {
409 	vStreamBufferSetStreamBufferNumber(pvStreamBuffer, TRACE_SET_LOW16(uxStreamBufferGetStreamBufferNumber(pvStreamBuffer), uiValue));
410 }
411 
prvTraceSetStreamBufferNumberHigh16(void * pvStreamBuffer,uint16_t uiValue)412 void prvTraceSetStreamBufferNumberHigh16(void* pvStreamBuffer, uint16_t uiValue)
413 {
414 	vStreamBufferSetStreamBufferNumber(pvStreamBuffer, TRACE_SET_HIGH16(uxStreamBufferGetStreamBufferNumber(pvStreamBuffer), uiValue));
415 }
416 
417 #endif
418 
419 static TraceKernelPortTaskHandle_t xTzCtrlHandle = 0; /* TzCtrl task TCB */
420 
421 /* Internal flag to tell the context of tracePEND_FUNC_CALL_FROM_ISR */
422 int uiInEventGroupSetBitsFromISR = 0;
423 
424 /**
425  * @internal Class reference table
426  */
427 traceObjectClass TraceQueueClassTable[5] = {
428 	TRACE_CLASS_QUEUE,
429 	TRACE_CLASS_MUTEX,
430 	TRACE_CLASS_SEMAPHORE,
431 	TRACE_CLASS_SEMAPHORE,
432 	TRACE_CLASS_MUTEX
433 };
434 
435 #if (TRC_CFG_SCHEDULING_ONLY == 0)
436 
vTraceSetQueueName(void * pvQueue,const char * szName)437 void vTraceSetQueueName(void* pvQueue, const char* szName)
438 {
439 	prvTraceSetObjectName(TRACE_CLASS_QUEUE, TRACE_GET_OBJECT_NUMBER(QUEUE, pvQueue), szName);
440 }
441 
vTraceSetSemaphoreName(void * pvSemaphore,const char * szName)442 void vTraceSetSemaphoreName(void* pvSemaphore, const char* szName)
443 {
444 	prvTraceSetObjectName(TRACE_CLASS_SEMAPHORE, TRACE_GET_OBJECT_NUMBER(QUEUE, pvSemaphore), szName);
445 }
446 
vTraceSetMutexName(void * pvMutex,const char * szName)447 void vTraceSetMutexName(void* pvMutex, const char* szName)
448 {
449 	prvTraceSetObjectName(TRACE_CLASS_MUTEX, TRACE_GET_OBJECT_NUMBER(QUEUE, pvMutex), szName);
450 }
451 
452 #if (TRC_CFG_INCLUDE_EVENT_GROUP_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_8_X_X)
453 
vTraceSetEventGroupName(void * pvEventGroup,const char * szName)454 void vTraceSetEventGroupName(void* pvEventGroup, const char* szName)
455 {
456 	prvTraceSetObjectName(TRACE_CLASS_EVENTGROUP, TRACE_GET_OBJECT_NUMBER(EVENTGROUP, pvEventGroup), szName);
457 }
458 
459 #endif
460 
461 #if (TRC_CFG_INCLUDE_STREAM_BUFFER_EVENTS == 1 && TRC_CFG_FREERTOS_VERSION >= TRC_FREERTOS_VERSION_10_0_0)
462 
vTraceSetStreamBufferName(void * pvStreamBuffer,const char * szName)463 void vTraceSetStreamBufferName(void* pvStreamBuffer, const char* szName)
464 {
465 	prvTraceSetObjectName(TRACE_CLASS_STREAMBUFFER, TRACE_GET_OBJECT_NUMBER(STREAMBUFFER, pvStreamBuffer), szName);
466 }
467 
vTraceSetMessageBufferName(void * pvStreamBuffer,const char * szName)468 void vTraceSetMessageBufferName(void* pvStreamBuffer, const char* szName)
469 {
470 	prvTraceSetObjectName(TRACE_CLASS_MESSAGEBUFFER, TRACE_GET_OBJECT_NUMBER(STREAMBUFFER, pvStreamBuffer), szName);
471 }
472 
473 #endif
474 
475 #endif
476 
prvTraceGetCurrentTaskHandle()477 void* prvTraceGetCurrentTaskHandle()
478 {
479 	return xTaskGetCurrentTaskHandle();
480 }
481 
xTraceKernelPortInitialize(TraceKernelPortDataBuffer_t * pxBuffer)482 traceResult xTraceKernelPortInitialize(TraceKernelPortDataBuffer_t* pxBuffer)
483 {
484 	(void)pxBuffer;
485 
486 	return TRC_SUCCESS;
487 }
488 
xTraceKernelPortEnable(void)489 traceResult xTraceKernelPortEnable(void)
490 {
491 #if defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0)
492 
493 	if (xTzCtrlHandle == 0)
494 	{
495 #if defined(configSUPPORT_STATIC_ALLOCATION) && (configSUPPORT_STATIC_ALLOCATION == 1)
496 
497 		xTzCtrlHandle = xTaskCreateStatic(TzCtrl, STRING_CAST("TzCtrl"), TRC_CFG_CTRL_TASK_STACK_SIZE, 0, TRC_CFG_CTRL_TASK_PRIORITY, stackTzCtrl, &tcbTzCtrl);
498 
499 #else
500 
501 		xTaskCreate(TzCtrl, STRING_CAST("TzCtrl"), TRC_CFG_CTRL_TASK_STACK_SIZE, 0, TRC_CFG_CTRL_TASK_PRIORITY, &xTzCtrlHandle);
502 
503 #endif
504 	}
505 
506 #else
507 
508 	(void)xTzCtrlHandle;
509 
510 #endif
511 
512 	return TRC_SUCCESS;
513 }
514 
515 #if defined(TRC_CFG_ENABLE_STACK_MONITOR) && (TRC_CFG_ENABLE_STACK_MONITOR == 1) && (TRC_CFG_SCHEDULING_ONLY == 0)
516 
portTASK_FUNCTION(TzCtrl,pvParameters)517 static portTASK_FUNCTION(TzCtrl, pvParameters)
518 {
519 	(void)pvParameters;
520 
521 	while (1)
522 	{
523 		if (xTraceIsRecorderEnabled())
524 		{
525 			prvReportStackUsage();
526 		}
527 
528 		vTaskDelay(TRC_CFG_CTRL_TASK_DELAY);
529 	}
530 }
531 
532 #endif
533 
xTraceKernelPortInitObjectPropertyTable()534 traceResult xTraceKernelPortInitObjectPropertyTable()
535 {
536 	RecorderDataPtr->ObjectPropertyTable.NumberOfObjectClasses = TRACE_NCLASSES;
537 	RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[0] = TRC_CFG_NQUEUE;
538 	RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[1] = TRC_CFG_NSEMAPHORE;
539 	RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[2] = TRC_CFG_NMUTEX;
540 	RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[3] = TRC_CFG_NTASK;
541 	RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[4] = TRC_CFG_NISR;
542 	RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[5] = TRC_CFG_NTIMER;
543 	RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[6] = TRC_CFG_NEVENTGROUP;
544 	RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[7] = TRC_CFG_NSTREAMBUFFER;
545 	RecorderDataPtr->ObjectPropertyTable.NumberOfObjectsPerClass[8] = TRC_CFG_NMESSAGEBUFFER;
546 	RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[0] = TRC_CFG_NAME_LEN_QUEUE;
547 	RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[1] = TRC_CFG_NAME_LEN_SEMAPHORE;
548 	RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[2] = TRC_CFG_NAME_LEN_MUTEX;
549 	RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[3] = TRC_CFG_NAME_LEN_TASK;
550 	RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[4] = TRC_CFG_NAME_LEN_ISR;
551 	RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[5] = TRC_CFG_NAME_LEN_TIMER;
552 	RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[6] = TRC_CFG_NAME_LEN_EVENTGROUP;
553 	RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[7] = TRC_CFG_NAME_LEN_STREAMBUFFER;
554 	RecorderDataPtr->ObjectPropertyTable.NameLengthPerClass[8] = TRC_CFG_NAME_LEN_MESSAGEBUFFER;
555 	RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[0] = PropertyTableSizeQueue;
556 	RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[1] = PropertyTableSizeSemaphore;
557 	RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[2] = PropertyTableSizeMutex;
558 	RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[3] = PropertyTableSizeTask;
559 	RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[4] = PropertyTableSizeISR;
560 	RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[5] = PropertyTableSizeTimer;
561 	RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[6] = PropertyTableSizeEventGroup;
562 	RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[7] = PropertyTableSizeStreamBuffer;
563 	RecorderDataPtr->ObjectPropertyTable.TotalPropertyBytesPerClass[8] = PropertyTableSizeMessageBuffer;
564 	RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[0] = StartIndexQueue;
565 	RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[1] = StartIndexSemaphore;
566 	RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[2] = StartIndexMutex;
567 	RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[3] = StartIndexTask;
568 	RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[4] = StartIndexISR;
569 	RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[5] = StartIndexTimer;
570 	RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[6] = StartIndexEventGroup;
571 	RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[7] = StartIndexStreamBuffer;
572 	RecorderDataPtr->ObjectPropertyTable.StartIndexOfClass[8] = StartIndexMessageBuffer;
573 	RecorderDataPtr->ObjectPropertyTable.ObjectPropertyTableSizeInBytes = TRACE_OBJECT_TABLE_SIZE;
574 
575 	return TRC_SUCCESS;
576 }
577 
xTraceKernelPortInitObjectHandleStack()578 traceResult xTraceKernelPortInitObjectHandleStack()
579 {
580 	uint32_t i = 0;
581 
582 	objectHandleStacks.indexOfNextAvailableHandle[0] = objectHandleStacks.lowestIndexOfClass[0] = 0;
583 	objectHandleStacks.indexOfNextAvailableHandle[1] = objectHandleStacks.lowestIndexOfClass[1] = (TRC_CFG_NQUEUE);
584 	objectHandleStacks.indexOfNextAvailableHandle[2] = objectHandleStacks.lowestIndexOfClass[2] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE);
585 	objectHandleStacks.indexOfNextAvailableHandle[3] = objectHandleStacks.lowestIndexOfClass[3] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX);
586 	objectHandleStacks.indexOfNextAvailableHandle[4] = objectHandleStacks.lowestIndexOfClass[4] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK);
587 	objectHandleStacks.indexOfNextAvailableHandle[5] = objectHandleStacks.lowestIndexOfClass[5] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR);
588 	objectHandleStacks.indexOfNextAvailableHandle[6] = objectHandleStacks.lowestIndexOfClass[6] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER);
589 	objectHandleStacks.indexOfNextAvailableHandle[7] = objectHandleStacks.lowestIndexOfClass[7] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP);
590 	objectHandleStacks.indexOfNextAvailableHandle[8] = objectHandleStacks.lowestIndexOfClass[8] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP) + (TRC_CFG_NSTREAMBUFFER);
591 
592 	objectHandleStacks.highestIndexOfClass[0] = (TRC_CFG_NQUEUE) - 1;
593 	objectHandleStacks.highestIndexOfClass[1] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) - 1;
594 	objectHandleStacks.highestIndexOfClass[2] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) - 1;
595 	objectHandleStacks.highestIndexOfClass[3] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) - 1;
596 	objectHandleStacks.highestIndexOfClass[4] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) - 1;
597 	objectHandleStacks.highestIndexOfClass[5] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) - 1;
598 	objectHandleStacks.highestIndexOfClass[6] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP) - 1;
599 	objectHandleStacks.highestIndexOfClass[7] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP) + (TRC_CFG_NSTREAMBUFFER) - 1;
600 	objectHandleStacks.highestIndexOfClass[8] = (TRC_CFG_NQUEUE) + (TRC_CFG_NSEMAPHORE) + (TRC_CFG_NMUTEX) + (TRC_CFG_NTASK) + (TRC_CFG_NISR) + (TRC_CFG_NTIMER) + (TRC_CFG_NEVENTGROUP) + (TRC_CFG_NSTREAMBUFFER) + (TRC_CFG_NMESSAGEBUFFER) - 1;
601 
602 	for (i = 0; i < TRACE_NCLASSES; i++)
603 	{
604 		objectHandleStacks.handleCountWaterMarksOfClass[i] = 0;
605 	}
606 
607 	for (i = 0; i < TRACE_KERNEL_OBJECT_COUNT; i++)
608 	{
609 		objectHandleStacks.objectHandles[i] = 0;
610 	}
611 
612 	return TRC_SUCCESS;
613 }
614 
pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass)615 const char* pszTraceGetErrorNotEnoughHandles(traceObjectClass objectclass)
616 {
617 	switch(objectclass)
618 	{
619 	case TRACE_CLASS_TASK:
620 		return "Not enough TASK handles - increase TRC_CFG_NTASK in trcSnapshotConfig.h";
621 	case TRACE_CLASS_ISR:
622 		return "Not enough ISR handles - increase TRC_CFG_NISR in trcSnapshotConfig.h";
623 	case TRACE_CLASS_SEMAPHORE:
624 		return "Not enough SEMAPHORE handles - increase TRC_CFG_NSEMAPHORE in trcSnapshotConfig.h";
625 	case TRACE_CLASS_MUTEX:
626 		return "Not enough MUTEX handles - increase TRC_CFG_NMUTEX in trcSnapshotConfig.h";
627 	case TRACE_CLASS_QUEUE:
628 		return "Not enough QUEUE handles - increase TRC_CFG_NQUEUE in trcSnapshotConfig.h";
629 	case TRACE_CLASS_TIMER:
630 		return "Not enough TIMER handles - increase TRC_CFG_NTIMER in trcSnapshotConfig.h";
631 	case TRACE_CLASS_EVENTGROUP:
632 		return "Not enough EVENTGROUP handles - increase TRC_CFG_NEVENTGROUP in trcSnapshotConfig.h";
633 	case TRACE_CLASS_STREAMBUFFER:
634 		return "Not enough STREAMBUFFER handles - increase TRC_CFG_NSTREAMBUFFER in trcSnapshotConfig.h";
635 	case TRACE_CLASS_MESSAGEBUFFER:
636 		return "Not enough MESSAGEBUFFER handles - increase TRC_CFG_NMESSAGEBUFFER in trcSnapshotConfig.h";
637 	default:
638 		return "pszTraceGetErrorHandles: Invalid objectclass!";
639 	}
640 }
641 
642 #endif
643 
644 #endif
645